• Aucun résultat trouvé

FIGURE3.4 – Dendrogramme de grappes

compromis dans la mesure où il suit cette logique et permet de choisir le seuil le plus proche possible de 1 qui ne génère pas de faux positifs.

Dans l’exemple fourni ici, la page que nous testons est une page d’authentification, pour laquelle les réponses correspondant aux pages de rejet et aux pages d’exécution sont très différentes en terme de contenu. Par conséquent, même un seuil assez faible est satisfaisant pour obtenir la grappe qui four-nit les requêtes d’injection réussie. Ainsi, pour un seuil situé entre 0.01 et 0.99, nous obtenons deux grappes.

La première grappe, constituée des requêtesDreq,Ereq,Freq,Greq, ne contient que des requêtes syn-taxiquement valides (Riv). La seconde grappe, quant à elle, contient des requêtes provenant des 3 en-sembles de requêtesRa,Riv etRii. Par conséquent, la première grappe nous permet donc d’identifier les requêtes d’injection réussie et la seconde grappe contient les autres requêtes, qui n’ont pas réussi à exploiter la vulnérabilité (qu’elles soient aléatoires, syntaxiquement valides ou invalides).

3.3 Génération des requêtes : utilisation des grammaires

Un objectif important de l’algorithme proposé est d’identifier la présence d’une vulnérabilité dans un point d’injection en fonction des réponses multiples générées à partir de ce point d’injection.

58 Détection de vulnérabilités par classification automatique des pages html

Pour améliorer la précision des résultats, il est nécessaire de générer un nombre suffisamment grand de requêtes permettant d’assurer une couverture élevée des différentes réponses pouvant être renvoyées par le serveur Web pour chaque point d’injection considéré. Notons que d’autres approches génèrent un nombre réduit de requêtes (par exemple, 3 pourSkipfish), ce qui peut donner lieu à des faux positifs, ce que nous voulons éviter dans notre approche.

Une manière possible de générer un nombre significatif de réponses (et les requêtes associées) est d’en-registrer dans un fichier statique, toutes les requêtes que l’on souhaite envoyer. En particulier, pour les requêtes de la catégorie Riv, on peut se baser sur les connaissances provenant d’experts en sécurité ou disponibles sur Internet (par exemple, utiliser les “SQL Sheets” [KIEZUN ET AL. 09]). Cette ap-proche présente l’avantage de pouvoir générer des requêtes particulièrement subtiles puisqu’elles sont produites par de réels experts du domaine. Son inconvénient majeur est qu’elle est statique et fastidieuse puisqu’il faut saisir une à une toutes les requêtes que l’on veut envoyer. En particulier, si l’on veut pou-voir envoyer des variantes d’un certain type de requêtes, il est nécessaire de toutes les imaginer et les écrire. Il en est de même pour les requêtes syntaxiquement invalides et les requêtes aléatoires.

Une approche plus flexible consiste à définir une grammaire ou un modèle pour automatiser ce pro-cessus. Cette approche comporte elle aussi des avantages et des inconvénients. Un des inconvénients est que l’écriture d’une grammaire ou d’un modèle est une opération pouvant s’avérer complexe, coû-teuse, et qui nécessite de disposer d’une spécification du langage concerné (SQL par exemple dans notre cas). Ce modèle ou cette grammaire peut de plus s’avérer inadapté si l’implémentation du langage ne respecte pas scrupuleusement les spécifications ou si l’application testée n’utilise qu’une partie de ce langage (par exemple, une application PHP qui n’utilise que les requêtes SELECT, qui ne représentent qu’une petite partie du langage SQL). D’un autre côté, cette approche présente des avantages certains. Elle permet de générer de façon complètement automatique un très grand nombre de requêtes. Dans le cas du langage SQL qui nous intéresse ici en particulier, la grammaire nous permet de générer une multitude de variantes d’un certain type d’injection. Ceci est très important dans notre approche car l’efficacité de l’algorithme de clustering repose sur le fait que l’on soit capable de générer un grand nombre de requêtes. Une grammaire peut également facilement être mise à jour si on envisage un nou-veau type d’injection que l’on n’avait pas considéré jusqu’à présent. L’avantage de la grammaire est qu’il suffit d’ajouter une règle pour pouvoir automatiquement générer une multitude de variantes de ce nouveau type d’injection. Nous en donnons des exemples dans les sous-sections suivantes.

3.3.1 Requêtes syntaxiquement valides :Riv

Du côté du serveur Web, la plupart du temps, une requête SQL est forgée par la concaténation de termes SQL et des paramètres envoyés par le client. Par exemple, le script PHP suivant traite l’authen-tification d’un utilisateur en donnant le nom d’utilisateur et mot de passe envoyés par le client :

$query = "SELECT id FROM users WHERE name=’$name’ AND pass=’$pass’";

Étant donné un couple correct (identifiant, mot de passe), la requête SQL forgée est considérée syntaxiquement correcte. En outre, la requête forgée associée au couple (identifiant, mot de passe) basée

3.3 Génération des requêtes : utilisation des grammaires 59

sur une attaque par dictionnaire est considérée comme syntaxiquement correcte, même si l’authentifi-cation a échoué.

A partir de cette d’observation, une injection SQL est définie comme une chaîne de caractère qui peut changer la sémantique de la requête SQL générée. Dans de nombreuses situations, une injection SQL est intéressante si elle conduit à une tautologie dans le clause WHERE de la requête SQL forgée. Dans l’exemple précédent, on peut considérer l’injection SQL suivante :

name="’ OR 1=1 OR string=’"

Par conséquent, la grammaire de l’injection SQL est juste une partie de la grammaire de la requête SQL. L’avantage de cette grammaire est qu’elle permet de générer facilement le nombre d’injections SQL dont nous avons besoin. Nous pouvons appliquer le même raisonnement à l’ensemble des mots générés aléatoirementRa et à l’ensemble Rii des injections SQL qui sont syntaxiquement invalides pour le point d’injection donné.

Voici, à titre d’exemple, une première version d’une grammaire pour l’ensemble de requêtesRiv, ex-primée en utilisant la notationBNF3:

I0 := String "’ " I1 Field Operator " ’" String %d10 %d13

I1 := ")" I1 "(" / I2

I2 := AndOr / AndOr I3 AndOr I3 := Not "(" I3 ")" / I4

I4 := Field Operator Field / Field Operator Field I1 Field Operator Field

String := *%d48-95

Field := " ’" String "’ "

Operator := "=" / "<" / ">"

AndOr := " or " / " and "

Not := " not " / ""

Cette grammaire génère différentes variantes d’attaques par injection SQL dont le principe consiste à insérer une tautologie dans une expression évaluée par une clause WHERE, de telle ma-nière que cette expression devienne une tautologie elle-même.

Sans perte de généralité, nous supposons que l’injection est réalisée à droite d’un opérateur (pour géné-raliser la grammaire, il suffit de prendre le symétrique). Pour réaliser une injection sur une zone entourée d’apostrophe, il faut forcer la fermeture de l’apostrophe, injecter la tautologie et ré-ouvrir l’apostrophe pour que la requête SQL générée soit syntaxiquement correcte (règle I0). Notons que dans cette règle, %d10 et %d13 représentent les caractèresCarriage ReturnetLine Feed. Pour la création de la tauto-logie – à la manière de la stratégie adoptée pour l’apostrophe – nous pouvons avoir besoin de forcer la

60 Détection de vulnérabilités par classification automatique des pages html

fermeture des parenthèses (règle I1). A chaque fermeture doit également correspondre une réouverture pour les mêmes raisons que précédemment. L’expression à injecter peut être composée d’une séquence de AND et de OU d’expressions parenthèses (règles I2, I3 et I4). De manière générale, ces règles ont été construites en s’assurant de l’équilibre dans le nombre de parenthèses ouvrantes et fermantes et d’apostrophes.

Cette grammaire permet de générer par exemple des injections de ce type :

OR ’’ = ’

A’ ) Or ( ’’ > ’<K

’ ) and ( ’’ < ’P0

:’ ))))) aNd ’’ > ’’ And ’’ > ’’ oR ’’ < ’E’ aND ((((( ’^P[’ > ’T

aNd ’>’ < ’

or ’I’ > ’;

<[C’ ) aNd ( ’’ > ’

’ ) and ’I’ > ’LUM’ AND ( ’PV’ < ’JV

B’ ) OR ( ’’ = ’

OR ’K’ > ’’ And ’’ < ’DU

Cette première version ne couvre pas toutes les injections listées dans les SQL Sheet traditionnel-lement proposées par les experts, mais elle peut être enrichie au fur et à mesure selon les besoins pour couvrir de plus en plus d’injections. Imaginons par exemple, qu’il soit nécessaire d’utiliser une clause UNIONpour générer une injection SQL efficace pour une application Web particulière. Imaginons que cette injection ait la forme suivante :

’ UNION SELECT ’klj’,’qdksfj’,’ma’ WHERE ’mlqskdjf’=’

Dans ce cas, il nous suffit simplement d’ajouter une règle permettant ce type d’injection dans notre grammaire, qui devient ainsi dans sa seconde version :

I0 := String "’ " I1 Field Operator " ’" String %d10 %d13

I1 := ")" I1 "(" / I2

I2 := AndOr / AndOr I3 AndOr / "union select " Liste " where "

I3 := Not "(" I3 ")" / I4

I4 := Field Operator Field / Field Operator Field I1 Field Operator Field

Liste := "’" String "’" / "’" String "’," Liste

3.3 Génération des requêtes : utilisation des grammaires 61

Field := " ’" String "’ " Operator := "=" / "<" / ">"

AndOr := " or " / " and "

Not := " not " / ""

Grâce à la modification de la troisième règle, cette nouvelle grammaire nous permet de générer cette nouvelle injection mais nous permet surtout de générer une multitude de variantes de ce type d’injection et c’est en ce sens que l’utilisation d’une grammaire est particulièrement utile.

Cette grammaire permet de générer par exemple ce type de requêtes :

’ )))uniON SelEct ’67417UJ’,’W]’ WHeRE ((( ’RE’ > ’

K’ ) OR ( ’:’ < ’

’ Union SElecT ’’ whEre ’\^’ < ’1

YBDH’ AND ’;’ = ’

’ ))) and ( NOT ( ’’ < ’1EF;U’ )) or ((( ’’ > ’]

6’ ANd ’[U<’ < ’

N58DR’ )UNion selECt ’’ whERe ( ’’ < ’9

and ( ’:WZFW’ > ’’ ) ANd ’’ = ’

\’ )uNIOn selecT ’’ whEre ( ’’ = ’S1RXW

’ )) or (( ’’ > ’

3.3.2 Requêtes aléatoires :Ra

La grammaire permettant de générer des requêtes aléatoires se limite à une seule règle :

STR = *%d48-95

Cette grammaire est très simple puisqu’elle ne comporte dans sa règle que des caractères al-phanumériques, dont les codes ASCII sont compris entre 48 et 95. Elle génère donc des chaînes de caractères aléatoires composées de ces caractères.

3.3.3 Requêtes syntaxiquement invalides :Rii

La grammaire permettant de générer des requêtes syntaxiquement invalides est constituée des règles suivantes :

I0 = STR I1 F O "’" STR / STR "’" I1 F O STR

62 Détection de vulnérabilités par classification automatique des pages html I2 = A / A I3 / I3 A I3 = N "(" I3 / N I3 ")" / I4 I4 = F O F / F O F I1 F O F STR = *%d48-95 F = " ’" STR "’ " O = "=" / "<" / ">" A = " or " / " and " N = " not " / ""

Cette grammaire va systématiquement fournir des requêtes d’injection SQL invalides car, quelle que soit l’injection qu’elle génère, le nombre d’apostrophes ou de parenthèses est impair (il est donc incorrect). Par exemple, la première règle indique que l’injection peut être réalisée en fermant une expression entre apostrophes puis en injectant une expression booléenne, mais sans ajouter d’apostrophe à la fin. L’équilibre du nombre d’apostrophes n’est donc pas assuré par cette règle.

Voici, à titre d’exemple, quelques requêtes qui peuvent être générées par cette grammaire :

NoT (( ’MX’ > ’\LC’ aND NOt not ( nOT ( ’’ > ’6>0HK’ )) ’’ > ’6I’ ) aND ( ’’>’

’T’ > ’’ aND ’H’ =’

L7’) ’V’ > ’0]^3’ Or ( ’’ <BV

) NOt ( noT nOt ( nOt ( nOt ’’ < ’8’ ) aNd ((( ’>’ > ’’ ))) Or (((( ’’ >’T

TRG?’) or (( ’’ <H

)) ’L’ > ’Y??’ ))) noT ( ’3’ = ’’ ANd ( ’’ = ’L’ Or ( ’RD’ >’UX

’ or ’’ =5

<I\X’ ’S’ = ’Y’ Or ’’ =M

’’ = ’’ aNd ’X’ <’

D4’) or ’’ <J_