Recently, reading a post in
Sara Golemon 's blog about the
PHP security guide I took some minutes to read the mentioned security article and I almost fall of my chair while looking the example entitled
"Browsing the FileSystem" (retrieved at Wed Apr 11 05:47:32 UTC 2007) which features the following code.
PHP:
<?php
echo "<pre>\n";
if (ini_get('safe_mode'))
{
echo "[safe_mode enabled]\n\n";
}
else
{
echo "[safe_mode disabled]\n\n";
}
if (isset($_GET['dir']))
{
ls($_GET['dir']);
}
elseif (isset($_GET['file']))
{
cat($_GET['file']);
}
else
{
ls('/');
}
echo "</pre>\n";
function ls($dir)
{
$handle = dir($dir);
while ($filename = $handle->read())
{
$size = filesize("$dir$filename");
if (is_dir("$dir$filename"))
{
if (is_readable("$dir$filename"))
{
$line = str_pad($size, 15);
$line .= "<a href=\\\"{$_SERVER['PHP_SE LF']}?dir=$dir$filename/\\\">$filename/</a>";
}
else
{
$line = str_pad($size, 15);
$line .= "$filename/";
}
}
else
{
if (is_readable("$dir$filename"))
{
$line = str_pad($size, 15);
$line .= "<a href=\\\"{$_SERVER['PHP_SELF']}?file=$dir$filename\\\">$filename</a>";
}
else
{
$line = str_pad($size, 15);
$line .= $filename;
}
}
echo "$line\n";
}
$handle->close();
}
function cat($file)
{
ob_start();
readfile($file);
$contents = ob_get_contents();
ob_clean();
echo htmlentities($contents);
return true;
}
?>
Gotcha ?? , see the function ls() it uses PHP_SELF without any sanitization hence we can:
CODE:
http://example.com/script.php/%22%3E%3Cscript%3Ealert('xss')%3C/script%3E%3Cfoo
So, this guide comes with a free XSS hole
Nobody can claim to write perfect code, I expect applications (even my own apps) to have holes but I certainly expect security guides to be better reviewed. Please fix your broken guide. (s/PHP_SELF/SCRIPT_NAME/g) thanks.
Update: I have been pointed by the author of this guide that the mentioned code is supposed to be an attacker tool, what a surprise !! of course I know it **may** be, but that is no excuse to have buggy examples.
People uses security guides as a "good programming" example no ?... you will probably not believe me, but I have seen this very same code in real life only slightly modifed to browse a single directory-