SQLmap is an open-source command-line tool that automates the detection and exploitation of SQL injection flaws. In a penetration test, its real value is validation: confirming that a parameter you suspect is injectable, identifying the database engine, and proving impact with the least data possible. This SQLmap tutorial walks through installation, the options you will actually use, safe testing settings, and how to report and fix what you find.
Scope reminder: every command below targets a lab host (lab.local). Only run SQLmap against systems you own or are explicitly authorized to test.
Table of Contents
- What SQLmap Does
- Installing SQLmap
- Validate Manually First
- Basic Usage: GET, POST and Request Files
- Injection Techniques (BEUSTQ)
- Level, Risk and Safe Testing
- Enumeration with Minimal Impact
- Tamper Scripts and WAFs
- Troubleshooting
- Reporting the Finding
- Remediation
- FAQ
What SQLmap Does
SQL injection happens when an application builds a database query by concatenating untrusted input instead of using parameterized queries. If you need a refresher on the vulnerability itself, read our SQL injection guide first. SQLmap automates the repetitive part of testing that flaw. It can:
- Detect whether a parameter (GET, POST, cookie, header or JSON value) is injectable
- Fingerprint the back-end DBMS (MySQL, PostgreSQL, Microsoft SQL Server, Oracle, SQLite and others)
- Enumerate the current user, database, privileges, tables and columns
- Retrieve limited data to prove impact
- Save a session so repeated runs do not re-send every payload
It does not replace understanding. SQLmap tells you that something is injectable; you still have to explain why and what it means for the business.
Installing SQLmap
SQLmap is written in Python and runs on Python 3. It ships with Kali Linux and Parrot OS. On Debian-based systems:
sudo apt update && sudo apt install sqlmap
sqlmap --version
To always run the latest development version, clone the official repository:
git clone --depth 1 https://github.com/sqlmapproject/sqlmap.git sqlmap-dev
python3 sqlmap-dev/sqlmap.py --version
Use sqlmap -h for the common options and sqlmap -hh for the full list.
Validate Manually First
Before launching an automated scan, look at the request yourself, usually in an intercepting proxy such as Burp Suite. Answer these questions:
- Which parameter is likely to reach the database?
- Is the value numeric (
id=7) or a string (name=alice)? - Does a single quote change the response, cause an error, or change the content length?
- Do
id=7 AND 1=1andid=7 AND 1=2return different pages? - Is the endpoint safe to test (read-only search) or dangerous (delete, transfer, update)?
This tells you which parameter to point SQLmap at with -p, and keeps your scan short and in scope.
Basic Usage: GET, POST and Request Files
Testing a GET parameter
sqlmap -u "http://lab.local/item.php?id=1" -p id --batch
-usets the target URL.-p idlimits testing to theidparameter.--batchaccepts default answers so the run is non-interactive. Review the defaults before using it on a real engagement.
Testing a POST body
sqlmap -u "http://lab.local/login.php" --data "user=test&pass=test" -p user
Using a saved request file (recommended)
The most reliable method is to save the raw request from your proxy (in Burp: right-click → Copy to file) and pass it with -r. Cookies, headers, CSRF tokens and the body are preserved exactly:
sqlmap -r search-request.txt -p q --batch
You can also mark the exact injection point inside the request file with an asterisk, for example {"q":"laptop*"} in a JSON body.
Authenticated testing
sqlmap -u "http://lab.local/account?id=5" --cookie "PHPSESSID=abc123" -p id
Watch out for endpoints such as logout that would kill your session mid-scan.
Injection Techniques (BEUSTQ)
The --technique option controls which methods SQLmap tries. The default is all of them:
| Letter | Technique | How it works |
|---|---|---|
| B | Boolean-based blind | Compares true/false page responses |
| E | Error-based | Extracts data through database error messages |
| U | UNION query-based | Appends a UNION SELECT to return data in the page |
| S | Stacked queries | Executes additional statements after a semicolon |
| T | Time-based blind | Infers data from response delays |
| Q | Inline queries | Uses subqueries embedded in the original query |
If you already know the DBMS and technique from manual testing, narrow the scan to reduce noise:
sqlmap -r req.txt -p id --dbms=mysql --technique=BU
Stacked queries can execute data-modifying statements. Exclude S unless the rules of engagement allow it.
Level, Risk and Safe Testing
--level(1–5, default 1): how many payloads and which injection points are tested. Level 2 adds cookies; level 3 adds the User-Agent and Referer headers.--risk(1–3, default 1): how dangerous the payloads are. Risk 2 adds heavy time-based queries; risk 3 adds OR-based payloads that can change many rows if they land in an UPDATE or DELETE statement.
Start with the defaults and raise them only with a reason. Other options that keep a test controlled:
sqlmap -r req.txt -p id --threads 1 --delay 1 --timeout 15 --proxy http://127.0.0.1:8080
--threadsand--delaylimit load on fragile applications.--proxyroutes traffic through Burp so you have evidence of every request.--flush-sessionclears cached results when the target has changed.
Enumeration with Minimal Impact
Once a parameter is confirmed, prove impact with the smallest amount of data:
sqlmap -r req.txt -p id --current-user --current-db --is-dba
sqlmap -r req.txt -p id --dbs
sqlmap -r req.txt -p id -D shop --tables
sqlmap -r req.txt -p id -D shop -T users --columns
sqlmap -r req.txt -p id -D shop -T users -C id,username --start 1 --stop 3 --dump
Listing the current user and database names, or counting rows with --count, is usually enough to demonstrate risk. Avoid dumping full tables of personal data or password hashes on client systems unless the engagement explicitly requires it. Options such as --os-shell and --file-write move from validation to exploitation and should only be used in labs or with written approval.
Tamper Scripts and WAFs
When a web application firewall blocks payloads, tamper scripts transform them, for example by changing spacing or encoding:
sqlmap --list-tampers
sqlmap -r req.txt -p id --tamper=space2comment,between --random-agent
A WAF bypass is itself a finding worth reporting, but the root cause is still the unparameterized query.
Troubleshooting
- “All tested parameters do not appear to be injectable”: confirm the parameter with
-p, increase--level/--riskone step at a time, or provide a request file so cookies and tokens are correct. - False positives on time-based tests: the target may simply be slow. Increase
--time-secand re-run with--threads 1. - Session expires mid-scan: refresh the cookie and use
--safe-urlwith--safe-freqto keep it alive. - Stale results: use
--flush-session. Use-v 3to see the payloads being sent.
Reporting the Finding
A useful SQL injection finding includes:
- The affected endpoint, HTTP method and vulnerable parameter
- The DBMS and injection technique confirmed
- A minimal reproduction (the request plus the SQLmap command used)
- The proven impact, such as the database user, privileges and accessible schemas
- Severity reasoning and a clear remediation
Do not paste extracted personal data into the report. Redacted samples or row counts are enough.
Remediation
The fix belongs in the code, not in the WAF:
- Use parameterized queries or prepared statements for every database call
- Use an ORM or stored procedures that do not concatenate input
- Run the application with a least-privileged database account
- Return generic error messages and log the details server-side
- Add allow-list validation for values such as sort columns and table names, which cannot be parameterized
The OWASP SQL Injection Prevention Cheat Sheet covers each defense in detail. Injection is also part of the OWASP Top 10.
FAQ
Is SQLmap legal to use?
The tool is legal; using it against systems without permission is not. Practice on intentionally vulnerable labs such as DVWA, OWASP Juice Shop or Hack The Box machines.
What is the difference between –level and –risk?
--level controls how many places and payloads are tested; --risk controls how dangerous the payloads are. Raise level to find harder injection points, and raise risk only when you accept the chance of modifying data.
Should I use –batch on a real engagement?
It is convenient for labs. On client systems, answering prompts yourself avoids accepting defaults you did not intend.
Conclusion
SQLmap is fastest when you already understand the request: confirm the injection manually, point SQLmap at a single parameter with a request file, keep level and risk low, and prove impact with the least data possible. Next, sharpen your discovery workflow with FFUF for web fuzzing to find more endpoints worth testing.
References
- sqlmap.org — official project site
- SQLmap usage wiki
- OWASP: SQL Injection