Anti-forensics sur systèmes de fichiers ext2/ext3
Signature : | Mis en ligne le : 16/09/2008
Catégorie(s) :
  • Misc
  • | Domaine :
    Commentez

     Retrouvez cet article dans : Misc 18

    La première chose qu'un pirate souhaite faire quand il a réussi à rentrer sur une machine, c'est cacher les données qu'il veut laisser. Il y a maintenant ceux qui utilisent les techniques que même ma grand-mère connaît et ceux qui profitent de la structure interne du système de fichiers. Cet article explique les différentes solutions pour cacher des données dans un système de fichiers ext2/ext3 tout en tenant compte des contraintes qui subsistent. Nous n'aborderons pas cependant le sujet des données effacées et de la manière de les récupérer qui est un tout autre sujet (celui de ne laisser aucune trace :)).

    Rappels sur les systèmes de fichiers ext2/ext3

    Quelques termes techniques à connaître

    Il est nécessaire de connaître quelques termes qui reviendront de manière récurrente tout au long de l'article. Le terme bloc désigne un bloc logique, c'est-à-dire un regroupement de 2, 4 ou 8 blocs physiques. Ces blocs physiques représentent l'unité du disque dur (il est divisé en blocs, pistes et secteurs) et ont une taille de 512 octets. Un inode, avec une taille fixe de 128 octets, est un bloc particulier du disque dur regroupant les informations essentielles d'un fichier et assurant la liaison entre ce fichier et le reste du système (issu du jargon français :)).

    Structure physique du système de fichiers ext2

    Chaque partition ext2 est découpée en blocs de taille identique. Seul le premier bloc réservé pour la partition boot sector n'est pas utilisé par le système de fichiers. Il contient un programme qui permet d'initialiser et de lancer le système. Il a une taille fixe de 1024 octets. Le reste de la partition est organisé en groupes de blocs de taille identique qui eux-mêmes sont structurés de la manière suivante :
    • le super bloc ;
    • les descripteurs de groupe ;
    • la table bitmap d'état d'allocation des blocs du groupe ;
    • la table bitmap d'état d'allocation des inodes du groupe ;
    • la table des inodes du groupe ;
    • les blocs de données.
    On répertorie ces structures en deux catégories : les metadata qui concernent le super bloc, les descripteurs et les différentes tables, et les data qui sont par logique les blocs de données. Ce sont sur les metadata que s'appuient les différentes techniques pour cacher des données.

    La table des inodes

    La table des inodes (dernière structure définie dans un groupe de blocs) est la structure qui nous intéresse le plus. Nous laissons donc de côté les autres. Il faut savoir que tout est fichier sur un système ext2 et qu'à chaque fichier est associé un inode unique. Cela peut être un répertoire, un lien symbolique... Chaque inode a un numéro unique sachant que les inodes de 1 à 10 sont réservés, l'inode 11 représente le premier inode utilisable : Parmi les inodes réservés, EXT2_BAD_INO contient les pointeurs de blocs vers les blocs de données qui occupent des mauvais secteurs du disque (les blocs défectueux sont regroupés dans le répertoire /lost+found) et EXT2_ROOT_INO est l'inode du répertoire racine de la partition. L'inode EXT2_UNDEL_DIR_INO indique le répertoire contenant les fichiers effacés qui peuvent être restaurés. Ce répertoire est caché sur le système. Pour connaître le numéro d'inode d'un fichier, il vous suffit d'utiliser l'option -i de /bin/ls : Les répertoires . et .. qui représentent la racine de la partition / (partition racine de l’espace de nommage) ont bien l'inode égal à 2. Pourquoi avons-nous aussi /home et /var avec un inode égal à 2 ? Ce sont en fait les points de montage de deux partitions ext2, par conséquent ces répertoires représentent les racines de ces 2 partitions. Tous ces inodes sont enregistrés dans une table elle-même appartenant à un groupe de blocs. Au niveau physique, une table d'inodes est une continuité de blocs. Quant à la table elle-même, chaque inode qui la compose est représenté par la structure ext2_inode (toujours dans le fichier linux/ext2_fs.h) qui contient toute l'information caractérisant un fichier. Cela concerne notamment le type du fichier, le propriétaire, les permissions et surtout des pointeurs vers les blocs de données (le contenu des fichiers). Pour terminer la partie sur la table des inodes, un exemple de la sortie de debugfs sur le contenu de la structure inode d'un fichier en fonction de son numéro d'inode :

     Un cas particulier d'inode : les répertoires

    Les répertoires sont considérés comme un fichier et possèdent donc un numéro d'inode (le répertoire racine a son numéro d'inode prédéfini : EXT2_ROOT_INO = 2). Pour chaque répertoire rencontré, ext2_inode.i_mode est égal à EXT2_S_IFDIR dans la table d'inodes et les blocs de données contiennent la liste des fichiers du répertoire et leur numéro d'inodes respectif plutôt que de contenir des données (c'est en quelque sorte, comme le dit si bien the grugq, le DNS du système de fichiers). Cette liste est composée de structures ext2_dir_entry_2 (ext2fs/ext2_fs.h).

    Différence entre ext2 et ext3

    Le système de fichiers ext3 est complètement compatible avec le système de fichiers ext2. Même les outils du package e2fsprogs (package qui contient les outils tels que debugfs, fsck, etc.) sont réutilisables sur un système ext3fs. Pour résumer assez rapidement, le système de fichiers ext3 équivaut à ext2 plus un journal. Sous ext3, le journal (endroit où sont stockés les logs d'activité de la journalisation) peut prendre deux formes : soit c'est un inode invisible par le système de fichiers, soit c'est un fichier caché  .journal  à la racine du système de fichiers, avec un attribut " immuable ". Tout dépend en fait de la création du système de fichiers. Les informations enregistrées dans le journal dépendent des paramètres de montage de la partition ext3. Pour plus de détails, reportez vous au document [ext3]. Ce qu'il faut retenir surtout, c'est que vous avez trois méthodes pour journaliser vos données :
    • Seules les structures ext2 sont enregistrées dans le journal et écrites sur le disque après les données.
    • Seules les structures ext2 sont enregistrées dans le journal mais elles peuvent être écrites sur le disque avant les données.
    • Tout est sauvegardé dans le journal (structure ext2 et données).
    Au niveau implémentation, il y a entre autres comme modification deux nouveaux inodes réservés dont un qui concerne la journalisation (cf. linux/ext3_fs.h) :

    Cacher les données

    Quel que soit le système de fichiers sur lequel vous souhaitez cacher des données, celles-ci ne doivent être détectées d'aucun outil forensics pour qu'elles soient efficaces. C'est évident mais cela sous-entend que vos données doivent être cachées à des endroits du système de fichiers que les outils forensics n'analysent pas. À cette condition s'ajoute le fait que le système de fichiers doit rester sans anomalie pour d'une part éviter d'alerter le système (nous verrons par quoi plus tard) et par conséquent l'utilisateur et d'autre part pour éviter de perdre ces fameuses données cachées. D'une manière générale, pour que la solution fonctionne pleinement, les données cachées doivent rester présentes sur le système. Un exemple simple voire très stupide : Jean-Kevin cache ses données dans le fichier '/tmp/.jean-kevin', mais, manque de chance, le système redémarre et ce système est configuré pour nettoyer le répertoire /tmp... Mais bon, on s'appelle pas Jean-Kevin par hasard :)

     Les outils forensics

    Comme nous venons de le dire, cacher des données ne veut pas dire nommer son fichier /bin/.log ou /usr/man/man1/... pour qu'au premier passage de chkrootkit [chkrootkit] (ou un autre), les fichiers soient détectés. Certes chkrootkit ne détecte pas tout, mais avec un peu de temps et de patience, l'analyste post-intrusion ou quiconque arrivera à ses fins. Il pourra par exemple faire un pattern matching de différentes chaînes de caractères sur tous les fichiers ou plus simplement et avec beaucoup de réussite faire un listing complet du système de fichiers et analyser un à un les fichiers qui semblent douteux. Des solutions moins fastidieuses existent comme faire une analyse forensics par rapport aux accès des fichiers. Il faut savoir que la structure inode d'un fichier fournit entre autres 3 informations concernant l'accès au fichier :
    • atime : modifié par des accès en lecture (read(), mmap(), execve(),...)
    • mtime : modifié par des accès en écriture (write(), truncate(), mknod(),...)
    • ctime : modification au niveau inode (chown(), link(),...)
    Souvent, après la création d'un nouveau fichier, le pirate a tendance à vouloir modifier les temps d'accès au fichier pour tromper l'ennemi. La commande touch avec l'option -r ou -d le permet : Seulement, quelle que soit l'option utilisée, le jour de ctime ou atime reste inchangé : Les données peuvent donc être facilement retrouvées. Si l'on connaît approximativement la date d'intrusion sur le système, une recherche à partir de cette date sur atime, ctime et mtime des inodes des fichiers permettra de découvrir les fichiers créés par le pirate au moment de son intrusion. L'utilisation de debugfs pour récupérer ces informations étant trop fastidieuse, il existe des outils, tel que mactime, issu de la solution forensics sleuthkit [sleuthkit], qui automatisent le processus. Dans ce cas-là, les outils forensics remplissent bien leur rôle : donner les informations nécessaires sur les systèmes de fichiers pour conclure ou non d'une intrusion sur le système. Cependant, si nous ne savons pas où chercher et comment chercher, ces outils deviennent vite inefficaces. Et même s'ils faisaient plus que donner des informations (automatisation de l'analyse forensics), ils seraient malgré tout défaillants du fait qu'ils n'analysent pas dans son intégralité la structure du système de fichiers.

    Un exemple concret

    Il existe un bug (ou un défaut d'implémentation, peu importe) dans la libc qui fait que seuls les inodes >= 1 sont pris en compte. Et les outils forensics font la même erreur. Dans sleuthkit par exemple, il considère qu'aucun bloc de données ne peut être alloué à un inode avant l'inode fs->first_inum = EXT2FS_FIRSTINO = 1  Par conséquent, si vous créez un fichier avec un inode = 0, il ne sera visible d'aucun utilitaire lié à la libc et d'aucun outil forensics. Cette solution anti-forensics est une solution parmi tant d'autres. Elle prouve cependant que les outils forensics contiennent des failles dans leur implémentation. Techniquement, pour créer un fichier avec un inode = 0, le plus simple est de créer un fichier normal et de modifier son numéro d'inode. Ce qui implique qu'il faut repérer son inode dans la table des inodes et par conséquent localiser cette table dans un groupe de blocs. Connaissant l'offset de l'inode, il sera ensuite possible de modifier son numéro d'inode et d'accéder aux blocs de données de cet inode (chaque inode contient les pointeurs vers les blocs de données).

    Ne pas être détecter par fsck

    L'exemple de l'inode = 0 est un exemple parmi tant d'autres pour montrer que les outils forensics sont une barrière à franchir afin que les solutions anti-forensics soient efficaces. Il est ensuite nécessaire de s'assurer que le système de fichiers ne soit pas altéré, au risque de perdre nos données, de rendre le système inutilisable ou bien que l'utilitaire fsck disponible dans e2fsprogs détecte une anomalie dans le système de fichiers. Petit rappel sur fsck : il est utilisé pour vérifier l'intégrité du système de fichiers et le réparer en cas d'anomalie. Il peut être lancé manuellement ou bien au démarrage du système à intervalles réguliers. Ces intervalles dépendent en fait du nombre de montage de la racine et par conséquent du nombre de démarrage de la machine. Ces informations sont présentes dans le super bloc et servent à conserver un système de fichiers stable et non corrompu, une des grandes particularités de ext2. Revenons à la solution anti-forensics précédemment évoquée. Passe-t-elle à travers les mailles du filet de fsck ? Malheureusement non. Il détecte les fichiers avec un numéro d'inode = 0 comme invalide du fait que l'inode 0 n'est pas autorisé à avoir des blocs de données qui lui sont attachés. Dans le code de fsck, cela se présente de cette manière : Pour résumer, il récupère la liste des numéros d'inodes et regarde leurs valeurs. S'ils ne correspondent à aucun numéro d'inode réservé (EXT2_BAD_INO < ino < EXT2_UNDEL_DIR_INO) mais qu'il est toujours inférieur au premier numéro d'inode non réservé (EXT2_GOOD_OLD_FIRST_INO), il vérifie si la valeur du i_mode de l'inode est différente de 0. Cela signifierait que le fichier est créé. C'est le cas pour le fichier avec l'inode = 0.

    Un exemple concret : les bad blocks

    Nous avons vu que la solution de cacher nos données dans un fichier avec inode = 0 fonctionne à moitié, ce qui évidemment nous satisfait ... à moitié. Grugq a implémenté une technique qui était à l'époque (nous verrons pourquoi) pleinement fonctionnelle runefs [runefs]. Sa solution découle du problème d'implémentation dans l'outil forensic " The Coronor's Toolkit "1 (TCT) développé par Dan Farmer et Wietse Venema [tct] (l'ancêtre de sleuthkit en fait). Ce dernier faisait l'erreur dans la version 1.09 de considérer qu'aucun bloc de données ne pouvait être alloué à un inode avant l'inode EXT2_ROOT_INO (inode 2) : Sauf qu'avant l'inode EXT2_ROOT_INO, il existe l'inode EXT2_BAD_INO des bad blocks. Cet inode sert à référencer les data blocks qui occupent des mauvais secteurs du disque dur. Qui dit inode dit blocs de données alloués, ce qui veut dire qu'il est possible d'y enregistrer des données. Nos données seront donc cachées et TCT ne verra rien ; L'espace pour cacher nos données est créé c'est-à-dire que des blocs de données sont alloués à l'inode 1. C'est vérifiable avec l'utilitaire debugfs :  1 On retrouve le même Sanity check, vu avec Sleuthkit Si vous avez bien suivi :) vous pouvez voir que le premier bloc alloué est bien égal à bb_blk->start (205509), le dernier à bb_blk->end (212992) et la taille à bb_blk->size (TOTAL : 7515, proche de 7484 dû à quelques meta-data pris en compte). Éditez les informations de l'inode 1 sur un de vos systèmes sains et vous verrez qu'aucun bloc n'est alloué à cet inode. Vous avez ensuite les utilitaires runewr et runerd pour respectivement écrire et lire des données cachées. Voici un exemple avec runewr vérifiable une nouvelle fois avec debugfs (debugfs est vraiment notre ami :)) : Du fait que fsck considère l'inode EXT2_BAD_INO comme un inode valide, il trouve normal que des blocs soient alloués à cet inode. Contrairement à l'inode = 0 où dès le départ, il était considéré comme invalide. Cette technique pour cacher des données était assez royale (même au redémarrage de la machine, les données étaient toujours présentes). Évidemment le code de TCT a été patché pour prendre en compte dans son analyse l'inode EXT2_BAD_INO et ne plus le considérer comme un inode invalide. L'édition des blocs de données alloués à cet inode est donc maintenant possible avec TCT.

    Les autres techniques

    Toutes les techniques qui suivent ont été créées par the grugq [the grugq], précurseur dans ce domaine.

    Waffen FS

    Cette technique consiste à créer un faux journal ext3 dans un système de fichiers ext2. Techniquement, cela consiste à créer un fichier normal qui contiendra des fausses en-têtes meta-data de journal. La description de l'en-tête est présent dans le fichier linux/ext3_fs.h. Au niveau de e2fsck, comme il supporte à la fois les systèmes de fichiers ext2 et ext3, il ne détectera aucune anomalie. Le fichier est vu comme un fichier journal ext3 normal. Mais évidemment, des solutions telles que sleuthkit commence à fournir des outils (jcatet jls) permettant d'analyser les fichiers journaux présents.

    Ky FS

    Kyfs prend un fichier répertoire (rappelez vous que tout est fichier sur un système ext2 et ext3) et modifie sa structure de cette manière : Les données seront enregistrées dans name[]. Vous pouvez ensuite créer autant de répertoires avec inode = 0 que vous voulez sachant que les répertoires ne contiendront pas de fichiers. Que ce soit fsck, le noyau ou les outils forensics, la supercherie ne sera pas découverte du fait que ces répertoires seront considérés comme des répertoires normaux ou effacés.

    Data mule FS

    Cette technique complète les 3 précédentes du fait qu'elle permet de cacher des données dans tous les endroits du système de fichiers pas encore pris en compte : l'espace réservé, l'espace restant dans les structures (padding), etc. Un exemple est le super bloc. Il correspond à un bloc de 1024 octets (cf. SUPERBLOCK_SIZE dans ext2fs/ext2fs.h). Or sa structure ext2_super_block (toujours dans ext2fs/ext2fs.h) n'occupe qu'une partie de cet espace. Le but de la technique Data mule FS est de combler l'espace vide avec des données à cacher (759 octets d'après the grugq). Et bien évidemment, comme ce sont des espaces valides dans un système de fichiers, aucune anomalie ne sera détectée.

    Conclusion

    The grugq a quasiment fait tout le tour des possibilités de cacher des données dans un système de fichiers ext2/ext3. Nous pouvons en imaginer d'autres, mais peut-être un peu tirées par les cheveux et certainement détectables par les outils forensics ou fsck :
    • créer un fichier et marquer l'inode comme free. Il vaut mieux certainement créer le fichier avec un inode très élévé pour éviter qu'il soit écraser.
    • l'inode d'indice 6 est réservé à la restauration des fichiers  effacés. Un répertoire interne caché regroupe les enregistrements des fichiers effacés s'ils ont la propriété restauration, permettant ainsi une restauration après effacement. L'idée est donc d'effacer un fichier mais en prenant bien soin qu'il ait la propriété restauration.
    Reste à être convaincu et à tester. Mais en fait la tendance est tout autre. On ne cherche plus comment cacher des données sur un système de fichiers ext2/ext3, on cherche plutôt comment ne pas en écrire. Mais c'est une tout autre histoire ... et un tout autre article :). Références :

     Retrouvez cet article dans : Misc 18

    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...