But it needs something to expose bash to the outside world. Without mod_cgi (or the like) or sshd with a specific configuration, a vulnerable bash isn't going to be remotely exploitable.
sendmail = popen(sendmail_cmd, "w");
Which calls /bin/sh to execute sendmail_cmd. However, two things must also be true:1. /bin/sh is bash
2. PHP has set environment variables with user-provided data
#1 is often the case, but is much less common now than in the past.
#2 is not commonly the case, PHP does not even automatically create PHP variables from user-provided data anymore (because it is a terrible idea to put untrusted data into a trusted scope without sanitizing).
> sendmail = popen(sendmail_cmd, "w");
> Which calls /bin/sh to execute sendmail_cmd.
Are you sure? It looks like (at least by default) sendmail_cmd is a string constructed by putting sendmail_path (from php.ini) together with the various options passed to mail(). For most *NIX sendmail_path is going to be /usr/sbin/sendmail and so would execute /usr/sbin/sendmail -t -i [email protected] 'message string'
popen()'s man page says:
FILE *popen(const char *command, const char *type);
[..]
The command argument is a pointer to a null-terminated
string containing a shell command line. This command is
passed to /bin/sh using the -c flag
[..]
Which is where /bin/sh gets involved. PHP should be calling pipe/fork instead of popen IMO, I can't see the point in invoking a shell.Ideally there would be something like a popenve() to simplify the process of opening the pipe(s) and passing arguments and environment.
There are also various other variations on the popen() concept, like my own popen3() implementations in C[0] (note that I'm not the only person to write a popen3; Python, Ruby, and probably other languages have their own).
However, I mimicked the real popen(), and my implementation uses /bin/sh as well. It would be easy to make a version of popen3() that accepts argument and environment arrays, but it would still be insecure if the environment was set to the calling process's environ pointer[1], and/or the command to be executed was a /bin/bash script.
[0] https://gist.github.com/nitrogenlogic/1022231#file-popen3_20... [1] http://linux.die.net/man/7/environ