12.3 Blind SQL Injection & Database Enumeration

Key Takeaways

  • Inferential (Blind) SQL Injection occurs when an application executes malicious SQL queries without returning database error messages or query result sets in HTTP responses.
  • Boolean-based blind SQLi forces differential application behavior by injecting True and False conditional predicates (' AND 1=1 -- vs ' AND 1=2 --), extracting data bit-by-bit or character-by-character.
  • Time-based blind SQLi leverages conditional execution delays using engine-specific functions—MSSQL WAITFOR DELAY, MySQL SLEEP(), PostgreSQL pg_sleep(), and Oracle DBMS_PIPE.RECEIVE_MESSAGE().
  • Standardized metadata schemas allow systematic structural enumeration: information_schema.tables and information_schema.columns in MySQL/MSSQL/PostgreSQL, and data dictionary views (ALL_TABLES, ALL_TAB_COLUMNS, USER_TABLES) in Oracle.
  • Automated exploitation frameworks such as sqlmap automate heuristic detection, character extraction algorithms, and WAF evasion using customizable tamper scripts.
Last updated: September 2026

12.3 Blind SQL Injection & Database Enumeration

In modern hardened web applications, database errors are suppressed and query output is rarely reflected directly within HTTP responses. However, an application may remain fundamentally vulnerable to SQL injection if untrusted user input is still concatenated into database execution strings. When data cannot be extracted through in-band channels (UNION or verbose error messages), security analysts must utilize Inferential (Blind) SQL Injection techniques to reconstruct sensitive information by observing subtle side-channel behaviors.


Principles of Inferential (Blind) SQL Injection

Inferential SQL injection differs from in-band injection because the attacker cannot see any direct database data in the application response. Instead, the attacker asks the database a series of binary (True/False) questions. By observing how the application or server responds to these questions, the attacker deduces data character-by-character.

+-----------------------------------------------------------------------------+
|                     BLIND SQL INJECTION METHODOLOGIES                       |
+-----------------------------------------------------------------------------+
| Feature              | Boolean-Based Blind           | Time-Based Blind     |
+----------------------+-------------------------------+----------------------+
| Feedback Mechanism   | Visible Response Differences  | Network Delay        |
| Indicator            | HTTP 200 vs 500, Content-     | Response takes >= N  |
|                      | Length, Specific text message | seconds to return    |
| Network Sensitivity  | High resilience to network lag| Prone to jitter/skew |
| Execution Speed      | Fast (binary search)          | Slow (delay penalty) |
+-----------------------------------------------------------------------------+

Boolean-Based Blind SQL Injection

Boolean-based blind SQL injection occurs when the application renders different responses depending on whether an injected SQL condition evaluates to TRUE or FALSE.

[Client Request: id=5 AND 1=1] ---> [Database Evaluates TRUE]  ---> Response: "Product Found"
[Client Request: id=5 AND 1=2] ---> [Database Evaluates FALSE] ---> Response: "Product Not Found"

Identifying the Boolean Vulnerability

To establish whether a parameter is susceptible to Boolean blind injection, the tester submits paired test conditions:

  1. Positive Test (True): item.php?id=10 AND 1=1 (or ' AND 'a'='a)
    • Expected Behavior: The page displays normally, showing the record, a 200 OK status, or expected content.
  2. Negative Test (False): item.php?id=10 AND 1=2 (or ' AND 'a'='b)
    • Expected Behavior: The page changes—the item is missing, an error message appears ("Item not found"), the HTTP status becomes 404, or the response Content-Length differs significantly.

If the application demonstrates consistent, reproducible differences between True and False inputs, the parameter is vulnerable to Boolean blind exploitation.

Character-by-Character Extraction Mechanics

To extract confidential data, the attacker combines three programmatic SQL functions:

  1. SUBSTRING(str, pos, len) (or MID()): Extracts a single character from a string at a specified 1-based index position.
  2. ASCII(char): Converts the extracted character into its decimal ASCII numerical code (e.g., 'a' = 97, 'A' = 65, '0' = 48).
  3. Comparative Operators (>, <, =): Evaluates the numerical ASCII value against test values.

Linear Search vs Binary Search

If a tester tests every ASCII value sequentially from 32 to 126, extracting a 20-character password requires an average of 20 * 47 = 940 HTTP requests.

By implementing a Binary Search (Bisection) Algorithm, the tester halves the search range with each request:

-- Step 1: Is the ASCII value of the 1st character greater than 64? (Range: 0-127)
AND ASCII(SUBSTRING((SELECT password FROM users WHERE username='admin'), 1, 1)) > 64 --  [TRUE]

-- Step 2: Is it greater than 96? (Range: 65-127)
AND ASCII(SUBSTRING((SELECT password FROM users WHERE username='admin'), 1, 1)) > 96 --  [TRUE]

-- Step 3: Is it greater than 112? (Range: 97-127)
AND ASCII(SUBSTRING((SELECT password FROM users WHERE username='admin'), 1, 1)) > 112 -- [FALSE]

-- Step 4: Is it greater than 104? (Range: 97-112)
AND ASCII(SUBSTRING((SELECT password FROM users WHERE username='admin'), 1, 1)) > 104 -- [FALSE]

-- Step 5: Is it greater than 100? (Range: 97-104)
AND ASCII(SUBSTRING((SELECT password FROM users WHERE username='admin'), 1, 1)) > 100 -- [FALSE]

-- Step 6: Is it equal to 97? ('a')
AND ASCII(SUBSTRING((SELECT password FROM users WHERE username='admin'), 1, 1)) = 97 --  [TRUE]

A binary search determines any ASCII character in at most 7 HTTP requests (log2(128) = 7), dramatically accelerating extraction.


Time-Based Blind SQL Injection

In many applications, the web application code handles errors silently and always returns identical content (e.g., "Search processed") regardless of whether the SQL query returned data or encountered an empty set. In this scenario, Boolean conditions produce no discernible change in HTTP status or body.

Time-based blind SQL injection overcomes this limitation by forcing the database server to pause execution for a designated duration (e.g., 5 seconds) when a condition evaluates to TRUE.

Attacker ---> Submits Query with Conditional Sleep ---> Target Server
                  |
                  v (Database evaluates: IF condition is TRUE -> SLEEP 5)
                  |================== [5 Second Pause] ==================>
                                                                          |
Attacker <--- Receives HTTP Response after 5.12 Seconds <-----------------+
[Conclusion: Condition is TRUE]

Database-Specific Time Delay Primitives

Each database management system implements distinct procedural functions to introduce sleep states:

+-----------------------------------------------------------------------------+
|                   DATABASE TIME DELAY PRIMITIVES (CPSA CORE)                |
+-----------------------------------------------------------------------------+
| RDBMS              | Delay Function / Command      | Syntax Example         |
+--------------------+-------------------------------+------------------------+
| Microsoft SQL      | WAITFOR DELAY                 | WAITFOR DELAY '0:0:5'  |
| MySQL / MariaDB    | SLEEP()                       | SELECT SLEEP(5)        |
|                    | BENCHMARK() (Alternative)     | BENCHMARK(5000000,MD5(1))|
| PostgreSQL         | pg_sleep()                    | SELECT pg_sleep(5)     |
| Oracle RDBMS       | DBMS_PIPE.RECEIVE_MESSAGE()   | DBMS_PIPE.RECEIVE_MESSAGE|
|                    |                               |   ('channel', 5)       |
| SQLite             | randomblob() heavy computation| (SELECT count(*) FROM  |
|                    |                               |  generate_series)      |
+-----------------------------------------------------------------------------+

Conditional Branching Syntax

To extract data using time delays, the delay command is wrapped inside a conditional statement (IF or CASE):

  • Microsoft SQL Server:
    '; IF (SELECT ASCII(SUBSTRING(user_name(), 1, 1))) = 100 WAITFOR DELAY '0:0:5'-- 
    
  • MySQL:
    ' AND IF(ASCII(SUBSTRING((SELECT version()), 1, 1)) = 56, SLEEP(5), 0)-- 
    
  • PostgreSQL:
    ' AND (SELECT CASE WHEN (ASCII(SUBSTRING(current_user, 1, 1))=112) THEN pg_sleep(5) ELSE pg_sleep(0) END)-- 
    
  • Oracle:
    ' AND 1=(CASE WHEN (ASCII(SUBSTRING((SELECT user FROM dual), 1, 1))=83) THEN DBMS_PIPE.RECEIVE_MESSAGE('a', 5) ELSE 1 END)-- 
    

Operational Considerations for Testers: Time-based attacks are susceptible to false positives and false negatives caused by network congestion or high database server load. Testers should select delay intervals (typically 3 to 5 seconds) that clearly exceed baseline network jitter while minimizing total assessment duration.


Database Metadata Enumeration Standards

Once an injection vector is established, an analyst systematically enumerates the database environment. Modern relational databases maintain metadata describing schemas, tables, and columns.

ANSI information_schema (MySQL, MSSQL, PostgreSQL)

The ANSI SQL-92 standard defines the information_schema, a set of read-only views available in MySQL, MSSQL, and PostgreSQL:

  1. Enumerating Databases / Schemas:
    SELECT schema_name FROM information_schema.schemata;
    
  2. Enumerating Tables in the Current Database:
    SELECT table_name FROM information_schema.tables WHERE table_schema = database();
    
  3. Enumerating Columns within a Specific Table:
    SELECT column_name, data_type FROM information_schema.columns WHERE table_name = 'tbl_users';
    

Oracle Data Dictionary Views

Oracle does not support information_schema. Instead, it uses hierarchical data dictionary views prefixed by access scope:

  • USER_TABLES / USER_TAB_COLUMNS: Objects owned by the currently connected user.
  • ALL_TABLES / ALL_TAB_COLUMNS: Objects accessible to the current user (including granted permissions).
  • DBA_TABLES / DBA_TAB_COLUMNS: All objects across the entire database instance (requires DBA privileges).
-- Enumerating accessible tables in Oracle
SELECT owner, table_name FROM all_tables;

-- Enumerating columns for a specific table in Oracle
SELECT column_name, data_type FROM all_tab_columns WHERE table_name = 'USERS';

PostgreSQL Native Catalog

In addition to information_schema, PostgreSQL provides its internal system catalog in the pg_catalog schema:

SELECT relname FROM pg_catalog.pg_class WHERE relkind = 'r';
SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname = 'public';

Automated Exploitation Tools: Principles and Mechanics of sqlmap

While understanding manual exploitation mechanics is vital for penetration testers, automated tools like sqlmap streamline detection and data recovery across complex web applications.

Detection Techniques & Heuristics

sqlmap systematically tests injection points using six categories of techniques (represented by the letters B, E, U, S, T, Q):

  • B: Boolean-based blind
  • E: Error-based
  • U: Union query-based
  • S: Stacked queries
  • T: Time-based blind
  • Q: Inline queries

Key Operational Parameters

  • --level (1-5): Controls the scope of tests performed. Level 1 tests GET and POST parameters. Level 2 adds Cookie headers. Level 3 adds User-Agent and Referer headers. Level 5 expands tests to host headers and deep arbitrary payloads.
  • --risk (1-3): Controls the aggressiveness of test payloads. Risk 1 is completely safe. Risk 2 adds heavy time-based tests. Risk 3 adds OR-based tests, which carry a potential risk of unintentionally updating or corrupting database tables if applied to UPDATE or DELETE statements.
  • --dbs, --tables, --columns, --dump: Directs automated enumeration of databases, tables, columns, and data extraction.

Tamper Scripts for WAF / Filter Evasion

When Web Application Firewalls (WAFs) or input filters block standard SQL keywords, sqlmap applies tamper scripts to rewrite outgoing payloads without altering their semantic meaning:

  • space2comment.py: Replaces space characters with inline comments (SELECT/**/id/**/FROM/**/users).
  • randomcase.py: Randomizes character casing (SeLeCt * FrOm uSeRs).
  • charencode.py: URL-encodes payload characters to evade pattern-matching signatures.
Test Your Knowledge

A penetration tester identifies an injection point in an Oracle application that suppresses all errors and returns identical response pages. Which SQL statement can be injected to confirm a time-based blind vulnerability by inducing a five-second delay?

A
B
C
D
Test Your Knowledge

In Boolean-based blind SQL injection, an analyst wants to minimize the number of HTTP requests required to extract individual characters from a 60-character database hash. Which algorithmic technique should be implemented?

A
B
C
D
Test Your Knowledge

During an engagement against an enterprise database, an analyst needs to enumerate all table names accessible to the current user. Which data source should be queried if the target database is Oracle, as opposed to MySQL or MSSQL?

A
B
C
D
Test Your Knowledge

When configuring the automated exploitation tool sqlmap against a production web application, what is the primary operational hazard associated with setting --risk=3?

A
B
C
D