SQLMap is an open-source Python tool developed by Bernardo Damele A.G. and Miroslav Stampar that automates detecting and exploiting SQL injection (SQLi), and taking over database servers. Where manual SQL injection demands endless payload tweaking, response-diff watching, and per-DBMS syntax juggling, SQLMap automates the whole thing. It auto-fingerprints major DBMSes — MySQL / PostgreSQL / Microsoft SQL Server / Oracle / SQLite — finds the injection point, extracts data, and, given the right conditions, even grabs an OS shell. This article assumes the theory in the SQL injection article and focuses on how SQLMap is actually used (see that article for how SQLi itself works).
What SQLMap is — automating manual SQLi #
The SQL injection article walks through the process a human builds by hand — from injections like ' OR 1=1 to working out a UNION's column count to extracting one bit at a time with blind techniques. SQLMap is that whole flow turned into an engine. Give it one potentially injectable parameter and SQLMap tries multiple techniques in turn, finds the one that works, identifies the back-end DBMS, and from there automatically pulls out databases, tables, columns, and rows.
| By hand (sql-injection article) | Automated by SQLMap |
|---|---|
| Finding the injection point (quotes, OR 1=1) | Automatically tries multiple techniques and decides |
| Guessing the DBMS (error text, function diffs) | --dbms hint or auto fingerprinting |
| Working out UNION column count by hand | Auto-tunes the UNION technique |
| Extracting one char at a time blind | Automates bit extraction via binary search |
| Formatting the pulled data by hand | Auto-dumps and saves it as a table |
What SQLMap tries is the six families denoted by --technique=BEUSTQ — Boolean blind / Error-based / UNION / Stacked queries / Time-based blind / inline Query. The families covered in the SQL injection article map directly to a single letter of that flag.
SQLMap stores its results (detected injection points, extracted data) in a dedicated output directory. Re-run it against the same target and it resumes the previous session, reusing what it already learned, so you never have to scan from scratch. That mechanism is also what lets you pause and resume a long blind extraction.
Legal and ethical considerations — --dump exfiltrates real data #
SQLMap is not merely a "detection tool." --dump actually exfiltrates real user records, password hashes, and personal data from the server, and --os-shell executes arbitrary OS commands on the DB server. Technically that is a complete attack, and aimed at someone else's system without permission it is a serious crime — data theft and tampering, and unauthorized access under Japan's Unauthorised Computer Access Act and its equivalents elsewhere.
- Apps you own or administer — your own web app, a VPS you pay for, an isolated test environment.
- Targets you have explicit written permission for — a pentest or vulnerability-assessment contract where the scope (target hosts, period, permitted operations) is documented.
- Legitimate learning platforms — DVWA, Hack The Box (HTB), TryHackMe (THM), and other labs where the operator permits attacks.
--dump and --os-shell are not "let me just try it" operations. The moment extracted data lands in memory or on disk, data theft can be established even if you never misuse it. Even in an assessment, always confirm your authorized target and scope first.
⚠️ The more intrusive the operation, the more clearly it is an "attack." Enumeration (
--dbs, etc.) is one thing, but--dump-all/--os-shell/--file-writedirectly cause data retrieval, tampering, and code execution. Never perform anything outside your scope.
Target specification — what you hand it as the injection point #
The first thing you tell SQLMap is "which request, which parameter, do I test." The most basic way is to pass a URL with -u (= --url).
$ sqlmap -u "http://site/item.php?id=1" --batch --dbs
# -u target URL (contains the injection point)
# --batch auto-answer prompts with defaults (non-interactive)
# --dbs after detection, retrieve the list of databasesBeyond a GET URL, the practical move is feeding in a raw HTTP request file saved from Burp. Because it reproduces cookies, headers, and the POST body wholesale, it is strong against post-auth pages and complex requests.
| Input option | Meaning |
|---|---|
-u "URL" / --url | Specify the target URL directly |
-r req.txt | Load a saved HTTP request (Burp, etc.) |
--data="id=1&name=test" | Specify a POST body (becomes POST automatically) |
-p id | Limit which parameter is tested |
--cookie="..." | Attach cookies (keep a session) |
-H "..." / --headers="..." | Attach arbitrary headers |
--method=POST | State the HTTP method explicitly |
--forms | Parse and test the forms on the page |
--crawl=2 | Crawl the site to depth 2 to find injection points |
$ sqlmap -r req.txt -p id --batch
# -r req.txt read a raw request saved from Burp etc.
# -p id narrow to id even if many params exist
# cookies and headers are taken straight from req.txtIf you already know the injection point, narrowing to one target like -r req.txt -p id is faster and quieter. --forms and --crawl widen the search but fire a lot of requests, so watch your scope and load.
Detection tuning — level / risk / technique / batch #
By default SQLMap tests conservatively (to avoid false positives and load). --level and --risk are what raise detection power, while --technique and --dbms narrow it.
| Option | Range / value | Meaning |
|---|---|---|
--level | 1–5 (default 1) | Where and how much to test. Higher reaches headers and cookies |
--risk | 1–3 (default 1) | How risky the tests are. Higher uses heavy / side-effecting payloads |
--technique | BEUSTQ | Limit which techniques are used (B/E/U/S/T/Q) |
--dbms | e.g. mysql | Hint/force the DBMS to skip fingerprinting |
--batch | — | Auto-answer every prompt with defaults (non-interactive) |
Raising --level / --risk improves the detection rate but also increases request count and side-effect risk. The convention is to try defaults first and step them up only when nothing lands.
$ sqlmap -u "http://site/item.php?id=1" --level=5 --risk=3 --batch
# --level=5 test the most places, including headers and cookies
# --risk=3 allow heavy, side-effecting payloads
# for surfacing stubborn injection points defaults miss--risk=3 includes payloads that can change data. Don't raise it casually on production or where your authorization is vague. If you know the DBMS, specifying it like --dbms=mysql skips irrelevant payloads and makes the run faster and quieter.
Enumeration and dumping — DB → tables → columns → data #
Once the injection point is confirmed, you simply drill down in stages. SQLMap's enumeration proceeds by combining "flags that grab the big picture" with "selectors that narrow the scope."
--dbs retrieves every DB name. --current-db checks only the connected DB.-D appdb --tables enumerates the tables in the target DB.-D appdb -T users --columns reveals the column layout of the target table.-D appdb -T users --dump pulls the row data. -C narrows the columns.| Enumeration flag | What it retrieves |
|---|---|
--dbs | Every database name |
--current-db / --current-user | The connected DB / DB user |
--is-dba | Whether the current user is a DBA |
--users / --passwords | DB accounts / their password hashes |
--tables / --columns | Lists of tables / columns |
--dump / --dump-all | Extract the targeted data / data from all DBs |
-D / -T / -C | Limit scope to a DB / table / column |
$ sqlmap -r req.txt -p id --batch -D appdb -T users --dump
# -D appdb -T users limit to the users table in appdb
# --dump extract its rows, display and save them
# add -C user,password to narrow the columns tooWhat --dump returns is real users' emails, password hashes, and personal data themselves. --dump-all targets every DB, so the blast radius is orders of magnitude larger. Outside a test lab, scope strictly with -D / -T / -C to only the authorized tables.
Takeover and evasion — grabbing a shell and bypassing WAFs #
When the conditions line up (privileges, stacked-query support, a writable destination), SQLMap can go beyond data extraction to operating the DB server itself. These are its most intrusive and dangerous features and must never be used outside scope.
| Takeover | What it can do | Danger |
|---|---|---|
--os-shell | Obtain an interactive OS shell on the DB server | Critical |
--sql-shell | Run arbitrary SQL interactively | High |
--file-read=/etc/passwd | Read a file on the server | High |
--file-write=local --file-dest=/var/www/shell.php | Write a local file onto the server | Critical |
$ sqlmap -u "http://site/item.php?id=1" --os-shell
# --os-shell tries to establish an OS shell on the DB server via the injection
# on success you can run any OS command = full compromise
# --file-read / --file-write are also intrusive file-level opsWhen a WAF or IPS sits in between, SQLMap has evasion and network options. --tamper transforms payloads to dodge signature detection, and what it targets is the very WAF placed there as a defense against SQL injection.
| Evasion / network | Effect |
|---|---|
--random-agent | Randomize the User-Agent to hide the default fingerprint |
--proxy="http://127.0.0.1:8080" | Go through a proxy (pipe into Burp to observe/record) |
--tor | Send through the Tor network |
--tamper=space2comment | Transform payloads to dodge WAF signatures |
--threads=5 | Raise the number of parallel threads for speed |
A SQLMap scan is easy to detect: a burst of anomalous SQL payloads lines up in the access log, and the default User-Agent (sqlmap/x.x) is left behind. A WAF, rate limiting, and anomalous-query monitoring catch most of it. --random-agent / --tamper / --tor reduce the traces, but the premise of a legitimate assessment is that you operate within an authorized scope — leaving traces is not itself a problem.
Defense and its relation to the sql-injection article #
The fact that SQLMap "works" means a SQL injection vulnerability actually exists in that app. So the best countermeasure against SQLMap comes down to eradicating SQLi itself. The details belong to the SQL injection article; here we only line up each SQLMap feature against the corresponding defense.
| Defense | What it neutralizes in SQLMap |
|---|---|
| Prepared statements / parameterized queries | Prevents the injection from forming at all (root fix) |
| Least-privilege DB accounts | Limits the damage of --os-shell / --file-write / --dump-all |
| WAF | Blocks known payloads but can be evaded with --tamper |
| Input validation | Auxiliary. Insufficient alone, but one layer of defense in depth |
SQLMap does not create new vulnerabilities; it is a tool that mechanically and exhaustively pounds an existing hole called SQL injection. So the answer for defense is consistent — prevent injection with prepared statements, contain damage with least privilege, and defend in layers with a WAF and monitoring. Once you assume attackers will reach for SQLMap, you see how fatal it is that even a single place builds SQL by string concatenation. Learn the manual reasoning from the SQL injection article, and the reality of automating it here.