Machines virtuelles et honeypots
Signature : | Mis en ligne le : 16/10/2008
Catégorie(s) :
  • Misc
  • | Domaine :
    Commentez

      Retrouvez cet article dans : Misc 21

    Tous les jours, nous mettons en place des systèmes permettant d'assurer le contrôle, l'intégrité et la sécurité de nos réseaux et des données transmises. Qu'il s'agisse de firewall, ids, antivirus, canaux chiffrés,… tous ces systèmes ont des limites et l'utilisateur-administrateur averti a pour devoir de connaître ces limites sous peine de graves désillusions. Les pots de miel (honeypots) sont des outils permettant l'observation d'attaques sur un réseau. Le principe des honeypots est assez amusant. Imaginez un instant que vous invitiez un cambrioleur  chez vous pour pouvoir l'observer. Pour cela, vous devez lui faire croire que vous êtes parti et donc trouver une bonne cachette pour pouvoir l'observer sans être remarqué. Il faut aussi être bien assuré en cas de vol effectif. Si vous êtes repéré, tout peut dégénérer. Le problème de furtivité est donc crucial dans ce type d'observation. Je vais vous montrer comment on peut repérer un honeypot en considérant son implémentation.

    1. Honeypot : le risque contrôlé ?

    Un honeypot [1] est un système sans activité légitime qui a pour fonction d'attirer un éventuel trafic malicieux. Par trafic malicieux, je veux parler de tous les maux possibles qui peuvent survenir quand on met en place un réseau avec un accès vers l'extérieur ou avec des utilisateurs au comportement intempestif : ver, pirate... Si une activité est déclarée, l'administrateur système peut alors prendre les mesures adéquates pour sécuriser son réseau. Une application plus ambitieuse des honeypots consiste aussi à observer l'attaquant. Lutter efficacement contre les pirates et leurs avatars exige d'avoir des modèles de leur comportement : réactivité, ingéniosité... Un honeypot permet d'attirer l'attaquant ; reste à l'observer pour découvrir ses outils, ses failles favorites. C'est le but des sondes d'espionnage comme sebek qui permettent d'enregistrer toute frappe au clavier de l'attaquant. On peut ainsi résumer en 3 grandes activités les fonctions que doit avoir un honeypot :
    • surveillance : toute activité en provenance ou à destination du honeypot est à contrôler. [HOSUS]
    • espionnage : permet la collecte d'informations sur le mode opératoire de l'attaquant. [SEBEK]
    • analyse : tout dépend de l'utilisation ; cela peut aller de la modélisation de l'attaquant en passant par la contre-mesure ou le choix des options de restauration du réseau après attaque.
    Un firewall peut être contourné, un ids leurré, l'anti-virus doit être à jour; il n'y a pas de système de sécurité parfait... et les honeypots ? Le risque est immense : on s'est tout de même permis d'inviter l'attaquant, on a inséré sciemment des failles dans le système. Si l'attaquant réussit à sortir du honeypot, alors la boîte de Pandore est ouverte. Donc il est crucial que notre honeypot soit furtif, c'est-à-dire que personne ne soit capable, quand il accède à une machine à distance, de déterminer s'il accède à une vraie machine ou un pot de miel. Tout ceci n'a pas l'air simple, nous allons essayer d'y voir plus clair.

    2. Comment faire un honeypot ?

    Le monde des honeypots est riche et varié. La classification des honeypots a été faite suivant le niveau d'interaction qu'ils offrent. Plus le niveau d'interaction augmente et plus l'implémentation est difficile. Le summum du honeypot est un honeypot qui offre tous les services d'un système d'exploitation. Nous allons nous intéresser en particulier à ces honeypots à haut niveau d'interaction car leur réalisation est très particulière et ce sont ceux qui permettent de collecter le plus d'information sur les attaquants. Il existe plusieurs façons de faire des honeypots à haut niveau d'interaction. On peut améliorer une machine avec des outils comme sebek et uberlogger, mais cela a l'inconvénient de permettre à l'attaquant de pouvoir atteindre le mode privilégié de la machine. S'il est capable de détecter les outils comme sebek, cela peut devenir embêtant. Or depuis SSTIC 2004, on sait qu'il n'est pas difficile de détecter sebek [2]. L'autre solution possible est d'employer la virtualisation. La virtualisation permet de faire fonctionner plusieurs environnements indépendants sur une seule machine. Deux systèmes d'exploitation cohabitent sur un honeypot employant une machine virtuelle. Le premier système d'exploitation sera considéré comme la partie sécurisée de notre installation. Le deuxième système d'exploitation sera la partie compromise et est donc de ce fait sous le contrôle complet du premier. Le principal avantage de cette architecture est la séparation ou isolation des modes privilégiés des deux machines. Ainsi l'acquisition des droits de root sur le système compromis ne donne pas accès au mode privilégié de la machine physique. Le principe de virtualisation peut être interprété de nombreuses façons. Sur cette excellente page [3], vous trouverez un comparatif des solutions de virtualisation existante. L'élément central de la virtualisation est la couche matérielle qui est composée :
    • du processeur qui peut correspondre ou non à celui de la machine hôte. Dans les deux cas, le mode privilégié du processeur est émulé. La différence entre processeur totalement émulé (PearPC, Xen,...) et partiellement émulé (WMware, UML,...) se fait donc au niveau de la couche utilisateur. Cela se traduit donc par une translation (ou non) du jeu d'instructions du processeur émulé vers le processeur hôte. C'est parfois nécessaire quand on veut faire fonctionner un système d'exploitation lié à une architecture.
    • de la gestion de la mémoire qui peut être déléguée au niveau du processeur (MMU),mais qui doit garantir la compatibilité entre la mémoire physique et la mémoire logique virtuelle.
    • des Entrées/Sorties ce qui signifie disposer d'interruptions et d'un certain nombre de périphériques virtuels(ou non).
    A tous ces mécanismes, il faut ajouter des éléments de contrôle (Virtual Machine Monitor) sur le système hôte pour pouvoir gérer l'exécution des différentes machines virtuelles. Je vais présenter 2 techniques de détection fondamentales de ce type d'architecture. Il y a une grande différence entre émuler une technologie et l'implémenter, certaines caractéristiques sont éliminées lors de l'émulation. Mais tout d'abord,nous allons nous concentrer sur la notion de flot d'exécution dans un processeur qui est supervisé par un système d'exploitation comme Windows ou Linux.

    2. Exécution

    L'exécution d'un bout de code sur un processeur n'est pas quelque chose de linéaire. De nombreuses interruptions matérielles ou logicielles provoquent des discontinuités dans le flot d'exécution. Ces discontinuités ont des effets importants sur les mécanismes d'optimisation du processeur comme le cache, le pipeline, la prédiction de branchement... et donc la régularité d'exécution du code sera affectée. Pour illustrer ce principe, étudions le comportement d'une boucle (Figure 1) très simple.

     /img-articles/misc/21/art-4/fig-1.jpg

    Dans un premier temps, nous exécutons la boucle 1 sans privilège particulier. Dans la figure 2, on voit clairement que l'exécution de la boucle est tout sauf régulière,car en même temps, il y avait une activité sur la machine (je copiais un fichier de 10Mo). Ces irrégularités sont provoquées par les interruptions et les mécanismes d'optimisation du processeur. Il est relativement facile de faire le lien entre interruptions et régularité d'exécution : on va utiliser l'instruction x86 cli pour éliminer les interruptions. C'est ce que l'on voit dans la figure 3. L'instruction cli (CLear Interrupt flag) permet de désactiver toutes les interruptions masquables.

     /img-articles/misc/21/art-4/fig-2.jpg

     /img-articles/misc/21/art-4/fig-3.jpg

    Les figures 2 et 3 sont radicalement différentes. On a bien l'impression que certains événements n'ont plus lieu quand on élimine les interruptions mais globalement l'observation de ces 2 courbes ne nous permet pas d'affirmer grand-chose (ceci est dû principalement à l'échelle).

    Pour mieux quantifier les différences entre ces deux courbes, nous traçons leurs diagrammes d'autocorrélation respectifs. Le diagramme d'autocorrélation est un outil très pratique pour évaluer le caractère aléatoire d'un ensemble de données [3]. De façon simple, l'autocorrélogramme quantifie la similitude entre une courbe Yt et cette même courbe décalé Yt+h ; il nous permet de voir s'il y a des événements liés dans notre ensemble de données.

    /img-articles/misc/21/art-4/f1.jpg

    /img-articles/misc/21/art-4/fig-4.jpg

    Quand on ignore les interruptions, l'autocorrélogramme montre des phénomènes quasi-périodiques. Si les interruptions sont prises en compte, l'autocorrélogramme n'indique pas de corrélations particulières (déterminer s'il s'agit d'un phénomène aléatoire est un problème plus compliqué). On se rend compte qu'avec notre simple boucle, on est capable de détecter l'activité d'une machine. Les grandes variations sont provoquées par les interruptions. Sur les figures 2 et 3, on ne voit que les grandes variations sur le temps d'exécution. Si on fait un zoom sur ces courbes (figure 5), on voit qu'il y a aussi des variations de moindre ampleur. La figure 5 est pleine d'enseignements. Même si on observe des mesures sans interruption, des variations sont toujours présentes. Ces variations sont assez difficiles à expliquer car quand on effectue un appel à la fonction printf(), on accède à des ressources en dehors du processeur (bus, carte graphique, carte son, disque dur,...) et à des ressources comme des tampons mémoires. Notre boucle fait aussi un accès mémoire, donc potentiellement on devra aller chercher les données en RAM pour les stocker en cache. Finalement l'exécution de notre simple boucle est bien difficile à comprendre.

    /img-articles/misc/21/art-4/fig-5.jpg

    On peut comprendre facilement les variations liées à la hiérarchie mémoire. Le cache est divisé en plusieurs blocs qui sont chargés ou évincés du cache. Les accès au sein d'un même bloc sont rapides (cache hit) tandis qu'en cas d'absence de la donnée du cache (cache miss), on doit charger un bloc. Si on fait des accès linéairement à une table, on va pouvoir observer les changements de bloc. De façon théorique, le programme de la figure 6  va nous permettre de faire la rétro-ingénierie des paramètres du cache du processeur (tableau 1).

    /img-articles/misc/21/art-4/fig-6.jpg

    Dans les figures 7 et 8, j'ai réalisé les évaluations des tailles de blocs sur différents processeurs. Rassurez-vous, on retrouve bien les paramètres des fondeurs. Maintenant, nous disposons de suffisamment d'éléments pour comprendre les grandes et petites variations de la boucle de la figure 1. Cette analyse du flot d'exécution est intéressante, car on peut la voir comme une empreinte laissée par le processeur et le système d'exploitation sur un morceau de code exécuté.

    /img-articles/misc/21/art-4/t1.jpg

    /img-articles/misc/21/art-4/fig-7.jpg

    /img-articles/misc/21/art-4/fig-8.jpg

     

    Si un attaquant envahit une machine et ne retrouve pas une empreinte normale alors il peut fuir ou tenter de déborder la machine virtuelle. Nous allons voir ce que l'on peut faire avec nos boucles quand on les exécute sur des machines virtuelles comme PearPC ou VMware. Quand on utilise un outil comme PearPC ou XEN, l'architecture de la machine virtuelle peut reposer sur un processeur différent du processeur physique. Cela signifie que les petites variations sur le temps d'exécution du code vont être celle du processeur hôte et pas celle du processeur émulé. Cela tient au fait que PearPC ou XEN n'implémente pas l'architecture du processeur (pipeline, cache...). Une simple boucle cherchant à estimer les paramètres de l'architecture sera suffisante pour détecter ce type d'anomalie. Pour les outils comme UML ou VMware, on va plutôt regarder ce qui se passe quand on désactive les interruptions. On est alors capable de voir l'activité du système d'exploitation superviseur à partir d'une exécution sur le système compromis.

    3. Deux processeurs différents

    Un attaquant peut détecter quand il accède à une machine MacOSX/PPC qu'il s'agit en réalité d'une machine Linux/x86 faisant fonctionner PearPC par exemple. C'est très simple : il peut tout d'abord vérifier la taille des blocs de cache. La figure 9 vous donne la réponse : un attaquant est capable de retrouver les caractéristiques physiques du processeur qui fait tourner la machine virtuelle. Ma machine PearPC tournait sur un Pentium 4. PearPC n'a pas de mécanismes de simulation des caches. Donc on ne peut pas recommander d'utiliser des produits permettant d'installer des honeypots supposant des architectures processeurs différentes (même au sein de la famille x86) de celle de la machine hôte. Pour détecter ce type d'architecture, l'attaquant quand il se connecte récupère toutes les informations possibles sur la machine. Il obtient des informations sur le processeur grâce à /proc/cpuinfo sous Linux ou sous arch, machine sous BSD. A partir de ces renseignements et de ceux du fondeur (toutes les caractéristiques des puces sont accessibles sur les sites web) et des programmes de rétro-ingéniérie, l'attaquant peut détecter la fraude au processeur.

    /img-articles/misc/21/art-4/fig-9.jpg

    4. Deux systèmes : un processeur

    Les outils comme VMware, UML sont en conformité quant aux caractéristiques du processeur. Reste que si on a deux systèmes d'exploitation, on a aussi beaucoup plus d'activité. Ceci signifie aussi que, quand on modifie le mode d'exécution sur la machine virtuelle (changement d'algorithme d'ordonnancement ou désactivation des interruptions), cela n'affecte pas l'exécution des processus sur le système hôte. Il suffit donc de faire quelques observations sur la régularité d'exécution pour se rendre compte qu'il y a une activité anormale. Pour bien comprendre la figure 10, il faut la comparer à la figure 4. Si on désactive les interruptions ou si on change l'algorithme d'ordonnancement (on utilise l'algorithme FIFO par exemple), notre exécution est très régulière. Maintenant en répétant les mêmes manipulations sur VMware, on ne retrouve pas du tout les mêmes corrélations. Le résultat est sans appel.

    /img-articles/misc/21/art-4/fig-10.jpg

    Je vous ai montré qu'il était difficile d'émuler du matériel car beaucoup trop de caractéristiques devraient être prises en compte. Maintenant que nous savons détecter ce qui est virtuel du réel, le but suprême de l'attaquant est de sortir de la matrice. Pour cela, il peut choisir de s'attaquer au matériel virtuel. Les périphériques à la disposition des systèmes d'exploitation virtualisés peuvent ou non être émulés. S'ils sont émulés, alors toutes les fonctionnalités du périphérique ne sont finalement que des fonctions et de la mémoire gérée par le système hôte. Pour comprendre comment tout cela marche, je vous invite à consulter le code de QEMU de Fabrice Bellard qui est d'une remarquable clarté. Il n'est donc pas impossible de trouver des failles pour s'échapper du honeypot via ces " tuyaux ". Le problème semble plus difficile quand le matériel existe vraiment, mais que son usage est restreint pour la machine virtuelle. Il est aussi tout à fait notable que les fondeurs de processeurs s'intéressent depuis peu au support matériel des machines virtuelles. Des fonctions supplémentaires sont ajoutées au processeur pour améliorer la sécurité des machines virtuelles : c'est par exemple le projet Pacifica chez AMD et IVT pour Intel. Pour l'instant, seule la sécurité et le confinement ont été pris en compte. Restera toujours la furtivité...

    6. Conclusion

    Le flot d'exécution d'un processus est très difficile à modéliser sur un processeur superscalaire general purpose. Les interruptions et les mécanismes d'optimisation des processeurs nous permettent d'obtenir une empreinte du matériel sur lequel on accède. J'ai présenté brièvement 2 techniques permettant de reconnaître les machines virtuelles à partir de l'analyse du flot d'exécution. L'avantage de ces attaques est qu'elles sont très génériques. Il existe d'autres moyens pour détecter les machines virtuelles et les honeypots. Pour cela, je ne peux que vous recommander la lecture de [4,5] pour les aspects détection système et de [6,7] pour les aspects de détection réseau. A cela, il faut ajouter la fameuse pilule rouge [8] de Joanna Rutkowka qui permet de détecter WMware en une instruction.

    Références

    [1] Dossier : les pots de miel (honeypots), Misc 8. [2] Gael DELALLEAU, " Mesure locale des temps d'exécution : Application au contrôle d'intégrité et au fingerprinting ", SSTIC 2004. [3] http://en.wikipedia.org/wiki/Comparison_of_virtual_machines [3] http://www.itl.nist.gov/div898/handbook/ [4] Frederic Raynal, Thorsten Holz, " Defeating Honeypots : System Issues, Part 1 " [5] Thorsten Holz, Frederic Raynal, " Defeating Honeypots : System Issues, Part 2 " [6] Laurent Oudot, Thorsten Holz, " Defeating Honeypots : Network issues, Part 1 " [7] Laurent Oudot, Thorsten Holz, " Defeating Honeypots : Network Issues, Part 2 " [8] Joanna Rutkowska, Red Pill, http://invisiblethings.org/papers/redpill.html

    Retrouvez cet article dans : Misc 21

    Vous souhaitez commenter cet article ?
    Brèves Flux RSS
    Édito : GNU/Linux Magazine 149
    Édito : GNU/Linux Magazine HS N°60
    Édito : Misc 61
    Édito : Linux Pratique 71
    Édito : Linux Essentiel N°25
    Communication RSS Com. RSS Presse
    Lancement de la plateforme de vente en ligne de PDF des Éditions Diamond ! Un...
    Misc N°61 – Communiqué de presse
    GNU/Linux Magazine N°149 – Communiqué de presse
    GNU/Linux Magazine HS N°60 – Communiqué de presse
    Linux Pratique N°71 – Communiqué de presse
    prochainement moteur de recherches des articles
     
    :
    :
    Jours heures minutes secondes
    En kiosque Flux RSS

    Le tout nouveau GNU/Linux Magazine est disponible dès maintenant chez votre marchand de journaux et sur notre site marchand.

    Découvrez le sommaire de ce numéro et un aperçu de ce magazine...

    Lire la suite...

    Le tout nouveau Misc est disponible dès maintenant chez votre marchand de journaux et sur notre site marchand.

    Découvrez le sommaire de ce numéro et un aperçu de ce magazine...

    Lire la suite...

    Le tout nouveau Linux Pratique est disponible dès maintenant chez votre marchand de journaux et sur notre site marchand.

    Découvrez le sommaire de ce numéro et un aperçu de ce magazine...

    Lire la suite...

    Le tout nouveau GNU/Linux Magazine HS est disponible dès maintenant chez votre marchand de journaux et sur notre site marchand.

    Découvrez le sommaire de ce numéro et un aperçu de ce magazine...

    Lire la suite...

    Le tout nouveau Linux Essentiel est disponible dès maintenant chez votre marchand de journaux et sur notre site marchand.

    Découvrez le sommaire de ce numéro et un aperçu de ce magazine...

    Lire la suite...

    Le tout nouveau Misc HS est disponible dès maintenant chez votre marchand de journaux et sur notre site marchand.

    Découvrez le sommaire de ce numéro et un aperçu de ce magazine...

    Lire la suite...