Greetings, fellow hackers and pen testers! As we continue to explore the depths of web application security, we cannot overlook the importance of advanced SQL injection techniques. This powerful and versatile attack vector remains a persistent threat to web applications - still appearing in the OWASP Top 10 in 2024. Today, we’ll dive into the fascinating world of SQL injection, covering advanced techniques, manual exploitation, and evasion methods that will serve you well on real-world engagements.
SQL Injection (SQLi) is more than just dumping passwords; it’s a potential gateway to Remote Code Execution (RCE) and full infrastructure compromise. A SQL injection in a web application can lead to:
- Data Exfiltration: Dumping entire databases, including credentials, PII, and intellectual property.
- Authentication Bypass: Logging in as any user, including administrators.
- Data Manipulation: Modifying or deleting critical records.
- Remote Code Execution: Using database features like
xp_cmdshell(MSSQL) orCOPY TO PROGRAM(PostgreSQL) to execute OS commands. - Lateral Movement: Pivoting to internal systems via database links or by dumping credentials stored in the database.
1. SQL Injection Types: A Taxonomy
Before we dive into exploitation, let’s establish a clear taxonomy of SQL injection types.
In-Band SQLi (Classic)
The attacker uses the same channel to inject the payload and retrieve results.
- UNION-Based: Results of the injected query are directly returned in the application’s response.
- Error-Based: The database’s error messages reveal data.
Inferential SQLi (Blind)
The database does not return data directly; the attacker infers information based on the application’s behavior.
- Boolean-Based Blind: The application returns different responses (e.g., “Welcome” vs. “Invalid”) based on whether a condition is true or false.
- Time-Based Blind: The application’s response time reveals information (e.g., if
SLEEP(5)is executed, the response takes 5 seconds longer).
Out-of-Band (OOB) SQLi
The attacker forces the database server to make an external network connection (DNS or HTTP) to a server they control.
- Used when in-band and blind techniques are unreliable or blocked.
- Requires the database to have network access and the relevant features enabled.
Second-Order SQLi
The malicious payload is not executed immediately. Instead, it is stored in the database and executed later when retrieved by a different query.
- Extremely difficult to detect with automated scanners.
- Common in applications that store user input and later use it in dynamic SQL.
2. Manual UNION-Based Exploitation: The Surgeon’s Knife
While sqlmap is a fantastic tool, a professional red teamer can do it by hand. Manual exploitation is often the only way to bypass a strict WAF that fingerprints automated tool behavior. It also provides a deeper understanding of what’s actually happening.
Step 1: Confirm the Injection Point
Always start by confirming that user input is being incorporated into a SQL query unsafely.
| |
Step 2: Determine Column Count with ORDER BY
We use ORDER BY to find the number of columns returned by the original query. This is essential for UNION-based attacks because the number of columns in the injected query must match the original.
| |
[!TIP] If
--(double-dash comment) doesn’t work, try#(MySQL),/* */(block comment), or--+(URL-encoded space).
Step 3: Identify Reflectable Columns with UNION SELECT
Now we find which columns accept string data and are displayed in the response using UNION SELECT. We need to ensure our injected data appears somewhere visible.
| |
When the page displays the character 'a', you’ve found your “sink” - the column that reflects data back to you. If no data is reflected, you may be dealing with a Blind injection.
Step 4: Fingerprint the Database
Before extracting data, identify the database management system (DBMS). The syntax for metadata queries differs between systems.
| |
Step 5: Extract Database Metadata
Now, list the databases, tables, and columns.
MySQL:
| |
Microsoft SQL Server (MSSQL):
| |
PostgreSQL:
| |
Step 6: Dump Sensitive Data
Finally, extract the data you’re after.
| |
3. Error-Based SQL Injection
When UNION-based injection isn’t possible (e.g., the query output isn’t displayed), but errors are, we can force the database to leak data within error messages.
MSSQL: CONVERT Errors
| |
If the username is “admin”, the error might say: Conversion failed when converting the nvarchar value 'admin' to data type int.
MySQL: EXTRACTVALUE / UPDATEXML
These XML functions can be abused to generate errors containing query results.
| |
PostgreSQL: CAST Errors
| |
4. Blind SQL Injection
When there’s no visible output or error messages, we must infer data from changes in the application’s behavior.
Boolean-Based Blind
The application returns different content based on whether the injected condition is true or false.
| |
This is slow (extracting 10 characters requires ~80 requests with binary search), which is why sqlmap exists.
Time-Based Blind
When even the boolean difference isn’t visible (e.g., the page always looks the same), we use time delays.
| |
Extract data:
| |
[!WARNING] Time-based injection can be slow and unreliable on networks with variable latency. Always calibrate your baseline response time first. If normal requests take 500ms and your target sleep is 5 seconds, the delay will be obvious. If network jitter is 3 seconds, you’ll get false positives.
5. Stacked Queries
Some database/driver combinations allow multiple SQL statements separated by semicolons to be executed in a single request.
| |
Supported Databases:
- MSSQL: Yes (widely supported).
- PostgreSQL: Yes.
- MySQL: Depends on the driver. PHP’s
mysql_query()does not support stacked queries, butmysqli_multi_query()and PDO might. - Oracle: No.
- SQLite: Yes, via
executescript().
Stacked queries are powerful for:
- Data manipulation (INSERT, UPDATE, DELETE).
- Enabling dangerous features (
'; EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;--). - Time-based blind attacks on databases that don’t support inline time functions.
6. Second-Order SQL Injection
Second-Order SQLi (also called Stored SQLi) occurs when user-supplied data is stored in the database and later incorporated into an SQL query without proper sanitization.
Scenario:
- An attacker registers a new user with the username:
admin'-- - The application safely inserts this into the
userstable using parameterized queries. No immediate injection occurs. - Later, an administrative function retrieves the username and uses it in a dynamically constructed query:
1 2$username = get_username_from_db($user_id); // Returns "admin'--" $query = "SELECT * FROM orders WHERE user = '$username'"; - The resulting query becomes:
SELECT * FROM orders WHERE user = 'admin'--'The attacker is now viewing the admin’s orders.
Why Second-Order SQLi is Dangerous:
- It evades many automated scanners because the injection point and the execution point are different.
- The input may be validated on entry but trusted on retrieval.
- It requires careful code review and data flow analysis to find.
Detection:
- Register accounts with SQLi payloads as usernames, emails, or other stored fields.
- Monitor for unexpected behavior in features that display or use this stored data (profile pages, admin dashboards, export functions).
7. WAF Evasion Techniques
Web Application Firewalls (WAFs) love to block keywords like SELECT, UNION, and OR 1=1. Red teamers must be creative.
Comment Injection
Many WAFs are confused by internal comments.
| |
Case Manipulation
Standard SQL is case-insensitive for keywords, but many WAF regex patterns are case-sensitive.
| |
Encoding
URL-encode your payload. Double-encoding can bypass WAFs that decode once.
| |
Hex Encoding Strings (MySQL)
Replace string literals with their hex equivalents.
| |
Whitespace Substitution
Replace spaces with other characters that SQL parsers accept but WAFs might not expect.
| |
HTTP Parameter Pollution (HPP)
Some WAFs only inspect the first occurrence of a parameter, while the application might concatenate them or use the last one.
| |
JSON/XML Payloads
If the application accepts JSON or XML, the WAF might not parse these formats as thoroughly.
| |
8. Out-of-Band (OOB) Exfiltration
When in-band (UNION, Error) and Blind techniques fail or are too slow, OOB exfiltration forces the database to connect to an attacker-controlled server.
Requirements:
- The database server must have network egress.
- Relevant database features (e.g.,
xp_dirtree,UTL_HTTP) must be enabled.
DNS Exfiltration
DNS is often allowed through firewalls. We force the database to resolve a hostname containing the exfiltrated data.
MSSQL:
| |
Check your DNS logs (e.g., using nslookup, tcpdump, or a Burp Collaborator) for queries like sa.attacker.com.
Oracle:
| |
PostgreSQL:
PostgreSQL doesn’t have a built-in DNS function, but you can use COPY TO PROGRAM if you have sufficient privileges:
| |
HTTP Exfiltration
If HTTP egress is allowed:
Oracle (UTL_HTTP):
| |
PostgreSQL (COPY TO PROGRAM):
| |
MSSQL (xp_cmdshell):
| |
Tools for OOB Testing
- Burp Collaborator: Built into Burp Suite Professional.
- Interactsh: Free, open-source OOB interaction server.
- DNSLog: Simple online DNS logger.
9. From SQLi to Remote Code Execution
The ultimate goal of many SQLi attacks is RCE. Here’s how to achieve it on different platforms.
MSSQL: xp_cmdshell
| |
PostgreSQL: COPY TO PROGRAM
Requires superuser privileges.
| |
Alternatively, use Large Object functions:
| |
MySQL: INTO OUTFILE / LOAD_FILE
MySQL can write files to the filesystem (if secure_file_priv allows):
| |
Read files:
| |
Oracle: Java Stored Procedures / Scheduler Jobs
If Java is installed in Oracle, you can create a Java stored procedure to execute OS commands. This is complex and typically requires DBA privileges.
10. Weaponizing SQLMap for Professionals
Don’t just run sqlmap -u [URL]. Use the advanced flags to bypass modern defenses and maximize efficiency.
Essential Flags
| |
WAF Evasion with Tamper Scripts
| |
Data Exfiltration
| |
Post-Exploitation
| |
Proxying and Logging
| |
11. Prevention and Mitigation
While we focus on exploitation, understanding defenses is crucial for writing comprehensive reports.
The Gold Standard: Parameterized Queries (Prepared Statements)
| |
Parameterized queries ensure that user input is always treated as data, never as SQL code.
Defense in Depth
- Least Privilege: The database user for the web application should never be
sa,root, orpostgres. It should have only the minimum permissions required (SELECT on specific tables, no DDL, noxp_cmdshell). - Database Hardening:
- Disable dangerous procedures:
xp_cmdshell(MSSQL),UTL_HTTP/UTL_FILE(Oracle),lo_export(PostgreSQL). - Set
secure_file_priv(MySQL) to restrictLOAD_FILEandINTO OUTFILE. - Disable stacked queries at the driver level if not needed.
- Disable dangerous procedures:
- Input Validation: Whitelist allowed characters for fields like usernames. Reject inputs containing SQL metacharacters when appropriate (though this should not be the primary defense).
- WAF Rules: Deploy a WAF with custom rules for your application’s specific parameters. Assume the WAF will be bypassed and layer other defenses.
- Error Handling: Never display raw database errors to users. Log them server-side and show a generic error message.
- ORM Usage: Object-Relational Mappers (ORMs) like SQLAlchemy, Hibernate, and Django ORM generally use parameterized queries under the hood, reducing the attack surface.
Conclusion
Advanced SQL injection is a game of cat and mouse. As defenders adopt parameterized queries and WAFs, red teamers must become more surgical, employing manual UNION techniques, error-based extraction, blind inference, and OOB exfiltration. Second-order injection reminds us that security must be applied consistently, not just at the point of input.
The database is the heart of the organization. It stores credentials, customer data, financial records, and intellectual property. Master the injection, and you own the heart.
Happy hacking!