Vulnérabilité Buffer Overflow

Table des matières

Dans ce tutoriel nous allons parler du buffer overflow (Débordement de tampon), une panne qui existe depuis longtemps, se produit lorsque les données qui sont copiées dans une zone mémoire (qui a été préalablement réservée) ne sont pas vérifiées correctement, il se peut que l'application fonctionne correctement si l'utilisateur insère des données avec un taille adéquate, mais si nous réservons la mémoire pour 15 caractères et que l'utilisateur en insère 20, cela affectera une autre zone mémoire, qui peut être réservée ou non.

Cela peut faire bloquer notre programme, mais cela peut aussi être bien pire, un utilisateur avec des intentions malveillantes peut profiter de cette erreur et influencer le fonctionnement de l'application ou exécuter du code arbitraire sur un ordinateur (normalement ce code ouvrira un interpréteur de commandes ). De plus, si le programme s'exécute avec des privilèges élevés, nous avons une grave faille de sécurité. Une autre attaque qui peut altérer le fonctionnement d'une application ou injecter du code est XSS.

NoterLes exécutions que vous verrez tout au long de ce didacticiel ont été réalisées dans le système d'exploitation 32 bits Ubuntu 16.04.

Voyons un Exemple simple de code C vulnérable à cette attaque, au lancement du programme il faut passer un paramètre, l'application attendez-vous à recevoir une chaîne ne dépassant pas 15 caractères, si c'est la chaîne attendue, ce sera un accès réussi, sinon il sera "refusé". Le code est comme indiqué ci-dessous :

 #include #include #define password "Test" void test (char * str) {char buffer [15]; entier n = 0; strcpy (tampon, str); if (strcmp (tampon, mot de passe) == 0) {n = 1; } if (n) {printf ("Succès \ n"); sortie (0); } else {printf ("Accès refusé \ n"); }} int main (int argc, char * argv []) {if (argc <2) {printf ("L'application nécessite un paramètre \ n"); sortie (-1); } test (argv [1]); }
Le programme porte le nom débordement.c, et pour compiler ce qui suit a été utilisé :
 gcc overflow.c -o overflow -fno-stack-protector
La dernière partie: -fno-stack-protector Il est utilisé pour que le compilateur ne mette pas de protection et nous pouvons montrer l'exemple. Si l'utilisateur entre des données correctes, qui sont une chaîne de 15 caractères maximum, le programme fonctionne bien, si nous entrons un "mot de passe" incorrect, il nous montrera Accès refusé, et si on met "Test« nous mettra Succès. Voyons une capture exécutant le programme 2 fois, une fois avec un accès incorrect et une autre avec la chaîne correcte :

On voit que tout fonctionne correctement. Mais que se passe-t-il si nous insérons une chaîne supérieure, voyons ce qui se passe :

Nous avons lancé le programme avec 20 lettres A, et nous montre Succès. Dans cette application, nous n'avons rien, nous sortons simplement de l'application, mais nous avons accédé à une zone restreinte sans connaître le mot de passe. Si nous substituons la fonction suivante :

 strcpy (tampon, str);
Par ce qui suit :
 strncpy (tampon, str, 15);
Oui nous exécutons le code avec 20 lettres A, nous avons la sortie suivante :

Vous pouvez également voir que nous utilisons strcmp, nous devrions plutôt utiliser strncmp, nous contrôlons donc également la taille. Nous avons contrôlé que seul un maximum de 15 caractères peut être copié, donc cela n'affecte pas notre programme s'ils en insèrent plus. Si après avoir affiché le message Succès nous exécutons une commande système (dans ce cas qui suis je), on obtient les informations :

Ci-dessus, nous ne sommes pas root, mais si nous l'exécutons avec sudo, nous obtenons ceci :

La seule chose que nous avons ajoutée est une ligne dans le code que nous avons vu ci-dessus, en dessous de la ligne de code :

 printf ("Succès \ n");
Nous avons mis :
 système ("whoami");
Pour comprendre un peu ce qui s'est passé, je vais modifier le programme pour afficher les 2 variables que nous avons (amortir Oui m) si elle est correcte ou non, et ci-dessous est la sortie, le premier nous insérons une chaîne qui sera traitée comme correcte ("Test"), Puis un incorrect qui ne dépasse pas la longueur et enfin le 20 lettres A:

On voit que dans la première exécution il vaut la peine 1 La variable m, parce que la chaîne passée est la bonne, dans la seconde elle vaut la peine 0, parce que c'est faux, mais dans le dernier ça vaut la peine 1094795585, ce qui fait sauter la condition que l'on pose si (n), ce sera vrai tant que n est différent de 0. Ce n'est pas une bonne condition, même si elle ne devrait pas échouer si le reste du code était correct. Si on met 16 lettres A comme paramètre nous verrons que la valeur de la variable m il est 65:

Si nous regardons le code ASCII, le nombre 65 correspond à la lettre À, nous avons vu que la mémoire de la variable n a été accidentellement touchée par nous, cette lettre supplémentaire que nous avons passée en paramètre est allée à la variable m. Nous aurions la mémoire comme suit :

Si nous allons au-delà des caractères, il se peut que cela nous envoie un message de violation de segment (si nous éliminons le sortie (0) qu'avons-nous dans le si (n)), nous pouvons le voir dans l'image suivante :

Cet avertissement est dû à une tentative d'accès à une zone mémoire hors des limites de celle attribuée par le système d'exploitation à l'application. Si nous compilions l'exemple comme suit :

 gcc overflow.c -o overflow -fstack-protector
Ou simplement retirer -fno-stack-protector A partir de la compilation que nous avons vue la première fois, et nous exécutons le code avec débordement, nous obtenons le résultat suivant :

Une protection supplémentaire que gcc nous offre.

NoterSi nous voulions exécuter un code (shellcode) il faudrait écraser l'adresse de retour par celle de notre shellcode, c'est un peu plus complexe que l'exemple vu dans le tutoriel et demande donc plus de travail.

Si quelqu'un parvient à profiter de cette vulnérabilité, cela peut vous causer beaucoup de dégâts. Eviter d'avoir ce type de panne et qu'un utilisateur malveillant puisse en profiter est très simple, programmer correctement, il faut bien connaître le langage de programmation qui est utilisé, savoir quelles fonctions utiliser et ce qu'il ne faut pas utiliser, tester l'application eh bien, non seulement avec des données correctes, il doit également fonctionner correctement lorsque nous traitons des données imprévues.

D'autres attaques que vous pouvez examiner et connaître afin qu'elles ne vous affectent pas ou ne minimisent pas leurs risques sont : DoS et Brute Force. Et n'oubliez pas de vérifier la page CVE pour les vulnérabilités.

Avez-vous aimé et aidé ce tutoriel ?Vous pouvez récompenser l'auteur en appuyant sur ce bouton pour lui donner un point positif
wave wave wave wave wave