Thèse soutenue

Fuzzing et méthodes symboliques pour la détection de vulnérabilités à large échelle

FR  |  
EN
Auteur / Autrice : Yaëlle Vinçont
Direction : Sylvain ConchonSébastien Bardin
Type : Thèse de doctorat
Discipline(s) : Informatique
Date : Soutenance le 15/12/2021
Etablissement(s) : université Paris-Saclay
Ecole(s) doctorale(s) : École doctorale Sciences et technologies de l'information et de la communication
Partenaire(s) de recherche : Laboratoire : Laboratoire Méthodes formelles (Gif-sur-Yvette, Essonne ; 2021-....) - Laboratoire d'intégration des systèmes et des technologies (Gif-sur-Yvette, Essonne ; 2001-....)
référent : Faculté des sciences d'Orsay
graduate school : Université Paris-Saclay. Graduate School Informatique et sciences du numérique (2020-....)
Jury : Président / Présidente : Mihaela Sighireanu
Examinateurs / Examinatrices : Jean-Yves Marion, Michail Papadakis, Emmanuelle Encrenaz
Rapporteurs / Rapporteuses : Jean-Yves Marion, Michail Papadakis

Résumé

FR  |  
EN

Alors que les programmes informatiques se répandent, le risque de bugs augmente. Dans cette thèse, nous voulons trouver d'éventuels bugs dans des programmes finis et publics. Pour cela, nous utilisons la génération automatique de tests. Complémentant les tests écrits à la main, les générateurs de tests fabriquent automatiquement une série de tests, avec pour but de maximiser la couverture de code et de minimiser l'effort humain. Actuellement, les techniques de génération de test les plus répandues dans l'académique et dans l'industrie sont basées sur l'exécution symbolique ou le fuzzing.- L'exécution symbolique vise à explorer complètement les chemins d'exécution. Pour cela, chaque chemin est exécuté sur une entrée symbolique, et une contrainte est inférée sur cette entrée. Quand l'analyse atteint la fin d'un chemin, cette contrainte est un prédicat de chemin, et l'exécution concrète du programme sur n'importe laquelle de ses solutions suivra le chemin voulu. De telles entrées concrètes sont générées avec un solveur de contraintes, et forment la série de tests. Cependant, il n'est pas toujours possible d'explorer tous les chemins en un temps raisonnable, et il est souvent nécessaire de borner l'exploration.- Le fuzzing vise à exécuter le programme sur de nombreuses entrées, en espérant explorer tous les chemins possibles. Il dépend donc d'une génération d'entrées rapide et facile. Tandis que les fuzzers de base fonctionnent en boîte noire et génèrent des entrées aléatoires indépendamment du programme, les fuzzers en boîte grise utilisent une analyse pour obtenir des informations à propos du programme. Ces informations sont alors utilisées pour améliorer la génération d'entrées. Cependant, malgré ces améliorations, les fuzzers ont toujours de la difficulté à trouver la solution de conditions qui ont une faible probabilité d'être vraies. Ainsi, l'exécution symbolique et le fuzzing exhibent des forces et des faiblesses complémentaires, nous poussant à les combiner. Pendant cette thèse, nous avons développé une technique de génération de test automatisée, qui combine la puissance de raisonnement de l'exécution symbolique pour s'attaquer au code complexe, et le faible coût du fuzzing pour générer des entrées efficacement. La solution que nous proposons combine deux nouvelles idées: l'Exécution Symbolique Légère (ESL) et le Fuzzing Contraint. L'Exécution Symbolique Légère est une variante de l'exécution symbolique où l'analyse s'arrête sur une condition d'un chemin, plutôt qu'à la fin, et le langage de contraintes ciblé est réduit à un fragment facilement énumérable de l'habituel. Par conséquent, dériver des prédicats de chemin (corrects) dans ce langage est plus compliqué, mais il est facile d'énumérer des entrées exerçant un chemin, sans utiliser de solveur de contraintes. Deuxièmement, le Fuzzer Contraint manipule une entrée et une contrainte facilement énumérable, et génère de nouvelles entrées qui satisfont la contrainte et suivent donc le chemin, jusqu'à la condition ciblée. En général, l'ESL guidera l'exploration au-delà des conditions difficiles et vers les parties intéressantes du code, tandis que le fuzzer contraint créera efficacement des entrées, y compris des solutions aux contraintes. Cela nous permet d'explorer le programme sans systématiquement faire appel à l'analyse symbolique, et supprime la dépendance à un solveur pour créer des entrées satisfaisant les contraintes. Nous avons évalué les performances de l'outil utilisant ces techniques, appelé ConFuzz, sur un banc de tests standard du fuzzing. La conclusion de cette expérimentation est que ConFuzz a de meilleures performances que l'état de l'art du fuzzing et de l'exécution symbolique.