Format Strings


<< Exploiter l'environnement Lire n'importe où en mémoire >>


I°) Introduction aux vulnérabilités format strings

Rappels brefs
   Nous allons donc nous intéresser dans cette partie aux exploits type format strings (chaînes de caractères formatées), qui restent légèrement plus difficiles que les buffer-overflows classiques à appréhender. Ces exploits ont connu leur essort (et leurs heures de gloires) essentiellement au début des années 2000, mais restent néanmoins présents et intéressants.
Ce type de faille, commune (aussi bien sur le web que dans les éxécutables), est un peu moins présent que les failles de type buffer-overflow mais permet une exploitation tout aussi en profondeur et en puissance. Tout d'abord, nous allons déterminer ce que sont les exploits de type chaînes formatées ainsi que la façon de les exploiter pour lire et écrire à n'importe quelle adresse en mémoire. Nous allons effectuer l'étude de ce type d'exploits en étudiant un programme basique qui va nous permettre d'étudier et de comprendre le procédé. Tout d'abord, une petit explication de principe sur l'exploitation des chaînes formatées.

Nous allons, classiquement, faire l'étude de la fonction C printf() qui est une source assez importantes d'exploitations type format strings. Voici un exemple d'utilisation de cette fonction :
    printf("on imprime à l'écran le paramètre 1 : %p, le 2eme : %p, le 3eme : %p,etc...",param1,param2,param3,...)
Ce qu'on appelle formatage d'une chaîne est associé au caractère % : il donne la possibilité d'afficher la variable associée sous différente formats. Les paramètres les plus usités sont %d (entier), %u (entier non signé), %x (représentation hexadécimale), %c (un unique caractère), %f (nombre à virgule flottante). Ces paramètes nécessitent des valeurs en entrée. Il existe aussi deux types de paramètres nécessitant des pointeurs en entrée : %s (imprime une chaine de caractères) et %n (inscrit dans le paramètre le nombre de bytes écrites jusqu'à ici).

Les chaînes formatées
   Illustrons ces quelques rappels par le programme que nous allons étudier dans ce tutoriel :
    //format-strings.c : Vulnérabilité aux chaînes de caractères formatées

    static int i = 1337;

    int main() {

      int ici,la;
      char commentaire[200];

      printf("\ni = %d = %x et se trouve à 0x%x\nOn compte jusqu'à %nici, puis jusqu'à %nlà le nombre de bytes écrites\n",i,i,&i,&ici,&la);
      printf("Jusqu'à ici, il y avait %d bytes et %d entre ici et là\n\n",ici,la - ici);
      printf("Maintenant, écrivez votre commentaire sur ce programme et terminez par entrée\n");

      scanf("%s",commentaire); //niveau notations, comentaire = commentaire[0] = &commentaire[0] = &commentaire

      printf("On peut écrire votre commentaire de deux façons :\n\nComme ça, ");

      printf("%s",commentaire);

      printf("\n\nou comme ça : ");

      printf(commentaire);

      printf("\n\nFin du programme\n\n");


      return 0;
    }
Pour tester ce programme et montrer le fonctionnement de ces formatages de chaînes, on l'éxécute :
    $ ./format-strings
    Tout d'abord, on imprime une chaîne de caractères de test : "Chaîne de caractères de test", se situant à 8049864

    i = 1337 = 539 et se trouve à 0x8049860
    On compte jusqu'à ici, puis jusqu'à là le nombre de bytes écrites
    Jusqu'à ici, il y avait 59 bytes et 18 de ici à là

    Maintenant, écrivez votre commentaire sur ce programme et terminez par entrée
    test
    On peut écrire votre commentaire de deux façons :

    Comme ça, test

    ou comme ça : test

    Fin du programme

    $
Mais, dans votre esprit bouillonant vient une question : que se passe-t-il si on donne comme commentaire une chaîne formatée ??? Le programme va-t-il l'interpréter ? La meilleur manière de le savoir est d'essayer...
    $ ./format-strings
    Tout d'abord, on imprime une chaîne de caractères de test : "Chaîne de caractères de test", se situant à 8049864

    i = 1337 = 539 et se trouve à 0x8049860
    On compte jusqu'à ici, puis jusqu'à là le nombre de bytes écrites
    Jusqu'à ici, il y avait 59 bytes et 18 de ici à là

    Maintenant, écrivez votre commentaire sur ce programme et terminez par entrée
    %x-vkd-%d
    On peut écrire votre commentaire de deux façons :

    Comme ça, %x-vkd-%d

    ou comme ça : bfca0c04-vkd-18

    Fin du programme

    $
Effectivement, la fonction printf() recevant une chaine formatée, elle a l'air de l'interpréter comme elle peut. Nous allons maintenant essayer d'en profiter pour lire les données de n'importe quelle adresse en mémoire.

<< Exploiter l'environnement Lire n'importe où en mémoire >>



4 Commentaires

mihawk 14/10/12 08:13
@Anonyme

pour contourner le stack smatching proctection ajoute l'option : -fno-stack-protector lorsque tu compile avec gcc :)

FrizN 20/07/11 06:58
Oui, même si c'est dur de répondre en 500 c. Déjà la randomisation du canary n'est pas si bonne sous Linux qu'on l'a un temps cru. Ensuite, d'autres techniques comme les format strings et heap overflows ne sont pas protégés par le canary. Sous Windows, l'exploitation des SEH permet de contourner le problème. Le mieux est de lire les présentations de blackhat (notamment celle de fritsch en 2009) sur le sujet.

Anonyme 20/07/11 05:17
SVP y t il des solutions pour contourner le stack smasher protection ??

xfather123 24/05/11 16:31
c8oloV this is delicious!




Commentaires désactivés.

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

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