• Aucun résultat trouvé

Découverte des messages : types et syntaxe

Partie I État de l’art 19

Chapitre 2 Rétro-ingénierie de protocoles 43

2.3 Découverte des messages : types et syntaxe

Une étape clé dans la rétro-ingénierie de protocoles est la découverte automatique des types de mes-sage et si possible la syntaxe associée. Comme précédemment mises en évidence, certaines techniques se basent uniquement sur les traces réseau alors que d’autres observent la machine hôte en même temps. Ces deux approches seront étudiées dans cette section.

2.3.1 À partir de traces réseaux

Initialement, la rétro-ingénierie de protocoles se faisait manuellement et était donc une tâche dif-ficile et longue à réaliser. Le projet Samba [5] a demandé 12 ans d’effort pour avoir une spécification utilisable. De ce fait, des méthodes automatiques sont rapidement apparues. Beaucoup d’entre elles et notamment les premières se sont basées sur des travaux en bio-informatique visant à établir des liens entre les différents gènes selon leur ressemblance grâce à des techniques d’alignement de séquences. [6] s’inspire de ces travaux en considérant que chaque paquet réseau correspond à une séquence. Deux types d’alignements sont exploités :

– un alignement local dont le but est d’extraire le type général du message ; – un alignement global visant à retrouver la syntaxe du message.

L’alignement local cherche à trouver deux sous-séquences similaires avec un score maximal et est notamment implanté par le biais de l’algorithme de Smith-Waterman [28]. Le score est calculé à partir des transformations nécessaires pour passer d’une séquence à une autre. Chaque transformation – insertion, substitution ou suppression – dévalorisera alors le score. D’un autre côté, quand aucune transformation n’est nécessaire, le score sera augmenté. Il mesure donc la similarité entre deux messages. Il devient alors possible de regrouper les messages selon leurs ressemblances.

La seconde étape d’alignement global, basée sur l’algorithme de Needleman-Wunsch [29], est assez similaire mais ne peut s’appliquer qu’à des messages identiques et donc de même type. En effet, elle considère les messages intégralement et ne se limite donc pas à chercher une sous-séquence seulement mais bel et bien une séquence globale. Par exemple, l’exemple suivant présente deux messages HTTP [7] réduits :

message 1 : GET /index.html HTTP/1.1 Host: loria.fr message 2 : GET / HTTP/1.0 Host: www.google.com On obtiendra alors l’alignement global suivant :

message 1 : GET /index.html HTTP/1.1 Host: ____lo_ria._fr message 2 : GET /__________ HTTP/1.1 Host: www.google.com

Pour aligner les séquences, des trous ont été introduits et correspondent à des insertions ou des substitu-tions selon le message considéré. De plus, certains caractères sont différents d’un message à l’autre. Un consensus est ensuite dérivé où l’ensemble des trous et des caractères différents sont remplacés par un caractère joker. Dans l’exemple précédent, le consensus est :

2.3. Découverte des messages : types et syntaxe

GET /?????????? HTTP/1.1 Host: ??????????????

La syntaxe des messages HTTP est alors partiellement dévoilée en ayant notamment mis en valeur les champs fixes (HTTP/1.1) ou les mots clés du protocole (GET, Host) et les champs variables (domaine, chemin d’accès).

PEXT [16] propose d’identifier les messages de même type grâce à un algorithme de classification assez simple : la classification ascendante hiérarchique [27]. En quelques mots, la méthode considère tout d’abord chaque message comme un groupe à part entière. Les deux groupes les plus proches sont alors réunis en un seul et ainsi de suite jusqu’à ce que la distance entre les groupes les plus proches soit supérieure à un certain seuil. La distance entre deux groupes est la distance minimale entre deux messages de chacun d’eux. Cette dernière est quant à elle fonction de la plus longue séquence de bits ou d’octets partagés en se basant sur un algorithme proche de ceux évoqués lors des techniques d’alignement de séquences. La reconstruction de la machine à états est aussi abordée dans ce papier et sera présentée dans la section suivante.

L’objectif de Discoverer [8] est de plus haut niveau puisque cette application ne cherche pas seule-ment à découvrir les différents types de messages mais aussi leurs formats. La première étape de Dis-coverer vise à délimiter les champs binaires et les champs de texte. Les octets de texte correspondent à des valeurs ASCII (American Standard Code for Information Interchange) ou Unicode [1], le reste étant considéré comme binaire. Un ou plusieurs champs textuels se retrouvent entre deux marqueurs binaires. Enfin, chaque segment de texte est divisé selon la présence ou non de séparateurs (espace, tabulation...). Chaque octet binaire est considéré comme un champ à part entière puisque ce type de découpage est impossible. L’étape suivante regroupe les messages ayant la même structure, c’est-à-dire le même en-chaînement de champs de texte et de champs binaires. Cette première classification incorpore aussi la notion de direction introduite dans la structure des messages car dans les protocoles clients-serveur, la na-ture des messages envoyés par l’un ou l’autre est souvent très différente. Pendant cette phase, les champs dynamiques et statiques peuvent aussi facilement être repérés.

A partir de ce point la sémantique des champs est étudiée pour repérer ceux de type longueur, dé-calage et cookie grâce à la méthode exposée dans [21] que les auteurs ont étendue (voir la section 2.5.3). Les décalages sont notamment repérés en comparant la différence entre la valeur numérique de deux champs par rapport à la différence de placement des champs suivants.

Grâce à cette sémantique et à la différenciation binaire/texte, les messages partageant exactement la même séquence sont rassemblés dans un groupe. Si aucune sémantique ne peut être associée, le contenu est directement comparé. Le nouveau format obtenu est donc de la forme :

format : champ*

champ : type, variable, sémantique type : binaire | texte

variable : statique | dynamique

sémantique : aucune | longueur | décalage | cookie

Ainsi Discoverer est capable d’inférer les formats des messages. Cependant, des messages de même format peuvent être de type distinct. On peut citer le cas du protocole SMTP [1] :

commande 1 : MAIL john@loria.fr commande 2 : RCTP oscar@inria.fr

Ces deux commandes sont bien de types différents (MAIL et RCTP) mais partagent le même format : deux champs variables sans sémantique dans le cadre des définitions précédentes. Les identificateurs de formats (IF) visent à différencier les deux types de messages. Ici le premier champ est un IF. Sans trop entrer dans les détails, un champ est assimilé à un IF lorsqu’un champ dynamique a un nombre de

GET /index.html HTTP/1.1 Host: loria.fr

FIGURE2.7 – Analyse par tainting

valeurs possibles réduit. Ensuite pour chacune de ces valeurs, le groupe est séparé en deux. Dans le cas de l’exemple ci-dessus, il faut bien entendu que les traces capturées soient assez conséquentes de manière à observer plusieurs messages MAIL et RCTP.

Après ces différentes phases de classification, Discoverer découvre beaucoup plus de formats de messages qu’il en existe réellement. Cela provient de la classification initiale qui impose aux messages d’un même groupe d’avoir exactement la même structure. Une ultime phase consiste donc à regrouper les groupes (ou formats) en utilisant l’alignement de séquences [29] non plus octet par octet mais champ par champ ou deux champs sont égaux si et seulement si ils sont de même type (binaire ou textuel) et s’ils partagent la même sémantique ou ont au moins une valeur commune.

Les deux principaux inconvénients de cette méthode sont l’absence de sémantique associée aux champs binaires (chaque octet est un champ à part entière) ainsi que l’utilisation supposée de sépara-teurs prédéfinis (espaces, tabulations...), ce qui représente une condition assez forte.

Dans [19], l’approche avancée est semi-automatique puisqu’elle demande à l’utilisateur d’être ca-pable d’identifier manuellement au préalable le champ qu’il souhaite extraire du message, ce champ peut alors correspondre au type du message. La méthode d’apprentissage employée consiste à générer des exemples représentant le champ extrait. Ils correspondent en fait à des conditions sur les octets du message. Par exemple, le champ délimité par l’utilisateur peut toujours être précédé par un octet égal à 00. Des contre-exemples sont générés également. L’ensemble de ces exemples servent alors à extraire ce champ dans un autre message et l’utilisateur confirme si la réponse est bonne ou mauvaise. Ce processus continue ainsi de manière incrémentale jusqu’à ce que l’utilisateur considère que le système est assez efficace.

2.3.2 En observant la machine hôte

Caballero et al. [15] constatent que les traces réseaux manquent de sémantique et la difficulté pour associer une sémantique aux différents champs d’un message a été mise en évidence au paragraphe précédent. Le système exposé dans ce papier se nomme Polyglot et l’approche consiste à analyser dy-namiquement la manière dont un message est traité. La première étape doit extraire une trace d’exécution système à partir d’un message et de l’analyse du programme qui le traite grâce à une technique de tainting [14]. Cela demande de marquer chaque paquet arrivant sur l’interface réseau de la machine et à propager ce marquage sur chaque résultat d’opération appliquée sur les données de celui-ci. Une opération peut être arithmétique, logique ou un déplacement de données. Le marquage indiquera quelle partie des

don-2.3. Découverte des messages : types et syntaxe nées originales sont utilisées. Par exemple, lorsqu’un champ est extrait du message et stocké dans un registre, ce registre se retrouve marqué. Le cas simple d’une requête HTTP et la manière dont elle peut être traitée sont proposés sur la figure 2.7. En fait différents champs sont extraits et le but de l’analyse par tainting est de garder en mémoire d’où proviennent ces différents champs.

De manière résumée et en reprenant la nomenclature des types de champs précédemment introduite, Polyglot procède de la manière suivante. Pour les champs de positions tels que les pointeurs ou les décalages, il suffit de voir qu’une donnée marquée est employée pour effectuer un déplacement (comme par exemple une boucle pour avancer dans les données). Les données pointées par ces positions sont logiquement considérées comme des champs de longueurs variables. Intuitivement, un protocole utilisant des séparateurs ou des mots clés va effectuer des comparaisons qui sont comptabilisées par Polyglot. Dans le cas d’une requête HTTP comme sur la figure 2.7, l’application bouclera sur les octets en comparant leur contenu aux différents séparateurs possibles (espace, tabulation...). Enfin, tout autre donnée marquée mais non traitée par une de ces techniques correspond à un champ de longueur fixe.

Cette première approche reste toutefois limitée à l’analyse d’un message à la fois et aucune méthode de classification ne permet de faire des regroupements comme avant pour essayer d’inférer les différents types de messages ainsi que leurs formats.

AutoFormat [10] a pour ambition de retrouver, en plus des différents champs, la structure hiérarchique qui leur est associée c’est-à-dire d’être capable de retrouver une spécification semblable à celle fournie par une grammaire ABNF. Effectivement, sur l’exemple ci-dessous extrait de la grammaire du protocole HTTP, il est clair que le champ Request-Line est divisé en plusieurs autres telle une relation hiérarchique : Request = Request-Line

*(( general-header | request-header | entity-header ) CRLF ) CRLF [message-body]

Request-Line = Method SP Request-UTI SP HTTP-Version CRLF

Il existe aussi une relation séquentielle entre certains champs comme sur la dernière ligne de cet exem-ple. De plus, les champs interchangeables, tout en respectant la grammaire, respectent une relation dite parallèle à l’instar des différentes entêtes (headers) dans l’exemple. La méthode appliquée est proche de la précédente (Polyglot) mais introduit en plus la notion de pile d’exécution. La trace d’exécution corre-spond aux différentes opérations sur les données marquées (tainting) tout en conservant en mémoire une représentation de la pile à l’exécution. Ensuite, toutes les actions successives avec la même pile sont re-groupées en une seule pour créer un nœud. Dans le cas contraire (pile différente), un nœud à part est créé et rattaché à un autre précédemment créé qui contient en partie les même données ou, à défaut, au nœud racine. Par exemple, si le texte “GET /index.html” a été déplacé à un endroit de la mémoire et ensuite seulement “GET”, le nœud induit par le second déplacement sera un fils de celui généré par le premier car “GET” est une donnée marquée contenue dans “GET /index.html”. Après un affinement secondaire de l’arbre, un historique des piles d’exécution est adjoint à chaque nœud et correspond à l’évolution de celle-ci à travers l’ensemble des ancêtres du nœud en question. Deux nœuds partageant un historique similaire sont supposés parallèles car ils se sont exécutés dans le même contexte. À partir de ces relations hiérarchiques et parallèles, les relations séquentielles sont alors facilement extraites.

AutoFormat est donc capable d’extraire ces différentes structures sur un message pour notamment en dériver une structure hiérarchique. Le seul inconvénient est qu’il n’est pas pour l’instant capable d’inférer la syntaxe du protocole puisque seul un message est utilisé. C’est dans cette optique que Wondracek et al. ont proposé [12]. En utilisant des techniques similaires à Polyglot [15], la sémantique associée aux champs est mise en exergue. Les auteurs arrivent notamment à extraire deux types de champs : les chemins d’accès à des fichiers et les données communes à une requête et à sa réponse, ce qui est seule-ment possible en utilisant de multiples messages. Une structure hiérarchique est aussi induite en repérant

Message 1 Mot−clé X Mot−clé Y Séparateur "/" Mot−clé K Token Message 2 Mot−clé X Mot−clé Z Séparateur "/" Token

(a) Alignement de deux messages

Message Mot−clé X Mot−clé alternatif Y | Z Séparateur "/" Mot−clé optionnel K Token (b) Arbre général

FIGURE2.8 – Déduction du format général d’un message

les données marquées (tainting) qui sont des sous-parties d’autres données marquées elles aussi. Un ar-bre général est déduit en exploitant les techniques d’alignement de séquences [29] sur plusieurs arar-bres. L’alignement est d’abord appliqué sur les feuilles des arbres d’après leurs sémantiques. Par exemple, des champs de longueurs correspondent si leurs tailles sont identiques, si les champs qu’ils délimitent correspondent aussi. Le score de chaque alignement est propagé aux nœuds pères et ainsi de suite pour obtenir un score global. L’exemple donnée dans la figure 2.8 repris de [12] donne un aperçu du fonc-tionnement de l’alignement et surtout de son résultat. Au premier niveau (le plus bas), un token (champs sans sémantique associée) est délimité par le caractère séparateur “\\” mais le premier message comporte en plus le mot-clé K, l’alignement va donc insérer un blanc (suppression) à cet endroit. En appliquant ce processus récursif en remontant l’arbre, il apparaît que la structure des messages est identique exceptée pour les mots clés Y et Z, le résultat de l’alignement dans ce cas là est donc une substitution. L’étape finale consiste alors à traduire cet alignement en format de messages où une suppression concorde avec quelque chose d’optionnel tandis qu’une substitution représente une alternative comme présenté dans la figure 2.8(b)

Cui et al. [11] s’inspirent des travaux précédents basés sur l’analyse par tainting tout en mettant en lumière leurs limitations. Tout d’abord, les messages ne comportent pas uniquement des champs mais aussi des données de taille variable, comme par exemple un fichier multimédia. Deuxièmement, les valeurs des différents champs peuvent être contraints entre eux à l’instar des vérifications par somme de contrôle (checksum en anglais) ou les numéros de séquences et d’acquittements TCP. Ces informations sont essentielles pour produire efficacement des signatures pour les attaques de type 0-jour (ou 0-day en anglais) [35]. Le système proposé, Tupni, recherche les différentes séquences de données en cherchant les boucles permettant de les lire, c’est-à-dire des boucles telles que chaque itération traite une nouvelle partie du message. En se basant sur la trace d’exécution d’une application et notamment les différentes conditions testées, Tupni déduit les différentes contraintes par rapport aux données marquées, c’est-à-dire le message original.

2.4. Apprentissage de la machine à états

Documents relatifs