CONNEXION
  • RetourJeux
    • Sorties
    • Hit Parade
    • Les + populaires
    • Les + attendus
    • Soluces
    • Tous les Jeux
    • Gaming
  • RetourActu Gaming
    • News
    • Astuces
    • Tests
    • Previews
    • Toute l'actu gaming
  • RetourBons plans
    • Bons plans
    • Bons plans Smartphone
    • Bons plans Hardware
    • Bons plans Image et Son
    • Bons plans Amazon
    • Bons plans Cdiscount
    • Bons plans Decathlon
    • Bons plans Fnac
    • Tous les Bons plans
  • RetourJVTech
    • Actus High-Tech
    • Intelligence Artificielle
    • Smartphones
    • Mobilité urbaine
    • Hardware
    • Image et son
    • Tutoriels
    • Tests produits High-Tech
    • Guides d'achat High-Tech
    • JVTech
  • RetourCulture
    • Actus Culture
    • Culture
  • RetourVidéos
    • A la une
    • Gaming Live
    • Vidéos Tests
    • Vidéos Previews
    • Gameplay
    • Trailers
    • Chroniques
    • Replay Web TV
    • Toutes les vidéos
  • RetourForums
    • Hardware PC
    • PS5
    • Switch 2
    • Xbox Series
    • Switch
    • Pokemon pocket
    • FC 25 Ultimate Team
    • League of Legends
    • Tous les Forums
  • PC
  • PS5
  • Xbox Series
  • Switch 2
  • PS4
  • One
  • Switch
  • iOS
  • Android
  • MMO
  • RPG
  • FPS
En ce moment Genshin Impact Valhalla Breath of the wild Animal Crossing GTA 5 Red dead 2
Liste des sujets

[Securité] Buffer overflow

Chaos_Clad
Chaos_Clad
Niveau 10
04 novembre 2008 à 12:43:32

Bonjour à tous :)

Ma question va être, je pense, super technique, sans forcément toucher à un langage particulier, d'où mon tag. Ne vous inquiétez pas, je ne vous demanderai pas comment pirater le serveur de jeuxvideo.com, ça je le ferai tout seul quand j'aurai compris vos explications :diable:

Mon prof, mon Dieu, celui qui m'enseigne le Python (entre autres) nous a parlé d'un ami à lui qui s'était fixé un but dans la vie : réaliser un buffer overflow.
Il nous a expliqué le principe, et j'ai écouté d'une oreille attentive.

Seulement je le connaissais déjà le principe, et je n'ai pas eu ce que je voulais, à savoir : concrètement, comment faire ?

Le buffer overflow, j'en ai entendu parler plusieurs fois comme de l'attaque ultime, destructrice, un peu la bombe atomique de la sécurité informatique, donc je me doute que ça doit être très difficile à réaliser, et j'aurai aimé avoir des éclaircissements, COMMENT réaliser un BO c-o-n-c-r-è-t-e-m-e-n-t ?
J'aime bien qu'on me dise "injection de code arbitraire", "mauvais contrôle de la mémoire dans un tableau", ça fait rêver, c'est grand, c'est beau :snif:
Mais supposons un instant que moi, simple citoyen innofensif, je choisisse un site au pif en me disant : "Lui, il va morfler ! :diable: ".
Mes questions sont :

1°) Comment savoir que le site est sensible au BO ? (parce qu'évidemment, si je demande le code source je perds l'effet de surprise et l'ennemi peut riposter)
2°) Comment... euh ben comment "attaquer" ? Logiciel assassin ? Requêtes perverses ? Reverse engeenering ? (fallait bien sortir un mot technique au milieu de tout ça xD)
3°) Sur les sites Web, je conçois, mais sur un logiciel ? J'ai entendu parler (mais mes souvenirs ont peut-être pris l'eau du temps) de quelqu'un qui avait trouvé une faille de type BO sur un jeu vidéo sur XBox, et là... je me retrouve comme les physiciens quand on leur demande "Pourquoi l'Univers ?".
4°) Qu'est ce ça veut dire en fait "injecter du code arbitraire" ?
5°) Est-ce que tout cela nécessite de connaître intimement le fonctionnement d'un ordinateur, du matériel à l'OS ?

Bien évidemment, ces questions n'ont qu'un but pédagogique et je n'encourage personne au piratage (même si c'est vrai que c'est rigolo de faire une blague à son pote en modifiant la page d'accueil de son site =D ).

Merci de vos réponses, bonne journée :)

godrik
godrik
Niveau 30
04 novembre 2008 à 13:39:32

je pense qu'avant de regarder les Buffers Overflow dans un site web, il vaut mieux l'étudier dans ton systeme d'exploitation.
Il est facile je pense de faire d'exploiter un depassement de buffer sur un programme tout simple en C.

L'idée est simple, il s'agit d'écraser la pile d'appel dans le but de faire un saut vers une addresse prédictible.

(on va finir par croire que j'ai des actions mais) le magazine MISC détaille bien les problemes de sécurité et on trouve des exploitations de buffers overflow dedans. Cela doit pouvoir te renseigner. Si tu veux, je verrais pour scanner un des articles et le mettre sur le web. Mais je ne sais pas quand j'aurais le temps de faire ca.

dnob700
dnob700
Niveau 10
04 novembre 2008 à 15:57:08

Question intéressante.

Je t'ai écrit un petit exemple de buffer overflow en C (ça m'a permi de me rafraîchir la mémoire sur la structure de la pile x86) : http://wall.sectionpc.info/C/buffer.c

Le principe est qu'il y a un tableau dans lequel on écrit une chaîne trop longue. Or, sur les plate formes courantes, la fin d'un tableau est vers le bas de la pile, là où se trouvent les informations sur la fonction qui nous a appelé par exemple.

Dans le code que je donne en exemple, la fonction f (qui est en assembleur juste pour avoir un meilleur contrôle sur ce qui se passe), ne fait pas gaffe à ce qu'elle écrit et, lors du return (instruction RET), elle revient à la fonction g avec le paramètre 42 au lien de revenir dans la fonction main. Et g pourrait être une fonction système où n'importe quoi d'autre.

Dans la réalité, l'écriture du buffer se fait typiquement par une lecture d'un paramètre (genre dans un script CGI, ou via un socket) pour lequel on ne vérifie pas la taille maximale d'un buffer.

La grande difficulté c'est de savoir quelle est l'adresse qu'il faut écrire dans le buffer et où l'écrire. Savoir où l'écrire n'est pas trop dur si on a le programme sous la main, il suffit de regarder quelles sont les variables alloué sur la pile au début de la fonction (il n'y a pas besoin du code source, ça se voit très bien sur le code assembleur d'un programme compilé) pour connaître l'endroit où il faut faire le dépassement de buffer.

Par contre connaitre l'adresse à écrire est plus dur, car maintenant, la plupart des systèmes charge les programmes à des adresses aléatoires pour rendre plus dur ce genre d'attaque. Donc soit il faut tout essayer (généralement la position est prise au hasard parmi 256 donc ce n'est pas énorme, mais si on se trompe on risque (fort probable) de cracher le programme et donc ça va être détecté), soit il y a des adresses connues (par exemples, je me demande si les fonctions systèmes ne sont pas chargées à une adresses fixe sous linux, il faudra vérifier) via, peut-être, une autre faille du programme qui donnerait une information qu'il ne devrait pas donner.

Enfin, la plupart des compilo peuvent surveiller automatiquement ce genre de chose : l'idée est d'écrire des données aléatoire en bas de la pile, données qui vont être effacé par le buffer overflow. Le programme peut alors détecté qu'il a subit une telle attaque et s'éteindre pour éviter d'être compromis par exemple. Sans compter que les langages moderne vérifie généralement toujours les dépassement de chaînes lors d'écriture. Donc, seuls des logiciels écrit dans des langages "anciens" (i.e. c ou c++) et mal compiler, sont sensible à l'attaque décrite ici. Cela dit, ça laisse énormément de programme.

Il est donc bien plus difficile de mener ce genre d'attaque que dans l'exemple trivial que je donne, mais l'idée est là.

Pour résumé, avec tes questions :
1°) Généralement, il faut connaître le logiciel qui tourne dessus (c'est facile, la plupart des serveurs donnent leur nom en permanence (sauf ceux qui sont bien configurés)). Ensuite, le code assembleur du programme peut suffire.

2°) On commence donc par du reverse engineering pour voir où est-ce que le programme est sensible, puis il faut lui envoyer des requêtes tordues pour réaliser l'attaque.

3°) Même principe que ce que j'ai décrit. Une XBox peut se connecter à internet, donc il s'agit aussi d'un serveur. Pourquoi le faire alors ? je pense que l'idée est toujours la même avec ces machines : les jeux, etc. sont protégé et les disques illisibles donc on ne sait pas comment développer pour ces machines. Avec ce genre d'attaque s'il est possible de prendre le contrôle de la machine (après tout, une XBox tourne sous windows) il est peut-être possible de récupérer les données décryptées qui sont dans sa mémoire et donc de comprendre bien mieux comment elles fonctionne que grâce à la doc technique qui n'existe pas ... (je dit ça, il y a certainement aussi des motifs crapuleux).

4°) Une fois que l'attaque est réussie, le but de l'attaquant es de pouvoir exécuter le code qu'il vaut sur la machine, du code "arbitraire", et non pas juste un petit lot de fonctionnalité qui dépendrait du logiciel. Pouvoir exécuter du code arbitraire sur une machine vaut dire en avoir le contrôle absolue.

5°) Oui. Pas forcément tout, mais il faut bien comprendre comment fonctionne le CPU, ainsi que l'OS, les compilo utilisé, etc.

dnob700
dnob700
Niveau 10
04 novembre 2008 à 16:27:25

Hop, j'ai pu en écrire une version en pure C pour gcc sous linux :
http://wall.sectionpc.info/C/buffer.gcc.c

L'autre version est maintenant à l'adresse :
http://wall.sectionpc.info/C/buffer.vc.c (je pourrais l'écrire en C, mais il faut faire trop d'addition avec VC++ qui écrit de gros prologue).

La versions linux fonctionne en 32 et 64 bits, mais la version windows ne doit fonctionner qu'en 32 bit (car le passage d'arguments pour la fonction g ce fait par les registre en 64 bits et non pas par la pile).

iznoroot
iznoroot
Niveau 2
04 novembre 2008 à 17:29:21

bon, dnob700 a brillamment développé le sujet mais je me permets d'ajouter quelques compléments concernant la nature du code arbitraire (dans l'exemple de dnob il s'agit d'un pointeur sur une fonction si j'ai bien compris)
Ce qui suit concerne les architectures x86, et vise les systèmes de type Unix
L'exemple typique, sur lequel la littérature abonde depuis des années (1995, bien que la première exploitation connue date de 198), est le cas simple du débordement dans la pile qui consiste à injecter dans le buffer un code malicieux, suivi d'une adresse de retour repetée plusieurs fois destinée à remplacer le contenu du registre IP (ce qui est possible car l'adresse d'IP suit celle du buffer dans la pile, précédée de l'adresse du pointeur de frame). Cette adresse de retour est évidemment celle du buffer, dans lequel on a au préalable inséré notre propre code. Ce code, écrit en opcodes, permet sous certaines conditions (présence d'un bit appelé bit SUID), de jouir des droits du propriétaire du programme vulnérable, généralement dans le but de s'octroyer un shell. Par exemple, un code destiné à une exploitation en local sur un programme SUID root, se chargera d'executer les instructions setuid(0);system("/bin/sh"); Dans le cas d'une exploitation à distance; le code associe (bind) un port à une socket en attente de connexion (listen), redirige les E/S sur le socket (dup2) et lance un shell dès qu'une connexion est établie (accept).
Ceci est bien sûr un cas très particulier, mais le principe général est bien de détourner le flux d'éxecution d'un programme afin de lui faire executer du code arbitraire, qui a souvent pour but de compromettre le système.

dnob700
dnob700
Niveau 10
04 novembre 2008 à 17:47:59

Oui, ce que tout décrit est tout à fait possible, mais une telle attaque se heurte à une nouvelle parade elle aussi, qui est la séparation du code et des données : sur la plupart des OS modernes avec des compilo correcte, le code est dans une certaine gamme d'adresse mémoire et la pile et le tas dans une autre. Et si le pointeur d'exécution passe dans la pile ou dans le tas, c'est immédiatement détecté par le CPU qui alerte l'OS qui termine le programme.

C'est pour ça que je n'injecte pas de code (mais c'est tout à fait possible, il faut juste un plus grand buffer), mais juste un pointeur de fonction (ce qui n'est donc pas arbitraire), par contre, si au lieu de la fonction g, j'avais mis une fonction système avec les paramètres que je veux, je peut faire des opérations "arbitraires" sur la machine, dans la limite des droits du processus que j'attaque.

dnob700
dnob700
Niveau 10
04 novembre 2008 à 22:59:23

En relisant ça, je me demande ce qui se passerait sur une architecture où la pile croit vers le haut plutôt que vers le bas : dans ce cas là, les données du contexte serait stockées avant les variables locales plutôt qu'après et il serait donc bien plus dur de les écraser accidentellement (ou par débordement de tampon).

Est-ce que quelqu'un sait pourquoi Intel a décidé de ce sens pour la pile (il y a certainement une optimisation super maligne, au moins à l'époque des 4086), et quelles sont les architectures où la pile pousse dans l'autre sens ?

dnob700
dnob700
Niveau 10
04 novembre 2008 à 23:09:30

Et comme c'est pas terrible de parler de ça sans que Chaos_Clad comprenne ce que je veux dire, ni pourquoi mes programmes fonctionnent, il faut se référer à l'excellente doc technique de Intel pour plus d'info sur la pile d'un processeur x86:
http://www.intel.com/products/processor/manuals/
Les points les plus importants sont dans les volumes 1 et 2 du "Architectures Software Developer's Manual" (le 1 donne l'architecture, c'est là qu'il y a des détail sur ce dont je parle ici, le 2 est la référence pour les instructions).

La description des manipulations de la pile lors d'un appel de fonctions sont dans le volume 1, chapitre 6 page 5 (page 160) (nommé par erreur vol. 2 6-5 dans le document).

(j'étais partis pour faire l'explication moi même, mais j'ai pas eu le courage)

Chaos_Clad
Chaos_Clad
Niveau 10
05 novembre 2008 à 16:52:00

Comme je m'y attendais, j'ai été très bien servi ^^
Merci beaucoup pour vos réponses, il va maintenant falloir que je me penche sérieusement et (très) longuement sur le sujet, mes connaissances en ASM étant proches du zéro absolu.

  • part se lamenter sur les cours d'architecture qu'il n'a pas suivi :snif: *
Sous forums
  • Aide à l'achat Mac
  • Internet
  • Macintosh
  • Création de sites web
  • Création de Jeux
  • Linux
  • Programmation
  • Steam Deck
  • Hardware
La vidéo du moment