Un buffer overflow (BOF) est littéralement un dépassement de 
  la capacité d'un buffer de données. Rien de bien méchant, 
  cela arrive fréquement lorsque l'on manipule des pointeurs et que l'on 
  programme sans trop de précautions. 
  La conséquence est généralement un 'crash' du programme, 
  qui tente un accès à des zones en dehors de son espace d'adressage 
  (donne des segmentation fault ou protection fault).
   La 
  saturation ou le crash deserveur n'est généralement le but ultime 
  des hackers. L'acquisition de privilèges ou l'ouverture de backdoor est 
  plus souvent ciblée.
La 
  saturation ou le crash deserveur n'est généralement le but ultime 
  des hackers. L'acquisition de privilèges ou l'ouverture de backdoor est 
  plus souvent ciblée.
Dans le domaine de la sécurité cette technique du BOF est utilisée pour 'dérouter' la séquence normale des instructions d'un programme et le forcer à éxécuter une routine spécifique, permettant généralement l'obtention de droits 'super utilisateur'. Cette routine ou ce programme exploitant la faille est appelé un "exploit" (en Anglais dans le texte)
 'droits 
  super utilisateur' ne veut pas dire seulement obtention de l'UID 'root' ou 'Administrateur'. 
  Beaucoup d'applications utilisent des variables ou des tables pour gérér 
  en interne des niveaux de privilèges indépendemment de l'OS. Des 
  flags du type 'useradmin=1' ou 'loginok=true' ou 'privileges=ALL' sont monnaie 
  courante dans les programmes et beaucoup plus facilement exploitables.
 'droits 
  super utilisateur' ne veut pas dire seulement obtention de l'UID 'root' ou 'Administrateur'. 
  Beaucoup d'applications utilisent des variables ou des tables pour gérér 
  en interne des niveaux de privilèges indépendemment de l'OS. Des 
  flags du type 'useradmin=1' ou 'loginok=true' ou 'privileges=ALL' sont monnaie 
  courante dans les programmes et beaucoup plus facilement exploitables.
Ce problème est important de part sa notoriété et également 
  de par sa persistance. Les premières mises en évidence de la possibilité 
  de ce type d'attaque datent de 1995 et sont toujours d'actualité.
  Statistiquement si l'on consulte les sites de référérence 
  que sont le site du Cert et 
  le site d'infosys security  par exemple, on constate qu'une part importante 
  des pbs traités concerne le BOF. Voir plus particulièrement le 
  rapport du dernier trimestre 
  2003 du CERT.
 bien 
  qu'abondamment documenté sur le web, ce type d'attaque nécessite 
  une grande ténacité et de bonnes compétences en programmation 
  de bas niveau (assembleur), en désassemblage (les sources sauf cas ideal 
  de certains logiciels libres n'étant pas à la disposition des 
  hackers) et en gestion de la mémoire et architecture système (structure 
  et adressage de la pile, contenu des bibliothèques sytème notamment).
bien 
  qu'abondamment documenté sur le web, ce type d'attaque nécessite 
  une grande ténacité et de bonnes compétences en programmation 
  de bas niveau (assembleur), en désassemblage (les sources sauf cas ideal 
  de certains logiciels libres n'étant pas à la disposition des 
  hackers) et en gestion de la mémoire et architecture système (structure 
  et adressage de la pile, contenu des bibliothèques sytème notamment).
Un certain nombre de conditions sont indispensables à l'occurence d'un BOF :
mais aussi
Soit le petit programme C suivant
main(int argc, char **argv) { 
  char *somevar;
  char *important;
  somevar = (char *)malloc(sizeof(char)*4); 
  important = (char *)malloc(sizeof(char)*14);
  strcpy(important, "command"); /*This one is the important variable*/
  stcrpy(somevar, argv[1]);
  ..... Code here ....
  } 
Il présente qq caractéristiques remarquables :
Modifions ce programme pour lui faire imprimer les adresses et les contenus, et executons le en lui passant le parametre 'TOTO' :
$mon_programme TOTO
0x8049700: T(0x616c62)
  0x8049701: O(0x616c)
  0x8049702: T(0x61) 
  0x8049703: O(0x0)
  0x8049704: (0x0)
  0x8049705: (0x0)
  0x8049706: (0x0)
  0x8049707: (0x0)
  0x8049708: (0x0)
  0x8049709: (0x19000000)
  0x804970a: (0x190000)
  0x804970b: (0x1900)
  0x804970c: (0x19)
  0x804970d: (0x63000000)
  0x804970e: (0x6f630000)
  0x804970f: (0x6d6f6300)
  0x8049710: c (0x6d6d6f63)
  0x8049711: o (0x616d6d6f)
  0x8049712: m (0x6e616d6d)
  0x8049713: m (0x646e616d)
  0x8049714: a (0x646e61)
  0x8049715: n (0x646e)
  0x8049716: d (0x64)
  0x8049717: (0x0) 
On connait désormais le décalage d'adresse entre 'somevar' et 
  'important'.
  Le C et strcpy() le permettant, on va se permettre un dépassement de 
  buffer de la variable 'somevar' pour substituer NOTRE commande à la 'command' 
  d'origine.
0x8049700: T(0x646e6573)
  0x8049701: O(0x2d646e65)
  0x8049702: T(0x2d2d646e)
  0x8049703: O(0x2d2d2d64)
  0x8049704: - (0x2d2d2d2d)
  0x8049705: - (0x2d2d2d2d)
  0x8049706: - (0x2d2d2d2d)
  0x8049707: - (0x2d2d2d2d)
  0x8049708: - (0x2d2d2d2d)
  0x8049709: - (0x2d2d2d2d)
  0x804970a: - (0x2d2d2d2d)
  0x804970b: - (0x2d2d2d2d)
  0x804970c: - (0x2d2d2d2d)
  0x804970d: - (0x6e2d2d2d)
  0x804970e: - (0x656e2d2d)
  0x804970f: - (0x77656e2d)
  0x8049710: n (0x6377656e) <--- c'est la !
  0x8049711: e (0x6f637765)
  0x8049712: w (0x6d6f6377)
  0x8049713: c (0x6d6d6f63)
  0x8049714: o (0x616d6d6f)
  0x8049715: m (0x6e616d6d)
  0x8049716: m (0x646e616d)
  0x8049717: a (0x646e61)
  0x8049718: n (0x646e)
  0x8049719: d (0x64)
  0x804971a: (0x0) 
C'est la le miracle : on peut modifier le déroulement de l'exécution d'un programme sans en modifier le code (heureusement il faudrait le recompiler et reinstaller l'executable sur la cible). Le paramètre d'entrée est le seul point...d'entrée du programme et on peut faire une subsitution de code, si tant est que certains appels se fassent à travers des variables et qu'elles soient correctement 'rangées' en mémoire.
D'après airWalk, "Introduction to buffer overflows" - for interScape, may 1999
Soit le programme C suivant :
void someFunction(char *str) {
  char buffer[16];
  strcpy(buffer, str);
  }
  void main()
  {
  char bigString[256];
  int i;
  for( i = 0; i < 255; i++)
  bigString[i] = 'A';
  someFunction(bigString);
  }
A l'exécution il provoque une erreur du type : 'Segmentation violation' 
  .
  Pourquoi ? Parce que c'est au sein, et plus précisément juste 
  avant le 'return' de la fonction qu'a lieu un dépassement de buffer.
  Les 240 'A' supplémentaires vont écraser les zones mémoires 
  suivant la fin de la variable 'buffer' , et en particulier l'adresse de retour 
  de la fonction, en y subsituant une valeur (pleine de 'A') invalide...d'ou l'erreur 
  sus nommée.
  On perçoit que dans ce cas, si l'on si prend bien il est possible de 
  modifier l'adresse de retour d'une fonction et donc modifier le déroulement 
  de l'exécution d'un programme.
Reste maintenant un détail, écrire une exploit capable de menacer le système. A la différence de l'exemple précédent qui faisait des appels à des commandes système, que l'on remplaçait, celui ci n'en fait pas...c'est son coté moins idéal.
 rappelons 
  que "l'exploit" du programme est souvent conditionnée par le 
  niveau de privilège d'exécution du programme hacké. Un 
  uid root (ou son équivallent Windows administrateur) permet + facilement 
  d'executer des commandes fatales.
rappelons 
  que "l'exploit" du programme est souvent conditionnée par le 
  niveau de privilège d'exécution du programme hacké. Un 
  uid root (ou son équivallent Windows administrateur) permet + facilement 
  d'executer des commandes fatales.
Nous savons comment on peut derouter un programme en écrivant l'exacte 
  quantité de mémoire et en écrasant l'adresse de retour 
  de la routine par une nouvelle adresse. Rest e à faire exécuter 
  un nouveau code.
  Ou peut se trouver le nouveau code agressif ?
  ll est impossible de modifier physiquemnt le programme compilé de la 
  cible. Le nouveau code ne peut qu'être passé qu'AU SEIN des données 
  modifiées responsables du buffer overflow !
  La taille du code ne correspondant pas forcément exactement à 
  l'offset entre début de buffer et adresse de retour à écraser, 
  précédera le code par des NOPs.
  Que contient le code agressif ?
  L'hypothèse étant que le programme vulnérable a un niveau 
  de privilège intéressant (root), une des exploits les + classiques 
  sera de lancer un shell permettant d'executer des commandes 'intéressantes' 
  : rm -R /*, cat /etc/passwd, mail, etc.
  Le code sera d'abord écrit en C, compilé , linké (gcc) 
  et désassemblé (avec gdb). Les codes hexadécimaux du programme 
  seront ensuite passés directement dans le buffer.
 Si 
  certains octets du code sont à zero, certaines des fonctions vulnérables 
  (comme strcpy()) risquent d'interpréter le 0x00 comme une fin de chaîne 
  ;-((
 Si 
  certains octets du code sont à zero, certaines des fonctions vulnérables 
  (comme strcpy()) risquent d'interpréter le 0x00 comme une fin de chaîne 
  ;-(( 
Pour plus de détails sur certains de ces aspects on pourra consulter la note du RSA : Countermeasures Againt BOF attacks
| 
 |