• Aucun résultat trouvé

4.2 Résultat de l’évaluation

4.2.1 Évaluation de l’instrumentation

Dans cette section, nous allons nous intéresser à deux aspects de notre instru-mentation : la performance du processus d’instruinstru-mentation et la performance des mécanismes de détection ajoutés par l’instrumentation. L’évaluation du processus d’instrumentation consiste à évaluer en fonction des programmes la durée d’analyse nécessaire au calcul des invariants mais aussi le nombre d’invariants ainsi générés. Nous pourrons alors voir si ces performances varient d’un programme à l’autre et s’il est possible d’identifier l’origine de ces différences.

L’évaluation des mécanismes de détection eux-même a pour objectif de répondre à la question suivante : quelle surcharge à l’exécution est induite par notre instru-mentation. Nous nous attendons à ce que cette surcharge soit relativement faible. En effet, très peu de nouvelles instructions sont finalement ajoutées au code source original. Cependant, nous allons vérifier cela par un ensemble de mesures effectué à l’aide d’un outil dédié à cette tâche.

4.2.1.1 Performance de l’analyse

Nous avons présenté dans la section 2.3.1 deux exemples d’attaques contre les données de calcul exploitant une vulnérabilité réelle et permettant de réaliser une intrusion sans déviation détectable du flot d’exécution du programme. Nous avons appliqué notre mécanisme d’instrumentation sur la portion de code vulnérable et nous avons obtenu les invariants capables de détecter ces attaques (voir la colonne

de droite de la figure 2.3). Toutefois, pour évaluer pleinement notre système de dé-tection d’intrusion, il convient de tester notre approche sur des programmes entiers, sans connaissance a priori des vulnérabilités. Pour cela, nous choisissons de cibler pour notre évaluation des programmes réels mais néanmoins de taille modeste afin de limiter le temps nécessaire à l’instrumentation mais aussi à l’écriture des scénar-ios d’exécution (nous avons notamment remplacé OpenSSH [OSSH] par Dropbear SSH [DROPB]).

lbm mcf libquantum bzip2 milc sjeng

Nombre de lignes de code 1267 2077 3567 7292 12837 13291

Nombre d’appels de fonction 72 88 228 134 1274 1718

Durée d’analyse en minutes 12 8 122 1044 4123 5245

Nombre d’invariants générés 28 46 114 96 293 729

Taux d’instrumentation 38% 52% 50% 72% 23% 42%

Table 4.1 – Résultat de l’instrumentation des applications locales

Nous avons utilisé notre outil sur deux types de programmes. Des applications locales et des applications réseaux. Les applications locales sont celles que nous utilisons dans la section 4.2.1.2 pour évaluer la surcharge à l’exécution de nos mé-canismes de détection. Les applications réseaux sont celles que nous utilisons à la section 4.2.2 pour évaluer le taux de couverture de nos mécanismes de détection. Nous utilisons l’ensemble de ces programmes pour évaluer la performance de l’anal-yse. Les résultats de l’évaluation des performances de l’analyse sont présentés dans le tableau 4.1 pour les applications locales et dans le tableau 4.2 pour les applications réseaux.

dropbear ssmtp fnord ihttpd nullhttpd

Nombre de lignes de code 11177 2717 2622 1180 5968

Nombre d’appels de fonction 429 314 232 289 399

Durée d’analyse en minutes 962 19 224 1 317

Nombre d’invariants générés 257 237 6 109 234

Taux d’instrumentation 60% 75% 3% 38% 58%

Nombre d’injections générés 371 261 209 232 356

Taux d’instrumentation 86% 83% 90% 80% 89%

Nombre de cibles potentielles 1194 1872 5378 1248 2082

Nombre de cibles vérifiées 439 1829 40 363 1169

Couverture des invariants 36,8% 97,7% 0,7% 29,1% 56,1%

Tout d’abord, pour comparer les résultats en terme de durée d’analyse, il nous faut connaître la taille des programmes analysés. En effet, plus le programme à anal-yser est de taille conséquente, plus grande sont les chances que la durée d’analyse soit longue. Pour comparer la taille des programmes, nous avons choisi de nous fonder sur le nombre de lignes dans leur code source. Toutefois, afin de limiter le biais dû au style de programmation des développeurs respectifs des applications concernées, les codes source ont préalablement été modifiés. En premier lieu, nous avons sup-primé tous les commentaires. Les lignes de commentaires augmentent la taille du programme mais pas la durée d’analyse. Puis, nous avons réindenté automatique-ment les codes source. Ceci nous permet de normaliser le rapport entre le nombre de lignes des codes source et le nombre d’instructions qu’ils contiennent. Ensuite, pour analyser les résultats en terme d’invariants générés, nous allons tout simple-ment comparer les taux d’instrusimple-mentation des programmes. Ces taux sont calculés par rapport à l’ensemble des appels de fonctions présents dans le code source des programmes.

Malgré l’influence du nombre d’instructions sur la durée de l’analyse, on peut voir que cette durée peut grandement varier entre deux programmes de taille compa-rable. Par exemple, fnord [FNORD] est un programme presque douze fois plus long à analyser que ssmtp [SSMTP], bien que ces deux programmes soient de taille com-parable (respectivement 2622 lignes et 2717 lignes). Pour comprendre cela, ce n’est donc pas seulement le nombre d’instructions dont il faut tenir compte mais aussi les types d’instructions sur lesquels repose la sémantique du programme. Par exemple, dans le cas considéré dans ce paragraphe, on note que fnord utilise deux fois plus les instructions de boucle et manipule deux fois plus de pointeurs que [SSMTP]. La même observation peut être faite à propos du nombre d’invariants générés. À nou-veau, fnord et ssmtp, bien que de taille comparable, produisent chacun une analyse complètement différente. En effet, on obtient un taux d’instrumentation en terme de mécanismes de détection respectivement de 3% et de 75%. Là encore, il faut con-sidérer la sémantique du programme pour comprendre cet écart, notamment le fait qu’un plus grand recours à des multiples indirections via des pointeurs va rendre plus difficile la tâche de l’analyse de valeur.

Cet écart est encore plus grand si on compare le nombre de cibles potentielles (c’est-à-dire l’ensemble des variables injectables avant un appel de fonction) et le nombre de cibles vérifiées (c’est-à-dire l’ensemble des variables contrôlées par un invariant avant un appel de fonction). Le taux de couverture des invariants est le rapport entre ces deux données. Dans le cas de fnord et de ssmtp, celui-ci est respectivement de 0,7%s et 97,7%. Notons que, si dans cet exemple l’écart de per-formance en terme d’invariants générés est extrême, il est possible, comme le montre les tableaux 4.1 et 4.2, d’obtenir des taux d’instrumentation intermédiaires.

Notons également grâce au tableau 4.2 que si dans le cas des mécanismes de dé-tection le taux d’instrumentation peut grandement varier, ce n’est pas le cas pour les mécanismes d’injection. En effet, on obtient pour ces derniers un taux

d’instrumen-tation toujours supérieur ou égal à 80%. Ceci montre comme on pouvait s’en douter que la difficulté de calculer des invariants ne réside pas dans le calcul des dépen-dances mais dans le calcul des domaines de variation (voir les sections 2.3.2 et 2.3.3). Comme la durée d’analyse, le nombre d’invariants générés par notre approche dépend grandement de la sémantique du code source. Il n’est donc pas possible de généraliser les résultats obtenus sur ces exemples.

4.2.1.2 Surcharge à l’exécution

SPEC CPU2006 [SCPU06] est un test de performance pour évaluer les capac-ités de calcul des processeurs informatiques. Celui-ci repose sur un ensemble de programmes à compiler pour l’architecture concernée ainsi que sur un ensemble de jeux de tests intensifs pour chacun de ces programmes. Ce test de performance est maintenu par une association à but non lucratif nommée SPEC (pour Standard Performance Evaluation Corporation). Il s’agit d’un test standard dans l’industrie. Son utilisation pour évaluer la surcharge à l’exécution d’un processus d’instrumen-tation donne la possibilité de comparer objectivement notre approche avec d’autres travaux reposant également sur l’instrumentation. Nous avons sélectionné 6 pro-grammes parmi ceux proposés par le test de performance. Il s’agit des propro-grammes dont le code source est entièrement écrit en C (certains programmes peuvent con-tenir du C++ ou du FORTRAN ). Nous avons également éliminé de cette sélection le programme GCC afin de ne conserver que des programmes de taille réduite.

lbm mcf libquantum bzip2 milc sjeng

Score non-instrumenté 19.24 17.80 23.62 16.59 12.64 18.41

Score instrumenté 19.17 17.72 23.45 16.54 12.59 18.24

Surcharge à l’exécution 0.37% 0.45% 0.72% 0.30% 0.40% 0.93%

Table 4.3 – Résultat de l’analyse de la surcharge à l’exécution

Nous avons tout d’abord procédé un test de performance avec 10 itérations pour ces 6 programmes. Nous avons ensuite instrumenté ces programmes à l’aide de l’outil que nous avons développé. Notons que seuls les mécanismes de détection ont été ajoutés aux différents codes source. Puis, nous avons lancé un nouveau test de per-formance identique au précédent. Dans les deux cas la phase de tests a duré environ 700 minutes. Le tableau 4.3 présente les résultats de ces deux tests de performance. On peut voir que la surcharge à l’exécution induite par nos mécanismes de détection est très faible. Ce résultat était attendu. En effet, on ajoute environ 2% à 3% d’in-structions aux programmes et ces ind’in-structions ne reposent que sur des opérations booléennes qui sont de faibles consommatrices de cycles processeur. Notons que du-rant les tests de performance, à aucun moment nous n’avons observé de faux positifs. Il s’agit là également de la confirmation d’un résultat qui était attendu, ceci est en effet garanti par la sur-approximation dont fait preuve le calcul des invariants.