SQL Injection (SQLi)
Lab: DVWA
Scenario: SQL Injection
Difficulty: Beginner
Estimated Time: 30 minutes
Learning Objectives
By the end of this scenario, you will be able to:
- Identify SQL injection vulnerabilities in web applications
- Exploit basic SQL injection attacks
- Understand how SQL injection occurs at the code level
- Implement basic detection and prevention measures
- Recognize the impact of SQL injection on application security
Setup
Prerequisites
- DVWA lab running at CSN Labs
- Web browser (Chrome/Firefox recommended)
- [Optional] Burp Suite for advanced testing and request interception
Initial Configuration
- Log into DVWA using the default credentials
- Set security level to "Low" (this is important for learning)
- Navigate to "SQL Injection" module from the left sidebar
Scenario Story
You are testing a web application's user lookup functionality. The application allows users to search for other users by entering a User ID. The application appears to use a database to retrieve user information. Your goal is to understand if the application is vulnerable to SQL injection and how an attacker could exploit this vulnerability.
Step-by-Step Walkthrough
Step 1: Identify the Input Field
Navigate to the SQL Injection page and observe the user ID input field.
Expected Output: You should see a form with a text input asking for a User ID, typically with a submit button.
What to Observe:
- The input field accepts numeric values
- After submitting, the application displays user information
- Note the URL structure and any parameters
Step 2: Test Basic Injection
Enter the following in the User ID field:
1' OR '1'='1
Click "Submit".
Expected Output: The application should return all user records from the database, bypassing the intended query logic that should only return one user.
What Happened: The single quote (') closed the original query string, and OR '1'='1' added a condition that is always true, causing the WHERE clause to match all rows.
Step 3: Understand the Query
The vulnerable query likely looks like:
SELECT * FROM users WHERE id = '1' OR '1'='1'
The '1'='1' condition is always true, causing the WHERE clause to match all rows instead of filtering to a specific user.
Try This: Enter 1' OR '1'='1'-- (with double dash for comment) to see if it produces the same result.
Step 4: Extract Database Information
Try to extract the database version:
1' UNION SELECT NULL, version(), NULL--
Expected Output: You should see the database version information displayed along with user data.
Note: The number of NULLs must match the number of columns in the original SELECT statement. You may need to adjust this based on the table structure.
Why This Works
SQL injection occurs when user input is directly concatenated into SQL queries without proper sanitization. The application trusts user input and doesn't escape special characters like single quotes ('), allowing attackers to break out of the intended SQL syntax and inject malicious code.
Vulnerable Code Example:
$query = "SELECT * FROM users WHERE id = '" . $_GET['id'] . "'";
What's Wrong: The user input is directly inserted into the query string without validation or escaping.
Defender Notes
How to Detect
-
Monitor Application Logs: Look for unusual SQL query patterns
- Multiple queries in a single request
- Queries with syntax errors (often from injection attempts)
- Queries accessing tables not normally accessed by the application
-
Watch for Common Injection Patterns:
' OR '1'='1'--(SQL comment)' UNION SELECT'; DROP TABLE- Time-based delays:
' OR SLEEP(5)--
-
Set up WAF Rules: Configure Web Application Firewall rules to block suspicious SQL keywords in user input
-
Monitor Database Performance: Sudden spikes in query execution time or unusual query patterns
How to Prevent
-
Use Parameterized Queries (Prepared Statements): Always use prepared statements with parameter binding. This is the most effective defense.
Safe Code Example:
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$_GET['id']]); -
Input Validation: Validate and sanitize all user input
- Whitelist allowed characters for numeric IDs
- Reject input that contains SQL keywords or special characters
- Use type casting for numeric inputs
-
Least Privilege: Database user should have minimal required permissions
- Don't grant DROP, DELETE, or ALTER permissions unless absolutely necessary
- Use read-only database users for queries that only retrieve data
-
Error Handling: Don't expose database errors to users
- Log errors server-side
- Display generic error messages to users
- Never show SQL syntax errors or database structure information
-
Regular Security Audits: Use automated tools and manual code reviews to identify vulnerable code
Try These Variations
Easy
- Try different injection payloads:
1' OR '1'='1'--1' UNION SELECT NULL--1' OR 1=1#
Medium
- Attempt to extract database schema information:
- List all tables:
1' UNION SELECT table_name FROM information_schema.tables-- - Get column names:
1' UNION SELECT column_name FROM information_schema.columns WHERE table_name='users'--
- List all tables:
- Try to enumerate user credentials
- Attempt to extract sensitive data from other tables
Hard
- Attempt blind SQL injection (when errors aren't visible):
- Boolean-based:
1' AND 1=1--vs1' AND 1=2-- - Time-based:
1' OR SLEEP(5)--
- Boolean-based:
- Try to bypass WAF filters using encoding or obfuscation
- Attempt second-order SQL injection (stored and executed later)
Evidence Checklist
Capture screenshots of:
- Initial vulnerable input field
- Successful injection payload (
1' OR '1'='1) - Database response showing all records
- Database version extraction (if attempted)
- Burp Suite request/response (if used)
- Any error messages that reveal database structure
Next Steps
- Return to DVWA Lab Overview
- Try the next scenario: Reflected XSS
- Explore CSN Labs for more challenges
- Review the SQL Injection Playbook for advanced techniques