Null byte injection in an upload form

Efuveo picture Efuveo · Feb 9, 2013 · Viewed 10.1k times · Source

I'm trying to reproduce the Null Byte Injection attack on an upload form. I have this code:

<?php
if(substr($_FILES['file']['name'], -3) != "php") { 
  if(move_uploaded_file($_FILES['file']['tmp_name'], $_FILES['file']['name']))
    echo '<b>File uploaded</b>';
  else
    echo '<b>Can not upload</b>';
}
else
  echo '<b>This is not a valid file/b>';
?>

I'm trying to upload a file named like this : file.php%00jpg so it will bypass the substr() and will be uploaded as file.php since move_uploaded_file() should stop at the null byte (%00).

The problem is that the uploaded file is not named file.php on the server but file.php%00jpg (which can be accessed by typing /file.php%2500jpg in the url bar).
It seems that move_uploaded_file() does not care about the null byte, so how does this works? Is it possible to upload a file with .php extension with my piece of code?

Thanks :).

Answer

Fabian Schmengler picture Fabian Schmengler · Feb 9, 2013

The HTML form urlencodes the file name to %2500 and PHP decodes it again to %00 (percent sign, zero, zero). There is no null byte in your test anywhere, you'd have to name the file with an actual null byte (not possible) or fiddle with the HTTP request manually instead of using the HTML form. Still, current PHP versions are not vulnerable to this attack, PHP internally boxes variables in a so called ZVal container and allows null bytes in the middle of a string without any effect.