Mis à jour le mercredi 8 mars 2017
  • 4 heures
  • Facile

Les Buffer Overflow

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Oh mon Dieu ! J'ai peur ! Rien que le nom, on se croirait dans une série américaine ! :waw:

Eh oui, on passe ici à un autre niveau de sécurité ! Et pour cause : la faille ne se trouve pas dans le code, mais bien dans le langage lui-même ! Enfin plus précisément il résulte d'une mauvaise utilisation du langage C qui gère le PHP. Car oui, PHP est en fait construit en librairies C.

Ok j'ai rien compris je passe au chapitre suivant.

Non jeune padawan ! N'ai crainte ! Bien que les Buffer Overflow soient vraiment complexes a sécuriser dans les applications en C, elle ne le sont pas en PHP. En effet, les développeurs ne touchent jamais au code C qui se trouve derrière PHP, il n'est donc pas de notre ressort de les sécuriser à ce niveau-là. Nous devons simplement avoir des connaissances sur où, pourquoi et comment ont lieu ces attaques.

Bah si ce n'est pas à nous de les sécuriser, on s'en fiche un peu non ?

Détrompez-vous ! Si vous pensez que les Buffer Overflow ne vous concernent pas, vous foncez droit dans un mur ! Vous avez fermé votre porte blindée à double tour, construit des murs solides, clôturé votre jardin, mais laissé la fenêtre du premier étage grande ouverte. Alors peut-être que personne n'essaiera jamais de grimper jusque-là par manque de connaissance en escalade, mais le jour ou un Yamakasi réussira à rentrer, c'est toute la sécurité de votre maison qui sera compromise. Bon j'arrête ici avec les métaphores, mais j'espère que vous avez saisi l'idée.

Explication

Le "Buffer Overflow" ou "dépassement de mémoire tampon" est un principe assez simple. Chaque donnée gérée par l'ordinateur est stockée temporairement dans un tampon avant d'être traitée. Chaque tampon contient donc une série de caractères (et un pointeur pour les connaisseurs). Dans le cas du langage C, des tampons sont systématiquement utilisés pour réguler les Entrées-Sorties du programme (Ex : la lecture ou l'écriture dans un fichier). A chaque fois qu'une entrée utilisateur doit être stockée, un espace est alloué par l'ordinateur. Le principe du Buffer Overflow est simple : écrire plus de données que le tampon ne peut en contenir. Le tampon va donc littéralement "déborder". Cela aura pour effet d'écraser des parties du code de l'application et permettra au pirate d'injecter des données utiles pour l'exploitation. Voilà une liste non-exhaustive de ce qu'il pourra faire avec votre serveur :

  • Injection de code (SQL ou non)

  • Exécution de code arbitraire (Le pirate peut alors prendre le contrôle total du serveur)

  • Attaque par déni de service (ou DOS) qui rendrait votre serveur indisponible

  • Utilisation de votre serveur pour d'autres attaques

Il faut tout de même savoir que ce type d'attaque nécessite une bonne connaissance du fonctionnement d'un ordinateur ainsi que de solides bases en programmation. Ce n'est donc pas à la portée de tout le monde.

Bien évidement ce n'est qu'une explication très imagée de ce qu'est réellement un Buffer Overflow, mais je préfère que mon cours reste accessible à tous. Mon but n'était pas ici de vous expliquer précisément comment fonctionne ce bug, mais bien d'expliquer à tous son fonctionnement général. Si vous souhaitez creuser un peu le sujet, il y a beaucoup de documentations à ce sujet sur internet.

Étude de cas

Avant de vous expliquer comment vaincre ce fardeau de la programmation, j'aimerai vous parler de cas précis qui ont été découvert il n'y a pas si longtemps que ça. Car oui, PHP a déjà été victime des Buffer Overflow. Ça ajoutera une dimension concrète à mes explications, et ça fera le plus grand bien à votre culture générale ;)

Bon pour commencer vous devez vous demander

Mais en PHP, il n'y a pas de limite de taille pour les variables contrairement au C ou au Java. Alors il devrait être complètement immunisé contre ce type d'attaque, non ?

Oui cette théorie est la plus plausible et fonctionne sur le papier. Mais malheureusement pour nous ce n'est pas aussi simple. Comme je l'ai dit tout à l'heure, le PHP est géré par du langage C qui, lui, possède des limites de taille pour les variables. Il existe donc bel et bien une limite de taille pour les variables PHP. Cette limite est imposée en fonction de la mémoire disponible sur le serveur, et des librairies C sur lesquelles sont basés l’interpréteur PHP et ses librairies.

En 2006, un vulnérabilité de ce type est découverte dans les fonction htmlspecialchars() et htmlentities() par un groupe de chercheur en sécurité informatique allemand (the Hardened-PHP Project). En effet, ces fonctions ont été construites avec l'idée qu'un caractère HTML ne dépasse jamais huit caractères. En général le principe marche, mais il existe des exceptions. C'est notamment le cas si vous utiliser l'encodage de caractère UTF-8. Bien qu'il soit très utile et assure une portabilité maximum à votre site, il est plus "lourd" que les autres. Pour supporter ces très nombreux jeux de caractères, UTF-8 n'alloue pas moins de 4 byts à chacun de ces caractères :

  • Les 128 caractères ASCII : Ce sont les caractères standards, les plus utilisés. Ils sont basés sur l'anglais, et ne prennent donc pas en compte les accents. UTF-8 a en fait été créé pour dépasser les limites imposées par l'ASCII. L'encodage UTF-8 de chacun de ces caractères ne nécessite qu'un byte.

  • Les alphabets latin, grec, arménien, hébreu, arabe [...] nécessitent quant à eux 2 bytes pour être encodés. Et c'est ici que nos fonctions se retrouvent en difficulté. Elles s'attendent à recevoir  un caractère de 1 byte de long, et on lui en envoie un qui en fait 2. Ça sent fort le débordement tout ça...

  • Les caractères basés sur le standard Unicode nécessite 3 bytes pour être encodés. Cela représente la majorité des caractères utilisé aujourd’hui.

  • Certains caractères Unicode rarement utilisés nécessitent 4 bytes pour être encodés par UTF-8. C'est pour cela que UTF-8 alloue 4 bytes (et non 3). Cela ne signifie pas pour autant que ce quatrième byte est perdu. Mieux vaut laisser un byte vide et inoffensif, que de l'utiliser et prendre des risques.

Donc que se passera-t-il si quelqu'un insère un caractère grec dans mon formulaire ?

Quand l'encodeur va rencontrer ce caractère qui est plus large que les 8 qu'il ne peut supporter, PHP va se contenter d'augmenter la taille du tampon de 2 caractères. Malheureusement, si l'entité HTML fait 11 caractères, le tampon va déborder et donc rendre possible toute sorte d'attaque. Un petit schéma pour éclairer tout cela :

Voilà pour notre petite étude de cas. Vous êtes maintenant incollable sur le fonctionnement de ce bug. On peut maintenant passer à la sécurisation :soleil:

Comment s'en protéger

Bon bien évidement nous resterons ici dans le cadre de notre application web. Je ne vais pas commencer à vous parler de sécurité dans les programmes C, sinon on n'est pas sortis d'affaire :D

Je vais peut-être vous décevoir, mais il n'existe pas une fonction miracle qui fait disparaître cette faille. En fait, si vous voulez vous prémunir contre ce type d'attaque, il va falloir être très rigoureux dans votre façon de développer. Ne comptez pas sur PHP pour garder votre application en sécurité. De nouvelles failles seront surement découvertes un jour, et c'est à vous de savoir protéger votre code. Je vais vous mettre plusieurs points à surveiller en permanence quand vous créer de nouveaux éléments sur votre application PHP.

- Veillez à toujours avoir PHP à jour sur votre serveur et à ne pas utiliser de fonctions obsolètes. C'est extrêmement important, de nombreux bug sont fixés à chaque mise à jour, et ce n'est pas pour rien qu'elles sont là. Si une nouvelle version est proposée, mettez votre serveur à jour. Si on vous dit d'utiliser PDO pour vos requêtes SQL, faites-le !

- Restez au courant des dernières alertes. Votre serveur est peut-être à la pointe de la sécurité aujourd'hui, cela ne garantis pas pour autant qu'il le sera demain. De nouvelles failles sont découvertes tous les jours, vous vous devez d'être au courant. Des organismes sont spécialisés sur le sujet et regroupent tous les nouveaux dangers potentiels.

- Rappelez-vous que les données externes au programme ne viennent pas forcément directement de l'utilisateur. Un flux RSS peut être un vecteur d'attaque s'il est correctement utilisé. Votre programme récupère des données du flux, à priori pas de danger ça vient d'une source sure, vous faites confiance. Grave erreur. Pareil si vous utilisez des bases de données externes. Vous ne maitrisez pas ce qui n'est pas sur votre serveur. Si vous ne vérifiez pas ce que le service externe vous envoie et que celui-ci est corrompu, votre sécurité l'est également.

- Maitrisez le contenu de toutes vos variables. N’autorisez que ce qui est nécessaire. Mieux-vaut trop de restrictions que pas assez ! N'oubliez pas le premier commandement de la sécurité informatique : ne faites jamais confiance ! Limitez tout.

  • La longueur de la chaine avec strlen()

  • Utilisez htmlspecialchars() pour éviter les injections

  • N’autorisez que les caractères dont vous avez besoin. Par exemple pour une variable qui contiendra un âge, n’autorisez que les chiffres compris entre 0 et 120

  • Virez les caractères spéciaux si vous n'en avez pas besoin

  • N'autorisez les majuscules que si nécessaire. Vous pouvez les gérer avec une expression régulière ou les fonctions strtolower() et strtoupper()

  • Ne faites pas confiance aux listes déroulantes, checklist, checkbox et autres input prédéfinis en HTML. Ça se modifie coté client

  • ...

En bref, soyez de vrais paranos. Même si les majuscules ne posent à priori aucun soucis de sécurité, ne les autorisez que si nécessaire. Partez du principe que si vous laissez des libertés à vos utilisateurs, ils l'utiliseront contre vous. Soyez meilleur qu'eux ! :diable:

Exemple de certificat de réussite
Exemple de certificat de réussite