Wednesday, December 2, 2009

Case Study – Directory Traversal & Remote Code Execution Using /proc/self/environ

SkyHi @ Wednesday, December 02, 2009
Credits to Christian Busch for helping me out on this one. :)

Late last night, I was approached with an interesting case of a denial of service attack. And I mean it – no one was able to access the service – because all files were deleted. The client informed me that remote shell scripts were able to find their way onto the server.

The first step was obviously to restore the files on the server, which was trivial given that WHM made daily backups for him. Then the search for the shell scripts began. I identified a couple of them –

File found - backup.php (2463) - 03/06/2009
File found - shelld.php (23124) - 03/08/2009
File found - .php (96420) - 03/07/2009
File found - testa.php (85) - 03/08/2009
File found - test.php (38868) - 02/05/2009
File found - c.php (597944) - 02/25/2009

The files are zipped and downloadable. Be sure to manage your AV exclusions. :)

The file that requires some attention is testa.php.


$o = fopen("shelld.php","wb");fwrite($o,$aa);fclose($o); ?>

I shall cut the crap and go straight to the logs. You may download a copy of all the logs here. But let’s take a look at a sample line – - - [07/Mar/2009:23:36:02 +0000]
"GET /?p=../../../../../../../../../../../../../proc/self/environ HTTP/1.1"
200 15491 "-"

A directory traversal attack! I haven’t seen one like that in years! But this one is smart. For those who do not understand what that line in the logs mean - a user using the IP address visited the page


with the browser headers as PHP code.

Let’s take a look at the output of the GET URL –
Smart, eh?

Smart, eh? Click to enlarge.

It seems like the browser and PHP information are output.

Looking at some relevant PHP code –

$p = stripslashes($_REQUEST['p']);

“This” certainly needs to be changed. ;)

Let’s look at the query executed again. The null byte is used to ignore the “.php” extension and only include /proc/self/environ

What’s even smarter is this – because browser information is include’d, PHP code was used as the browser headers and was therefore included and parsed.

If you look further down the logs, you will realize that the C99 shell is also included from a certain URL –

Shells. Sea Shells. Remote Shells. Evil Shells.

Shells. Sea Shells. Remote Shells. Evil Shells.

Looks like someone set up a site just for this purpose.

There are other things probably worth mentioning, but I guess not this time. The things to take away would be –

1. Always sanitize parameters passed to functions like require’s, require_once’s, include’s, include_once’s, fopen’s, file_get_contents’, etc to prevent directory traversal
2. Using /proc/self/environ as an attack vector to execute PHP code remotely that is hardly ever published. I hope that this article provided you with some insights.
3. And to all the security researchers out there – You can now stop using the cat /etc/passwd POC and start using something like this. =)