Refer to the post start DVWA with Docker to learn how to start DVWA. I will mostly use Burp Suite to solve the challenges. To configure Burp suite refer to the post configure burp suite for DVWA. Click on the File upload button on the left menu to access the challenge.
We reach a page allowing us to upload an image.
If we choose an image an upload it the application returns the relative path to the uploaded image on the server : ../../hackable/uploads/coconuts.jpeg succesfully uploaded!
.
The image is transmitted in a POST request :
POST /vulnerabilities/upload/ HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:66.0) Gecko/20100101 Firefox/66.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://localhost/vulnerabilities/upload/
Content-Type: multipart/form-data; boundary=---------------------------57639004077907672938394449
Content-Length: 50688
Connection: close
Cookie: PHPSESSID=2qdgiu3g3iqib3k2ptd18rntl7; security=low
Upgrade-Insecure-Requests: 1
-----------------------------57639004077907672938394449
Content-Disposition: form-data; name="MAX_FILE_SIZE"
100000
-----------------------------57639004077907672938394449
Content-Disposition: form-data; name="uploaded"; filename="coconuts.jpeg"
Content-Type: image/jpeg
The idea behind an upload exploit is to manage to upload an executable file to the server and trick the server into executing it for us. In our case we suspect that there is little to no control over what's being transmitted. We know that the server uses PHP, so if we manage to upload a php file we can probably make the server execute our php code.
In our case, to verify our theory we craft a very simple file name phpinfo.php
with the following content:
<?php phpinfo() ?>
If we try to upload our file the server responds positively.
Now from the relative path given by the server we try to access our file to trigger its execution.
As we can see below, our attack was successful since the server displayed the results of the phpinfo()
command.
The issue here is that the server expects to receive images but never verifies that the user did send an image. There are multiple ways to ensure that an image is being sent by the user:
In this level the previous attack does not work. When we try to upload our php file the server throws an error saying that it only accepts PNG and JPEG files.
One way of verifying that a file is a PNG or JPEG is with the Content-Type
header.
When we sent the php file the following message was sent :
100000
-----------------------------35945180013209453201206516548
Content-Disposition: form-data; name="uploaded"; filename="phpinfo.php"
Content-Type: application/x-php
The browser told the server that the file type is application/x-php
. This line is probably filtered by the server.
If we use Burp Repeater to repeat our previous request and replace the content type with image/png
the server responds positively.
Now we can access our file to execute our code.
The problem here is that the verification lies on a property modifiable by the user : the Content Type.
// Is it an image?
if( ( $uploaded_type == "image/jpeg" || $uploaded_type == "image/png" ) &&
( $uploaded_size < 100000 ) ) {
The server should perform verifications on the file itself to ensure that it is indeed an image.
In this level the previous tricks do not work. The server throws the same error message as the medium
level.
The problem here is that the extension of the file is always checked.
There is no way to upload a file with an extension different from .png
or .jpg
.
What we have to do is exploit a fault in the php server to execute php code hidden in the EXIF data of the image file.
To do so we can either use a file prepared for us in IntruderPayloads images or we can create it ourselves with exiftool
.
The command to add some php code in the image myimage.jpg
is :
exiftool -DocumentName="<?php phpinfo(); __halt_compiler(); ?>" myimage.jpg
Here we add the code
<?php phpinfo(); __halt_compiler(); ?>
__halt_compiler()
halts the execution of the compiler, so any code located after will not be interpreted.
Let's upload our image now.
Everything goes well since it was a real image, with the right extension.
Now to exploit the vulnerability we need a way to give this file to the PHP interpreter.
To do so we use a file include exploit by navigating to the url localhost/vulnerabilities/fi/?page=file1.php%0A/../../../hackable/uploads/image.jpg
:
The impossible level protects itself by stripping metadata that could be interpreted.
// Strip any metadata, by re-encoding image (Note, using php-Imagick is recommended over php-GD)
if( $uploaded_type == 'image/jpeg' ) {
$img = imagecreatefromjpeg( $uploaded_tmp );
imagejpeg( $img, $temp_file, 100);
}
else {
$img = imagecreatefrompng( $uploaded_tmp );
imagepng( $img, $temp_file, 9);
}
imagedestroy( $img );