Injection

1. PrincipeMain en arriere fleche dessinee 318 51824

L'attaque par injection est évaluée par l'OWASP comme étant la plus risquée, car la faille est assez répandue, il est facile de l'exploiter et l'impact peut être très important. Cela va de la simple récupération de données à la prise totale de contrôle du serveur. La victime de l'attaque est un des composants techniques de l'application Web.

Contensin [6] explique que pour réaliser une attaque de ce type, il faut injecter dans les zones de saisie classiques présentées à l'utilisateur du code malicieux. Ces données seront interprétées comme des instructions par un des composants de l'application Web. Les champs de formulaires peuvent être protégés par JavaScript pour vérifier que les valeurs saisies correspondent à ce qui est attendu. Cependant, J. Scambray, V. Liu et C. Sima [7] démontrent qu'il est possible d'outrepasser ces vérifications en faisant appel à un serveur proxy personnel, par exemple, qui permettra d'intercepter les requêtes pour les modifier et envoyer le code malicieux. La difficulté de l'attaque réside finalement dans la détection des technologies utilisées pour formuler le code d'attaque adéquat. Cependant, la plupart des applications Web de gestion de contenu présentes sur le Web sont basées sur des projets Open Source. H. Dwivedi, A. Stamos, Z. Lackey et R. Cannings [8] montrent qu'il est alors facile d'identifier les technologies employées en parcourant le code source mis à disposition. De plus, il existe des outils d'injection automatique disponibles sur le Web, rendant le risque plus élevé. L'exploitation de la faille devient automatisable.

2. Exemples d'attaque

L'attaque par injection SQL consiste à injecter du code SQL qui sera interprété par le moteur de base de données. Le code malicieux le plus répandu est d'ajouter une instruction pour faire en sorte que la requête sous-jacente soit toujours positive. Cela permet par exemple d'usurper une identité pour se connecter à une application Web, de rendre l'application inutilisable ou de supprimer toutes les données de la table visée, voire de la base de données complète. L'exemple suivant va interroger une table qui contient la liste des cartes bancaires enregistrées dans la base de données de l'application Web d'un site marchand. Le script de création de cette table est le suivant :

Figure 6 - Script SQL de création de la table « comptes »

Sélectionnez

CREATE TABLE IF NOT EXISTS `comptes` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'identifiant', 
`nom` varchar(30) NOT NULL COMMENT 'nom d''utilisateur', 
`motdepasse` varchar(41) NOT NULL, 
`typecarte` varchar(30) NOT NULL COMMENT 'type de carte', 
`numerocarte` varchar(30) NOT NULL COMMENT 'numéro de carte', 
PRIMARY KEY (`id`), 
UNIQUE KEY `nom` (`nom`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;

Pour afficher le numéro de carte bancaire, l'utilisateur doit s'authentifier. La requête SQL suivante permet de vérifier que le couple utilisateur « user4 »/mot de passe du compte « eng111 » est correct et si tel est le cas renvoie le numéro de carte bancaire :

Figure 7 - Requête SQL pour l'authentification et affichage du numéro de carte

Sélectionnez

SELECT `numerocarte` 
FROM `comptes` 
WHERE `nom` = 'user4' 
AND `motdepasse` = PASSWORD( 'eng111' )

Le script PHP pour exploiter cette requête de façon dynamique avec les informations fournies par l'utilisateur est le suivant :

Figure 8 - Script PHP pour l'authentification et l'affichage du numéro de carte

Sélectionnez

<?php //connexion a la base de donnees 
mysql_connect('localhost', 'root', ''); 
mysql_select_db('eng111'); 
//recuperation des parametres 
$nom = $_GET['nom']; 
$motdepasse = $_GET['motdepasse']; 
//generation de la requete 
$requeteSQL = "SELECT numerocarte FROM comptes WHERE nom = '$nom' AND motdepasse = PASSWORD( '$motdepasse' )"; 
//execution de la requete 
$reponse = mysql_query($requeteSQL); 
$resultat = mysql_fetch_assoc($reponse); 
//affichage du resultat 
echo $resultat['numerocarte']; 
?>

En remplissant le formulaire avec la valeur « ' OR 1=1 -- ' » pour le champ « nom » et n'importe quelle valeur pour le mot de passe, la requête qui sera envoyée à la base de données devient :

Figure 9 - Requête SQL incluant du code frauduleux d'injection

Sélectionnez

SELECT numerocarte FROM comptes WHERE nom = '' OR 1=1 -- '' AND motdepasse = PASSWORD( 'x' )

Ainsi la condition 1=1 est toujours vérifiée et le reste de la commande est mis en commentaire grâce à la chaîne de caractères « -- ». Cela permet donc de récupérer aléatoirement un numéro de carte.

L'attaque par injection de XPath suit le même principe que pour SQL [9]. En effet, XPath est un langage de requête pour gérer les données stockées au format XML, comme le fait SQL pour les bases de données relationnelles. XPath et Xquery, dont XPath est un sous-ensemble, souffrent donc des mêmes vulnérabilités face à l'injection de code malicieux.

L'attaque par injection LDAP permet d'accéder à des informations privées qui sont enregistrées dans l'annuaire d'entreprise. En modifiant le comportement du filtrage dans la requête LDAP qui sera générée, il est possible de récupérer la liste exhaustive des adresses de courrier électronique d'une entreprise pour les saturer de spam par exemple.

L'attaque par injection de commandes est surtout principalement possible sur les scripts CGI écrits en Perl, PHP et Shell. Il est possible de prendre le contrôle du serveur. Il faut pour cela faire en sorte que la commande initiale soit exécutée sans problème et ajouter des commandes du système d'exploitation du serveur qui seront exécutées par le serveur.

L'attaque par traversée de répertoire permet d'accéder à des fichiers présents sur le serveur. Les fichiers cibles privilégiés étant ceux contenant des informations de sécurité comme le fichier des mots de passe ou les fichiers contenant les clés privées de chiffrement pour SSL par exemple. Cette attaque est rendue possible si l'application Web inclut du contenu de fichier en passant l'adresse de ce fichier en paramètres de la requête.

Les attaques XXE (XML eXternal Entity) sont un dérivé des attaques par traversée de répertoire. Les conséquences vis-à-vis des fichiers présents sur les serveurs sont donc les mêmes. Ce type d'attaque est basé sur la fonctionnalité de XML « entités externes ». Les entités sont des substituts pour des séquences d'information. Elles sont équivalentes aux variables dans les langages de programmation. Les entités externes permettent de déclarer des documents dont le contenu sera affiché lors de l'utilisation de l'entité. Si l'entité pointe sur un fichier existant sur le serveur, son contenu pourra être divulgué à l'attaquant. Cette fonctionnalité peut être exploitée en plaçant un fichier XML au format RSS sur un site et de l'intégrer à un agrégateur en ligne. Si ce dernier est vulnérable, il sera alors possible de voir le contenu des fichiers demandés par l'attaquant.

3. Parade et bonnes pratiques

Les différentes attaques citées précédemment reposent principalement sur l'utilisation de caractères spécifiques qui permettent de mettre en commentaire des portions de code et d'insérer du code frauduleux. Il est cependant rare que l'application ait besoin d'accepter les caractères suivants :

Figure 10 - Caractères spéciaux communément utilisés dans les attaques d'injection

Sélectionnez

& ~ " # ' { } ( [ ] ( ) - | ` _ \ ^ @ \ * / . < > , ; : ! $

Cependant les applications Web de gestion de contenu comme les forums doivent les accepter, notamment les forums utilisés par les développeurs pour partager du code. Dans ce cas, il faut transformer au moins les caractères ci-dessus en code HTML avant de les stocker dans la base de données. L'affichage de l'information ne sera pas différent pour l'utilisateur, mais les données seront plus sûres.

Bien qu'un site puisse subir différents types d'attaques par injection, il suffit de vérifier que les caractères utilisés sont ceux attendus. Ce contrôle doit être effectué au niveau du client grâce à JavaScript et au niveau du serveur lorsque les paramètres sont récupérés pour fermer la faille de sécurité. Par exemple, le langage PHP offre une fonctionnalité qui permet de transformer ces caractères.

Figure 11 - Script PHP pour remplacer les caractères par le code HTML

Sélectionnez

<?php 
$nouvelleValeur=htmlspecialchars($valeurParametre,ENT_QUOTES); 
?>

De plus il faut vérifier que les valeurs sont bien du type et du format attendus (longueur, intervalle de valeur…).

L'ANSSI porte une attention particulière aux outils automatiques d'exploitation des failles SQL dans son bulletin de sécurité CERTA-2011-ACT-045. Pour déterminer si un site est victime de ce type d'agression, il faut vérifier dans les journaux d'activité du serveur HTTP qu'il n'y a pas d'événement inhabituel, tel qu'un nombre de requêtes HTTP anormalement élevé ou des requêtes ayant pour paramètres des valeurs inappropriées.

 
×