Skip to content

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 parameter
sqlmap -u 'http://target/vuln.php?id=1' --batch
# The usual starting point - a saved Burp request
sqlmap -r req.txt --batch
# Confirmed-and-escalate, in order
sqlmap -r req.txt --batch --dbs # list databases
sqlmap -r req.txt --batch -D prod -T users --dump # exfiltrate
sqlmap -r req.txt --batch --is-dba --os-shell # post-exploit

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

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.

The single most common cause of a “not injectable” result is a mis-specified request, not a patched target. Get the request right first.

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:

Terminal window
sqlmap 'http://target/?id=1' \
-H 'User-Agent: Mozilla/5.0 ...' -H 'Accept: ...' --compressed

Every header, cookie, and body the app expects comes along for free.

Terminal window
sqlmap -u 'http://target/vuln.php?id=1' # GET params inline
sqlmap 'http://target/' --data 'uid=1&name=test' # POST body (-p uid to narrow)
sqlmap -r req.txt # full Burp-saved request
  • -r req.txt is 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*'.

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.

Terminal window
--random-agent # swap SQLMap's giveaway default User-Agent for a real browser one

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

1. Detect sqlmap -r req.txt --batch
→ "sqlmap identified the following injection point(s)"
2. Recon --banner --current-user --current-db --is-dba
3. 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 - notably OR-based payloads, which can modify data on UPDATE/DELETE statements, so they’re off by default. Raise --risk for login forms where OR is 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.

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.

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.