Bypassing PHP PathInfo

30 November -0001

The pathinfo() built-in PHP function is often used by programmers to identify the types of files being specified in URLs. Pathinfo will do simple parsing of path and filenames and present an array of useful attributes such as the base name of the file specified or the file extension of the file specified. The following example is provided from the PHP.net website:

<?php
$path_parts = pathinfo('/www/htdocs/index.html');

echo $path_parts['dirname'], "\n";
echo $path_parts['basename'], "\n";
echo $path_parts['extension'], "\n";
echo $path_parts['filename'], "\n"; // since PHP 5.2.0
?>

Which produces the output:

/www/htdocs
index.html
html
index

As you can see this is very useful for identifying the types of files that are being requested. However, in many cases developers will use this information as authoritative, relying in pathinfo() to report accurately. Pathinfo's parsing can be easily bypassed by using the age old trick of appending extra dots and extensions to the filename.

Consider the following example. In the web directory we have two files - test.php and index.php. Test.php contains the following code:

<?php
$file = pathinfo($_GET['file']);
if (file_exists($file['basename'])) echo 'Found this file';
else echo 'Could not find this file';
?>

If we call the URL 'test.php?file=index.jpg' we get the handy output 'Could not find this file' and if we call 'test.php?file=index.php' we get 'Found this file.' Now, if we were to modify this code to check for valid image file extensions we might end up with something like:

<?php
$file = pathinfo($_GET['file']);
if ($file['extension'] == '.jpg') echo 'Valid image file!  ';
if (file_exists($file['basename'])) echo 'Found this file';
else echo 'Could not find this file';
?>

And then we call 'test.php?file=index.php.jpg' we understandably see 'Valid image file! Could not find this file.' So this could be used to screen out extension overloading.

However, if we append a null byte in our URL by requesting the URL 'test.php?file=index.php%00.jpg' we can easily evade the filter checking, resulting in the output 'Valid image file! Found this file.' This can be an extremely dangerous vulnerability because a developer using code of this style might think they have successfully limited files they are including to only files with image extensions when in fact attackers can bypass the filter and cause arbitrary file inclusion.