Calendrier de l'avent n°1 08/12/2022

Hybrid-Fuzzing, ou tests automatisés sous stéroïdes

Dans un logiciel, chaque bug est une occasion de plus pour un attaquant de voler des données ou prendre possession d’une machine, en plus de frustrer profondément l’utilisateur (et un peu aussi les développeurs que nous sommes, qu’on se le dise).

C’est pour cela qu’au fil des décennies diverses méthodes et outils ont été développés pour éviter d’en rédiger ainsi que pour leur faire une chasse acharnée. En ce qui concerne la chasse au bug, on trouve essentiellement deux paradigmes :

Tout d’abord, faire relire son code par autrui (humain ou machine) dans l’espoir qu’il y trouve des problèmes. Cela peut sembler bête et pourtant des entreprises entières se spécialisent dans ce sujet, on appelle cela un audit de code. Il s’agit alors d’une analyse statique du logiciel. Si cela est automatisée (par exemple avec une liste de choses standard à vérifier) cela ne coûte pas très cher, au risque de trouver des problèmes qui n’en sont pas. Si cela est fait manuellement, des problèmes plus subtils peuvent potentiellement (pas de garantie) être découvert, mais cela porte un certain coût financier et temporel.

Ensuite on peut l’exécuter dans toutes sortes de situations pour vérifier qu’il marche bien ou pour tenter d’y trouver des failles. Il s’agit alors d’une analyse dynamique du logiciel. S’il n’est pas envisageable de tester toutes les valeurs et situations qui peuvent exister au sein de notre logiciel, il reste encore la possibilité de choisir des cas particuliers. On espère que le bon comportement du logiciel face à ces cas particuliers soit représentatif du comportement global du logiciel. Je parle bien entendu ici des tests; unitaires, d’intégration, de non régression, de bout en bout, etc.

Serait-il possible de mélanger ces deux approches pour envoyer à notre logiciel exactement les bonnes valeurs pour le faire planter et ainsi s’épargner du temps d’exécution et de relecture ? Et bien OUI ! et il s’agit du thème du billet d’aujourd’hui : l’hybrid fuzzing.

L’idée est la suivante: tout d’abord le logiciel va examiner la fonction pour y trouver de potentiels points de faiblesse / d’intérêts:

  • allocation de mémoire
  • conditions de boucle
  • branchements conditionels

Ensuite il va consulter les tests que nous avons préalablement déjà rédigé pour tenter de s’assurer que le logiciel marche bien, (on peut ainsi guider sa recherche par exemple); ou générer des tests aléatoires pour tenter de voir quels chemins dans le logiciel/ le code tester sont facilement atteignables / ont déjà été atteints.

Il va en comprendre quels sont les endroits que nous avons le moins assurés jusqu’ici (quelles lignes par exemple ne sont jamais/difficilement parcourues). Il va alors tenter d’en déduire des valeurs / des situations à donner en entrée pour casser le logiciel.

Cette méthode est plus efficace qu’un bombardement sourd avec des valeurs aléatoires car elle tente d’éviter d’utiliser des valeurs différentes amenant aux même choix. Elle est aussi plus efficace qu’une recherche de tous les branchements possibles car elle tente constamment de casser le logiciel en passant par des chemins pas encore vérifiés / peu parcourus .

Voilà, vous avez été introduit à l’hybrid fuzzing ! Une méthode de test diablement ingénieuse.

Lien vers une vidéo youtube qui résume bien le propos, en français

Anonyme


IP7

Le robot d'IP7