Chaine de format - introduction   Version imprimable de cet article Enregistrer au format PDF

Introduction aux vulnérabilités format strings


par S3cur3D

Rappels brefs

Nous allons 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 :

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

  1. //format-strings.c : Vulnérabilité aux chaînes de caractères formatées
  2.  
  3. static int i = 1337;
  4.  
  5. int main() {
  6.  
  7. int ici,la;
  8. char commentaire[200];
  9.  
  10. 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);
  11. printf("Jusqu'à ici, il y avait %d bytes et %d entre ici et là\n\n",ici,la - ici);
  12. printf("Maintenant, écrivez votre commentaire sur ce programme et terminez par entrée\n");
  13.  
  14. scanf("%s",commentaire); //niveau notations, comentaire = commentaire[0] = &commentaire[0] = &commentaire
  15.  
  16. printf("On peut écrire votre commentaire de deux façons :\n\nComme ça, ");
  17.  
  18. printf("%s",commentaire);
  19.  
  20. printf("\n\nou comme ça : ");
  21.  
  22. printf(commentaire);
  23.  
  24. printf("\n\nFin du programme\n\n");
  25.  
  26.  
  27. return 0; }

Télécharger

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.

Documentations publiées dans cette rubrique Documentations publiées dans cette rubrique