Autres injections : commande, LDAP et NoSQL (notions)
L’injection SQL n’est qu’une illustration d’un schéma plus général : une application envoie à un interpréteur un texte composé en partie de données non fiables. Dès qu’un interpréteur est en jeu (shell du système, annuaire, base de données non relationnelle, moteur de modèles, analyseur XML), le même risque existe. Cette leçon vous montre le raisonnement commun et quelques variantes, au niveau des notions. L’objectif est de savoir reconnaître et prévenir, pas de fournir des recettes.
Rappel légal
Les techniques d’injection, quelle qu’en soit la nature, ne se pratiquent que dans un cadre autorisé : votre laboratoire, DVWA, Juice Shop, la PortSwigger Academy, TryHackMe ou HackTheBox. Une injection de commande vise directement le système d’un serveur : en dehors d’un périmètre autorisé par écrit, elle tombe sous le coup des articles 323-1 à 323-3-1 du Code pénal, avec des conséquences potentiellement lourdes.
Le schéma commun à toutes les injections
Quatre éléments sont toujours présents :
- Une source de données non fiables (paramètre, en-tête, champ de formulaire, fichier).
- Un interpréteur qui comprend un langage (SQL, shell, requêtes d’annuaire…).
- Une construction par concaténation qui mélange les deux.
- Un effet : l’interpréteur exécute plus que prévu.
Quand vous découvrez une nouvelle variante, posez-vous la question : « quel est l’interpréteur ? quels caractères y ont un sens particulier ? ». Vous aurez presque toujours la réponse sur la nature de la faille.
L’injection de commande système
Certaines applications appellent un programme du système pour accomplir une tâche : tester la connectivité d’une adresse, convertir une image, générer un document. Si le nom de l’adresse ou du fichier provient de l’utilisateur et est inséré dans une ligne de commande, les caractères spéciaux du shell (séparateurs de commandes, enchaînements) peuvent faire exécuter autre chose que prévu.
Voici le style de code qui pose problème, en pseudo-PHP :
$hote = $_GET['hote'];
$sortie = shell_exec("ping -c 2 " . $hote);
echo "<pre>" . $sortie . "</pre>";
Le développeur voulait seulement un test de connectivité. Mais la valeur est livrée telle quelle au shell, qui peut interpréter des caractères de séparation pour exécuter une commande supplémentaire. L’impact est potentiellement le plus grave de toutes les injections, puisqu’il s’agit d’exécuter des commandes sur le serveur avec les droits du service web.
DVWA propose un module « exécution de commande » dédié à cette faille. En laboratoire, la démarche d’un testeur reste la même qu’avec le SQL : observer le comportement normal, envoyer une valeur contenant un caractère de séparation de commandes, constater un comportement qui montre que la ligne de commande a été altérée (par exemple, la sortie contient autre chose que ce qui était prévu), puis s’arrêter à la preuve la plus anodine possible et consigner. En audit réel, on ne fait jamais autre chose qu’une commande inoffensive d’identification, et uniquement dans le périmètre autorisé.
L’injection LDAP
LDAP est un protocole d’annuaire, très utilisé en entreprise pour stocker les comptes et les groupes (notions vues avec Active Directory dans le cours précédent). Une application qui interroge l’annuaire pour authentifier un utilisateur construit un filtre de recherche à partir de la saisie. Si les caractères spéciaux du langage de filtre (parenthèses, astérisque, opérateurs logiques) ne sont pas neutralisés, un utilisateur peut modifier la logique du filtre : par exemple, élargir la recherche ou rendre une condition toujours vraie. Le mécanisme est parent de l’injection SQL, appliqué à un annuaire. L’impact typique : contournement d’authentification ou fuite d’informations d’annuaire.
L’injection NoSQL
Les bases « NoSQL » (documents, clé-valeur…) n’utilisent pas SQL, mais ne sont pas immunisées. Beaucoup acceptent des requêtes structurées, souvent sous forme d’objets JSON contenant des opérateurs. Si l’application prend l’entrée de l’utilisateur et la transmet directement comme objet de requête, un visiteur peut fournir, à la place d’une valeur simple, une structure contenant un opérateur de comparaison, ce qui change le sens du filtre. Par exemple, une vérification « le mot de passe est égal à telle valeur » peut devenir « le mot de passe est différent de telle valeur », donc vraie pour presque tous les cas. Le principe est le même : la donnée est interprétée comme une partie de la requête.
Autres variantes à connaître de nom
| Variante | Interpréteur visé | Idée en une phrase |
|---|---|---|
| Injection de modèle (template injection) | Moteur de modèles de pages | Une saisie est interprétée comme une expression du moteur de modèles |
| Injection XML (XXE) | Analyseur XML | Des entités externes du document sont résolues par le serveur |
| Injection d’en-têtes ou de journaux | Protocole HTTP, fichiers de logs | Des sauts de ligne injectés falsifient une réponse ou une entrée de journal |
| Injection de requête de langage d’expressions | Moteurs d’expressions | Une saisie est évaluée comme du code par le moteur |
Inutile de les maîtriser toutes : le raisonnement commun vous permet de les comprendre rapidement quand vous les rencontrerez dans la documentation de l’OWASP ou dans les laboratoires de la PortSwigger Academy.
Reconnaître le risque en relisant un code
Votre meilleur réflexe est de repérer les trois ingrédients dans un extrait de code : une valeur venant de l’extérieur, un appel à un interpréteur, une concaténation. Les noms de fonction changent selon les langages (exécution de commande, construction de requête, évaluation d’expression), mais la recette ne change pas. Relisez ces deux exemples génériques :
// Construction de filtre d'annuaire à partir de la saisie
$filtre = "(&(uid=" . $login . ")(userPassword=" . $mdp . "))";
// Évaluation d'une expression fournie par l'utilisateur
$resultat = evaluer($_POST['formule']);
Dans les deux cas, une donnée externe est insérée dans un langage interprété. Le premier est typique d’une injection LDAP, le second d’une injection d’expression. Il suffit de ce regard pour suspecter ; la confirmation se fait ensuite en laboratoire.
Astuce
Sur un test de boîte grise ou blanche, où le code source est fourni, une simple recherche des appels aux fonctions d’exécution de commandes, de construction de requêtes et d’évaluation d’expressions permet de dresser rapidement la liste des endroits à examiner.
À vous de jouer
Pour chacun des trois extraits ci-dessous, identifiez la source, l’interpréteur et le risque :
$archive = $_GET['nom']; system("zip -r sauvegarde.zip " . $archive);$req = "SELECT * FROM articles WHERE titre LIKE '%" . $_GET['q'] . "%'";$filtre = "(cn=" . $_POST['nom'] . ")";utilisé pour interroger un annuaire.
Voir une solution
1) Source : paramètre nom ; interpréteur : le shell du système ; risque : injection de commande, avec un impact potentiel sur le serveur. 2) Source : paramètre q ; interpréteur : le moteur SQL ; risque : injection SQL (une recherche est un cas très courant). 3) Source : champ nom ; interpréteur : l’annuaire LDAP ; risque : injection LDAP, qui permet de modifier la logique du filtre. Dans les trois cas, la correction relève du même principe : ne jamais composer l’instruction par concaténation avec une donnée externe.
À retenir
- Toute injection suit le même schéma : donnée non fiable, interpréteur, concaténation, exécution imprévue.
- L’injection de commande vise le système du serveur et a un impact potentiellement très lourd.
- LDAP et NoSQL ont leurs propres caractères et opérateurs spéciaux, mais le principe est identique à SQL.
- Reconnaître le risque dans un code : valeur externe, appel à un interpréteur, concaténation.
- On ne pratique qu’en laboratoire autorisé et on s’arrête à la preuve minimale.
Il est temps de passer du côté de la défense : comment empêche-t-on ces failles, à la racine ? C’est la leçon suivante.