Fall to the NullByte

Posted by MahFreenAmeh on July 16, 2007, 7:43 a.m.

So, as many of you know, or may know, perhaps, Willhostforfood recently fell to what is known as null-byte injection. I'll explain what that is in a moment. Anyways, luckily, I figured eventually someone would do something like that to the site, so using null-byte injections myself, I decided to get the source for the pages just in case someone who hacked it decided to deface it… I know, this makes me out to be the hacker, but I did that so that the source would be readily available for the site owner if he wanted it.

Anyways, let's get to the more interesting part: stopping the nullbyte injections. There's plenty of ways. The most simple is as such:

Quote:

/*Filename has been put into $fname*/

$fname = str_replace('%'.'',$fname);

That cuts out all %'s from the filename. Why you do that, I'll go over in a minute. That's what most sites tend to do. Just as well, you can use these two functions that I just thought up:

Quote:

function nullcheck($str) {

$char = 1;

foreach(preg_split("//",$str) as $let) {

if(ord($let) == 0 && ($char > 0 && $char < strlen($str))) {

return $char;

}

$char++;

}

return false;

}

function nullcheckarr($str) {

$arr = array();

$char = 1;

foreach(preg_split("//",$str) as $let) {

if(ord($let) == 0 && ($char > 0 && $char < strlen($str))) {

$arr[] = $char;

}

$char++;

}

return ($arr)?$arr:false;

}

What these do is quite simple.

nullcheck() checks if there's an occurrence of the null byte anywhere between the beginning of the string (where there actually is a nullbyte by default,) and the end of the string (same.) If one is found, it returns the position of the nullbyte. So, assuming that, given the string "This is a ^string" and assuming that ^ is the nullbyte, nullcheck("This is a ^string") returns 11, whereas nullcheck("This is a string") returns false.

nullcheckarr() does the same thing, but returns an array of values corresponding to where each nullbyte is, excluding 0 and the end of it, so,

nullcheckarr("T^his^ is a ^string")

Returns an array with values as such:

Array: (

[0] => 1,

[1] => 5,

[2] => 12

)

Which can be iterated through using any method of looping, such as:

$nullarray = nullcheckarr("T^his^ is a ^string");

/*Method one: while()/do while() (same semantics, dfferent operating manner)*/

$i = 0;

while(++$i<=count($nullarray)) {

/* do something with $nullarray[$i]*/

}

/*Method two: for() */

for($i=0;$i<=count($nullarray);$i++) {

/* do something with $nullarray[$i]*/

}

/*Method three: foreach()*/

foreach($nullarray as $null) {

/*do something with $null/*

}

As such, you can assess if there are any null bytes in the string, and if so, how many, and where they are.

Now, to explain the mechanics of null byte injection.

Null byte injection consists of naming a file, say,

xploit.php

To something like,

xploit.php%00.bar

What does this do? Usually, PHP will parse that as:

xploit.php END OF STRING. That is, it will see .bar at the end, and upload it as such, but because of the nullbyte between php and the ., that is the end of the string to it, which means that the file is really xploit.php, and will be parsed on the server side as such.

It's quite a famous exploit, and many sites have fallen prey to it. So, if someone tries to upload a file to your server, you should check to see if there's either a nullbyte in it somewhere using a function similar to the ones I made, or see if %00 exists in it. If so, don't upload it, or change the nullbyte/%00 to something that is NOT harmless.

I think that about covers it for now.

~MahFreenAmeh [Security Consultant]~

P.S.:

<img src="http://mfa.firephoenixnet.com/frac/500x500x10.png">

<img src="http://mfa.firephoenixnet.com/gs/500x500.png">

<img src="http://mfa.firephoenixnet.com/cs/500x500.png">

Diagonallychallenged,wearetheinsane!

Comments

s 17 years, 4 months ago

And a 100MB+ upload will probably stop me before I even notice that stuff

MahFreenAmeh 17 years, 4 months ago

Woorf. I forgot what I was giong to say. But yeah.

Haha. I tend to stay away from setting max_file_size via hidden, I usually like to just have one upload area, and set a default max_upload_size in php.ini. Just an idea for me.