DVWA - File inclusion
Starting the challenge
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 inclusion button on the left menu to access the challenge.
Low Level
Understanding the application
We reach a page allowing us to choose between three files.
If we select the first file we get our IP address.
The third file gives us even more information :
File 3
Welcome back admin
Your IP address is: 172.17.0.1
Your user-agent address is: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:67.0) Gecko/20100101 Firefox/67.0
You came from: http://localhost/vulnerabilities/fi/?page=include.php
I'm hosted at: localhost
What is interesting is the way the page seem to be loaded : with php includes.
If we look at the URLs they are constructed like this host?page=<filename>
:
- http://localhost/vulnerabilities/fi/?page=file1.php
- http://localhost/vulnerabilities/fi/?page=file2.php
- http://localhost/vulnerabilities/fi/?page=file3.php
Inclusion vulnerability
If the code uses PHP includes we might be able to trick the server into serving other files located on a server we control.
For instance if I set up a file index.php
with the following code on my server
<?php phpinfo() ?>
then the vulnerable site will load my index.php
file and execute my code which will display php information.
To do so I replace file1.php
by <my_url>
in the URL.
We can go further and upload a script that will let me run commands on the vulnerable server.
Vulnerable code
The code is very light :
<?php
// The page we wish to display
$file = $_GET[ 'page' ];
?>
It justs retrieves the content of the parameter page and loads it as a filepath. The problem here is that the user input is trusted not to go outside of the perimeter thought for the application.
If only files file1.php
, file2.php
and file3.php
should be readable by the user, the code should implement a whitelist to only allow those files.
Moreover, the other files on the server can have specific permission sets disallowing the user www-data
from reading them (or listing the directories).
Medium level
In this level the previous attack does not work. It seems that the developer has implemented a system of regular expressions to validate the input passed in the page
parameter.
But it is difficult to think of everything. If we configure a burp intruder with the list of local file inclusions we can see that /etc/passwd
returns some information.
And there we managed to retrieve the list of users. If we can upload files we could upload our own php script and get a shell on the server.
Vulnerable code
The code strips http:
and relative paths ../
from the user’s input but fails to take into account absolute paths.
<?php
// The page we wish to display
$file = $_GET[ 'page' ];
// Input validation
$file = str_replace( array( "http://", "https://" ), "", $file );
$file = str_replace( array( "../", "..\"" ), "", $file );
?>
In addition to that, the server is misconfigured and allows any user to access sensitive files.
Remediation
The server should only serve files related to the website. The developper should implement a whitelist of files to display.
High level
In this level the direct file inclusion /etc/passwd
does not seem to work.
It might be that the developer implemented a control to ensure that the parameter starts with file
.
However there are techniques to bypass these kind of filters.
For instance we can try %00
or %0A
.
If we try the following URL we will dump the passwd file :
http://localhost/vulnerabilities/fi/?page=file1.php%0A/../../../../../../etc/passwd
You can learn more about null-byte injection here.
Vulnerable code
<?php
// The page we wish to display
$file = $_GET[ 'page' ];
// Input validation
if( !fnmatch( "file*", $file ) && $file != "include.php" ) {
// This isn't the page we want!
echo "ERROR: File not found!";
exit;
}
?>
Impossible level
The impossible level implements a whitelist :
<?php
// The page we wish to display
$file = $_GET[ 'page' ];
// Only allow include.php or file{1..3}.php
if( $file != "include.php" && $file != "file1.php" && $file != "file2.php" && $file != "file3.php" ) {
// This isn't the page we want!
echo "ERROR: File not found!";
exit;
}
?>