How to Use sqlmap: SQL Injection Testing Guide (2026)

Web Security
19 min read
How to Use sqlmap: SQL Injection Testing Guide (2026)
On this page
  1. What Is sqlmap?
  2. Install sqlmap in Under a Minute
  3. Your First Scan, Line by Line
  4. How to Read the Injection Point Summary
  5. From Injection Point to Data
  6. The Options That Actually Change Your Results
    1. -r: load a request from a file
    2. -p: name the parameter
    3. --level and --risk: leave them alone at first
    4. --tamper: when a filter mangles your payload
    5. --batch and the session file
    6. --threads: careful speed
  7. When sqlmap Says "Not Injectable" and You Know It Is
  8. Should You Use sqlmap in CTFs?
  9. Frequently Asked Questions
  10. Legal and Ethical Considerations
  11. Your Next Steps

Most people learn sqlmap backwards. They copy a command off a forum, point it at a URL, watch a wall of text scroll past, and end up with either a table dump they cannot explain or the message "all tested parameters do not appear to be injectable" on a page they are certain is broken. The tool is not the hard part. Reading what it tells you is. Before you run it against anything, find one injection by hand in HackerDNA's Query Quake lab so you know what sqlmap is automating.

sqlmap automates the tedious half of SQL injection: proving the flaw is real, fingerprinting the database, and pulling data out one character at a time. It does not find bugs you have not already suspected, and it is close to useless as a discovery scanner. This guide walks a real scan from the first request to the dumped table, explains every line of output that matters, and covers the situations where the right answer is to close the terminal. SQL injection remains one of the injection flaws tracked in the OWASP Top 10, which is exactly why this tool has stayed relevant since 2006.

TL;DR: sqlmap is an open source tool that detects and exploits SQL injection automatically. Point it at a parameter you already suspect with sqlmap -u "http://target.example/page?id=1" --batch, read the injection point summary it prints, then enumerate with --tables and --dump. Leave --level and --risk at their defaults until a scan comes back empty, and never run it against a target you do not have written permission to test.

What Is sqlmap?

sqlmap is an open source penetration testing tool that automates the detection and exploitation of SQL injection flaws. You give it a request with a parameter you control, and it works out whether that parameter reaches a SQL query, which technique will pull data back, which database engine is behind the application, and then extracts the contents.

It is written in Python, licensed under GPLv2, and ships pre-installed on Kali Linux. Version 1.10.9 recognizes 31 database engines, from the ones you expect (MySQL, PostgreSQL, Oracle, Microsoft SQL Server, SQLite) to a long tail almost nobody meets in the field (Mckoi, FrontBase, Raima, eXtremeDB). That breadth matters less than it sounds. In practice you will see MySQL, PostgreSQL, MSSQL, and SQLite over and over.

The important thing to understand before your first run is what sqlmap is not. It is not a web vulnerability scanner. It will not crawl an application and hand you a list of bugs. It tests the parameters you point it at, and if you have not done the reconnaissance to know which parameters are worth testing, you are just generating traffic. The underlying weakness it hunts is CWE-89: Improper Neutralization of Special Elements used in an SQL Command, which ranked third in MITRE's 2024 CWE Top 25 Most Dangerous Software Weaknesses with a score of 35.88.

If you have never seen the manual version of what this tool does, read the SQL injection tutorial first. sqlmap will make a lot more sense once you have typed ' OR 1=1 -- into a login box yourself and watched the query fall apart.

Install sqlmap in Under a Minute

On Kali Linux it is already there. Everywhere else, pick one:

# Kali Linux (already installed)
sqlmap --version

# pip, any OS with Python 3
pip install sqlmap

# from source, if you want to track development
git clone --depth 1 https://github.com/sqlmapproject/sqlmap.git
cd sqlmap
python3 sqlmap.py --version

The pip package and the git clone are the same project; the clone just gives you the newest commits and lets you read the tamper scripts. sqlmap runs on Python 2.7 and 3.x, though there is no reason to be on 2.7 in 2026. If you install from source, note the command becomes python3 sqlmap.py rather than sqlmap, which trips up half the people following a tutorial written for the other install method.

One habit worth building immediately: run it inside a virtual environment or a container rather than as root. sqlmap writes session files, dumped CSVs, and logs into your home directory, and those files contain other people's data.

Your First Scan, Line by Line

The simplest useful command is a URL with a parameter and nothing else:

sqlmap -u "http://127.0.0.1:8099/product.php?id=1" --batch

--batch tells sqlmap to answer its own prompts with the default option instead of stopping to ask you seven questions. Use it once you understand what the questions are. The first few times, leave it off and read them.

Here is what sqlmap 1.10.9 printed when I ran that against a deliberately vulnerable page on my own machine, trimmed to the lines that carry information:

[INFO] testing connection to the target URL
[INFO] checking if the target is protected by some kind of WAF/IPS
[INFO] testing if the target URL content is stable
[INFO] target URL content is stable
[INFO] testing if GET parameter 'id' is dynamic
[INFO] GET parameter 'id' appears to be dynamic
[INFO] heuristic (basic) test shows that GET parameter 'id' might be SQL injectable
[INFO] testing for SQL injection on GET parameter 'id'
[INFO] GET parameter 'id' appears to be 'AND boolean-based blind - WHERE or HAVING clause' injectable (with --string="Mug")
[INFO] heuristic (extended) test shows that the back-end DBMS could be 'SQLite'
[INFO] target URL appears to have 3 columns in query
[INFO] GET parameter 'id' is 'Generic UNION query (NULL) - 1 to 20 columns' injectable

Four of those lines are worth memorizing, because they are the ones that tell you whether the rest of the run means anything.

  • "target URL content is stable" means the page returns the same content for the same request. If it says the content is not stable, sqlmap cannot tell your payload's effect apart from normal page noise, and every boolean-based result after that point is suspect. Fix it with --string or --text-only.
  • "parameter 'id' is dynamic" means changing the value changed the response. A parameter that is not dynamic is usually not reaching a query at all.
  • "heuristic (basic) test shows ... might be SQL injectable" is sqlmap throwing a single broken character at the parameter and noticing a database error. This is the fastest signal you get, and it is the one that most often confirms what you already suspected by hand.
  • "checking if the target is protected by some kind of WAF/IPS" is worth watching on real engagements. If a filter is in front of the app, silence here does not mean there is not one.

That entire scan took 52 HTTP requests. Keep that number in mind, because it is the baseline for a decision you will make later about --level and --risk.

💻
Practice this now: SQL Injection lab - a vulnerable parameter you can attack by hand first, then re-run with sqlmap to compare what the tool sees against what you found. Browser-based, free to start.

How to Read the Injection Point Summary

When sqlmap finds something, it prints a block that beginners scroll straight past. It is the most useful output in the whole run. Here is the real block from that scan:

sqlmap identified the following injection point(s) with a total of 52 HTTP(s) requests:
---
Parameter: id (GET)
    Type: boolean-based blind
    Title: AND boolean-based blind - WHERE or HAVING clause
    Payload: id=1 AND 6764=6764

    Type: error-based
    Title: SQLite >= 3.9 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (JSON path)
    Payload: id=1 AND 2526=JSON_EXTRACT(CHAR(123,125),...)

    Type: time-based blind
    Title: SQLite > 2.0 AND time-based blind (heavy query)
    Payload: id=1 AND 9391=LIKE(CHAR(65,66,67,68,69,70,71),UPPER(HEX(RANDOMBLOB(500000000/2))))

    Type: UNION query
    Title: Generic UNION query (NULL) - 3 columns
    Payload: id=1 UNION ALL SELECT CHAR(113,106,120,112,113)||...,NULL,NULL-- FBlf
---
back-end DBMS: SQLite

Each "Type" is a different way of getting an answer out of the database, and they are not equally good. This is the ranking that matters when you are waiting on a slow dump:

  1. UNION query. The database appends your rows to the real result set and the page prints them. One request can return many values. Always the fastest, always prefer it when sqlmap finds it.
  2. Error-based. The database leaks the answer inside an error message. Nearly as fast as UNION, and it works when the page prints errors but not extra rows.
  3. Boolean-based blind. The page has two visible states, true and false, and sqlmap reconstructs data one bit at a time by asking yes-or-no questions. Slow but reliable.
  4. Time-based blind. Nothing visible changes, so sqlmap asks the database to stall when the answer is yes and times the response. Painfully slow and easily thrown off by a busy network. If this is your only option, expect a dump to take hours.
  5. Stacked queries. The parameter lets you terminate the statement and run a second one. Not a data retrieval method by itself, but it is the gateway to writing files and running commands.

The default --technique=BEUSTQ tries all of them, and sqlmap picks the fastest available for each task without being told. The reason to know the ranking anyway is that it tells you what the application is doing. A target where only time-based works is a target that never shows you output, and that shapes everything you do next. If that describes your situation, the blind SQL injection guide covers the manual equivalent, which is what you fall back on when the tool cannot make progress.

Note the last line: back-end DBMS: SQLite. Once sqlmap knows the engine, it stops testing payloads for the other 30 and the run gets dramatically shorter. If you already know what the target runs, pass --dbms=mysql and skip that phase entirely.

From Injection Point to Data

Detection and extraction are separate steps. Once the injection point is stored, you add enumeration flags and sqlmap reuses what it already knows instead of testing again:

# what databases exist
sqlmap -u "http://target.example/product.php?id=1" --dbs

# tables in one database
sqlmap -u "http://target.example/product.php?id=1" -D shopdb --tables

# columns, so you know what is worth pulling
sqlmap -u "http://target.example/product.php?id=1" -D shopdb -T users --columns

# the data itself, two columns only
sqlmap -u "http://target.example/product.php?id=1" -D shopdb -T users -C username,password --dump

That escalation order is deliberate. Beginners reach for --dump-all or -a (retrieve everything) on their first run, then wonder why the scan has been running for forty minutes and the target's error logs are full. Walk down the tree instead: databases, tables, columns, then the two or three columns you actually need.

Here is the real dump from my test target:

Table: users
[2 entries]
+----+---------------------------------------------+----------+
| id | password                                    | username |
+----+---------------------------------------------+----------+
| 1  | 5f4dcc3b5aa765d61d8327deb882cf99 (password) | dana     |
| 2  | e10adc3949ba59abbe56e057f20f883e (123456)   | ravi     |
+----+---------------------------------------------+----------+

[INFO] table 'users' dumped to CSV file '/root/.local/share/sqlmap/output/127.0.0.1/dump/users.csv'

Look at the parentheses. sqlmap recognized those values as MD5 hashes, offered to run a dictionary attack, and cracked both against its built-in wordlist. That is a genuinely nice touch, and also a reminder of how fast unsalted MD5 falls over. The last line matters too: everything sqlmap retrieves is written to disk under your home directory. On a real engagement that file is now evidence you are responsible for.

Two flags are worth adding to your muscle memory here. --count tells you how many rows a table holds before you commit to dumping it, which saves you from starting a blind extraction of 400,000 records. And --where="id<10" lets you pull a representative sample instead of the whole table, which is usually all a report needs.

The Options That Actually Change Your Results

sqlmap has hundreds of switches. Six of them cover almost everything you will do in your first year.

-r: load a request from a file

This is the single most useful flag in the tool and the one tutorials mention last. Instead of rebuilding a complex request on the command line with --data, --cookie, and four -H headers, capture the request in Burp Suite, save it to a file, and hand the file over:

sqlmap -r login-request.txt -p username --batch

Every header, cookie, and body parameter comes along exactly as the browser sent it. For anything behind a login, JSON APIs, or multipart forms, this is the only sane approach. Add --force-ssl if the saved request does not record the scheme.

-p: name the parameter

Without -p, sqlmap tests every parameter it can find, including cookies and headers at higher levels. If your reconnaissance says the bug is in search, say so. A focused test finishes in a fraction of the time and generates a fraction of the noise.

--level and --risk: leave them alone at first

Here is the strong opinion: the reflex to open with --level 5 --risk 3 is wrong, and it is the most common mistake beginners make with this tool. Those options control how many payloads sqlmap tries and how dangerous they are allowed to be.

I measured it. Against a parameter that is not injectable, sqlmap 1.10.9 ran 11 test groups at the defaults (--level 1 --risk 1) and 172 at --level 5 --risk 3, with everything else held identical. That is roughly fifteen times as many tests to reach the same answer, and on a slow target it turns a two-minute check into a coffee break. Worse, risk level 3 includes OR-based payloads that can match every row in a table, which on a DELETE or UPDATE statement is how people accidentally wipe data during an authorized test.

Run the defaults. If the parameter genuinely looks injectable and comes back clean, then raise the level, one step at a time. Level 2 adds cookie testing, level 3 adds User-Agent and Referer, and level 5 tests headers most applications never put in a query.

--tamper: when a filter mangles your payload

If an input filter strips spaces or normalizes keywords, the payload that works by hand may never arrive intact. Tamper scripts rewrite payloads into equivalent forms, and 1.10.9 ships 84 of them:

sqlmap -u "http://target.example/p?id=1" --tamper=space2comment,randomcase --batch

space2comment swaps spaces for /**/, randomcase varies keyword capitalization, between replaces comparison operators. Run --list-tampers to read all of them. Do not stack six at once and hope: pick the one that matches the filtering behavior you observed, because tamper scripts change the payload in ways that can break an otherwise working injection.

--batch and the session file

The first time you re-run sqlmap against the same target, you will see this:

[INFO] resuming back-end DBMS 'sqlite'
sqlmap resumed the following injection point(s) from stored session:

sqlmap caches everything it learns in a SQLite session file per target. That is why the second run finishes instantly, and also why a stale result can follow you around after the application changes. --flush-session clears it and starts clean. If a scan is behaving in a way that makes no sense, flushing the session is the first thing to try.

--threads: careful speed

Blind extraction is one request per character, so --threads 5 can genuinely cut a long dump down. Above 10 you are hammering the target, and on production infrastructure that is how a test becomes an outage. Five is a reasonable ceiling for authorized work.

Keep going: the sqlmap cheat sheet lists the full command reference by task, including the file access and OS shell options this article deliberately skips.

When sqlmap Says "Not Injectable" and You Know It Is

This is the moment that sends people to forums. You found the bug manually, sqlmap disagrees, and the temptation is to crank every option to maximum. Work through these in order instead.

  • You did not send a valid session. The most common cause by far. sqlmap got a login redirect for every request and dutifully reported that nothing was injectable. Use -r with a captured authenticated request.
  • The parameter is not the one you think. Add -p and name it explicitly. If it lives in JSON or a cookie, -r handles the placement correctly.
  • The response is unstable. Timestamps, CSRF tokens, or rotating ads change the page on every request, so sqlmap cannot compare responses. Give it an anchor: --string="Welcome" for text that appears only on true responses, or --text-only to ignore markup.
  • An anti-CSRF token is rejecting every request. Point sqlmap at it with --csrf-token=token_name and it will fetch a fresh one before each request.
  • A filter is rewriting the payload. Now is the time for --tamper, and now is also the time to raise --level. Not before.
  • It is second-order. The payload is stored on one page and executed when a different page renders it. sqlmap handles this with --second-url, but you have to know the second page exists, and no scanner will tell you that.

There is also the honest possibility that the parameter is properly parameterized and you were wrong. That happens more often than forum posts suggest, and it is worth ruling in rather than escalating for another hour. A prepared statement gives sqlmap nothing to work with, and no combination of flags changes that.

Should You Use sqlmap in CTFs?

Should beginners use sqlmap in CTFs? Not for the first ten challenges. Automating a skill you have never performed manually leaves you unable to tell a real finding from a false positive, and unable to work when the tool stalls. Solve web challenges by hand until you can build a UNION payload yourself, then let sqlmap take over the repetitive extraction.

There is a practical reason as well as a pedagogical one. sqlmap is on the restricted tools list for the OSCP exam, alongside other automated exploitation tools; OffSec's stated aim is to test whether you can identify and exploit vulnerabilities rather than automate the process. If your plan includes that certification, every hour you spend running sqlmap instead of writing payloads is an hour of preparation you did not do. The current rules are in the OSCP exam guide, and they change occasionally, so check before you sit it.

Where sqlmap earns its place in a CTF is the moment after discovery. You have proven a boolean-based blind injection exists, and now you need 400 characters out of a table one bit at a time. Doing that by hand is not learning, it is typing. That is the job the tool was built for.

One more habit that separates people who improve from people who plateau: after sqlmap finds something, read the payload it used. It is printed in the injection point summary. Work out why AND 6764=6764 proves anything, and why the UNION payload has three NULLs in it. That is the whole lesson, and it is sitting in the output of every successful run.

Frequently Asked Questions

Is sqlmap legal to use?

The tool itself is legal and open source. Running it against a system you do not own or have written authorization to test is not, and in most jurisdictions it constitutes unauthorized access regardless of whether you extracted data. sqlmap prints this warning on every launch for a reason. Practice on deliberately vulnerable targets, dedicated training platforms, or systems covered by a bug bounty program's scope.

Does sqlmap work on POST requests and APIs?

Yes. Use --data="username=admin&password=x" for simple form posts, or capture the full request with a proxy and pass it with -r request.txt for anything more complex. Version 1.10.9 also handles JSON bodies, GraphQL endpoints with --graphql, and can derive targets straight from an OpenAPI specification with --openapi.

How long should a sqlmap scan take?

Detection against a single GET parameter at default settings is typically under a minute; my baseline run took 52 HTTP requests. Extraction depends entirely on the technique. A UNION dump of a small table is seconds. The same table over time-based blind injection, at roughly one request per bit with a 5 second delay each, can run for hours. If a dump is crawling, check which technique sqlmap settled on before you blame the tool.

What is the difference between --level and --risk?

--level (1 to 5) controls how many payloads sqlmap tries and where it looks, adding cookies at level 2 and headers at levels 3 and above. --risk (1 to 3) controls how dangerous those payloads are allowed to be, with level 3 including OR-based payloads that can affect every row in a table. Raise level when a scan comes back empty. Raise risk only when you understand what the payload could do to the data.

Can sqlmap give you a shell on the server?

Sometimes. --os-shell and --sql-shell exist, but they need conditions that are rare on a modern hardened target: stacked query support, a high-privilege database user, and a known writable path inside the web root. Treat them as an occasional bonus on a permitted engagement, not a step in your standard workflow, and understand that they write files onto a system you are only borrowing.

Critical reminder: Always get explicit written authorization before testing any system. sqlmap sends malformed queries by design, and higher risk levels can modify or destroy data. "I was only testing" is not a defense.

  • Confirm scope in writing before the first request, including which hosts, which parameters, and which times of day.
  • Keep --risk at 1 unless the client has explicitly accepted the possibility of data modification.
  • Extract the minimum needed to prove impact. One row from a sensitive table demonstrates the flaw; the whole table is a breach you caused.
  • Dumped data lands on your disk in plain CSV. Encrypt it, report it, then delete it.
  • On bug bounty programs, read the rules on automated tooling first. Several major programs prohibit automated scanners outright, and sqlmap counts.

For the defender's side of the same coin, OWASP's SQL injection reference and its query parameterization cheat sheet are the material to hand your development team.

Your Next Steps

Learning how to use sqlmap well is mostly about learning to read four lines of its output: is the content stable, is the parameter dynamic, which technique did it settle on, and which database is behind it. Everything else is flags. The people who get good at SQL injection are the ones who found the bug by hand first and used the tool to skip the typing, not the ones who learned the tool and hoped it would find bugs for them.

Do it in that order. Start with Query Quake, where you build the UNION payload yourself and see exactly which columns come back. Then take the guided path through the Web Attacks course, which covers injection alongside the rest of the OWASP Top 10 in browser labs with nothing to install. Both are free to start, no credit card required. Once you can find the injection without help, come back to sqlmap and let it do the boring part.

HackerDNA Team

HackerDNA Team

Written by the HackerDNA team - cybersecurity professionals building hands-on hacking labs and educational content to help you develop real-world security skills.

Meet the Team

Ready to put this into practice?

Stop reading, start hacking. Get hands-on experience with 170+ real-world cybersecurity labs.

Start Hacking Free
25,000+ Hackers 100+ Labs & Courses Free
Start Hacking Free