Attaque par débordement de tampon : définition, types et prévention
Le débordement de tampon est une vulnérabilité logicielle majeure exploitée pour exécuter du code.
- Touche principalement les langages C et C++.
- Vise la pile d’exécution en écrasant l’adresse de retour.
- Les fonctions strcpy et gets sont des failles connues.
- Le Stack-Smashing Protector (SSP) détecte l’écrasement de l’adresse.
- Privilégier des langages résistants gérant la mémoire automatiquement.
Qu’est-ce qu’une attaque par débordement de tampon ?
Le débordement de tampon (buffer overflow) est considéré comme la vulnérabilité logicielle la plus courante. Elle touche principalement les langages C et C++, qui offrent un contrôle direct sur la mémoire. Un tampon est un segment mémoire à capacité limitée : lorsque des données dépassent cette capacité, elles viennent écraser les zones adjacentes. Par exemple, si un tampon attend 8 bits d’identifiants et reçoit 11 bits, les 3 bits excédentaires corrompent la mémoire voisine.
L’attaquant exploite ce dépassement pour écraser la mémoire avec du code exécutable. La technique la plus répandue vise la pile d’exécution, une structure fonctionnant en dernier arrivé, premier sorti. En modifiant l’adresse de retour d’une fonction, l’attaquant détourne le flux du programme et prend le contrôle de la machine. Cette faille est si critique que même des environnements réputés sécurisés doivent intégrer des protections spécifiques pour limiter les risques d’exploitation.
Comment prévenir les attaques par débordement de tampon ?

La prévention d’une attaque par débordement de tampon repose principalement sur des pratiques de développement sécurisées. L’objectif est de réduire les risques d’exploitation en contrôlant strictement la manipulation de la mémoire. Voici les mesures les plus efficaces à mettre en œuvre :
- Réécrire les fonctions avec un paramètre de taille pour limiter strictement la quantité de données copiées.
- Utiliser
strncpyà la place destrcpypour les copies de chaînes. - Privilégier
fgetsplutôt quegetspour la lecture des entrées. - Activer Stack-Smashing Protector du compilateur pour détecter l’écrasement de l’adresse de retour.
- Privilégier les langages résistants qui gèrent automatiquement la mémoire et les limites de tampons.
Des fonctions alternatives plus sûres
Les fonctions strcpy et gets sont des failles bien connues du langage C. Elles ne vérifient jamais la taille de la destination, ce qui permet à un attaquant d’écrire au-delà de la zone allouée. En remplaçant strcpy par strncpy, vous spécifiez un nombre maximal de caractères à copier, comparable à la capacité attendue du tampon (par exemple, 8 bits pour un identifiant, tandis que des données reçues pourraient en représenter 11 bits). De même, fgets permet de limiter la lecture à la taille du tampon, contrairement à gets.
Protections au niveau du compilateur et du langage
Le Stack-Smashing Protector (SSP) est une protection intégrée aux compilateurs comme GCC. Cette fonctionnalité ajoute une valeur sentinelle sur la pile d’exécution, juste avant l’adresse de retour. Si un débordement survient, cette valeur est corrompue et le programme s’arrête avant de laisser l’attaquant prendre le contrôle. Cette protection s’est popularisée après la sortie du compilateur GCC version 4.9, qui l’a rendue accessible au plus grand nombre.
Enfin, le choix du langage de programmation est une décision stratégique. Les langages comme Python, Java ou C# gèrent les limites de tampons de manière implicite, réduisant drastiquement le risque d’attaque par débordement de tampon. Si l’écriture en C ou C++ est indispensable, la formation des développeurs aux bonnes pratiques et l’utilisation d’outils d’analyse statique de code sont des compléments indispensables pour limiter les failles de sécurité.
Types d’attaques par débordement de tampon
L’attaque par pile d’exécution (stack overflow)
La pile d’exécution est la zone mémoire la plus ciblée par les attaques par débordement de tampon. Elle stocke les paramètres de fonction, les variables locales et surtout les adresses de retour ces pointeurs qui indiquent au programme où reprendre son exécution après un appel de fonction.
Le principe de l’attaque est redoutablement simple : l’attaquant envoie plus de données que la taille prévue pour le tampon. Par exemple, si un tampon d’identifiants est prévu pour 8 bits et que le système reçoit 11 bits, les 3 bits excédentaires vont s’écrire ailleurs en mémoire.
L’objectif concret est d’écraser l’adresse de retour de la fonction en cours. Une fois cette adresse remplacée par celle d’un code malveillant, le programme exécute ce code dès la fin de la fonction. C’est l’architecture x86, avec sa gestion particulière de la pile et des registres ebp et esp, qui rend cette technique possible sur la plupart des systèmes.
Le dépassement de tas et le débordement de nombre entier
Toutes les vulnérabilités ne se situent pas dans la pile d’exécution. Le tas (heap en anglais) désigne la zone mémoire allouée dynamiquement aux variables créées pendant l’exécution du programme. Un dépassement de tas peut corrompre d’autres variables situées à proximité et conduire à une exécution de code arbitraire.
Le débordement de nombre entier est un cas particulier insidieux. Lorsqu’une valeur entière dépasse sa capacité maximale, elle se transforme en une valeur inattendue souvent négative ou très petite. L’attaquant exploite cette faille pour contourner les vérifications de taille et provoquer un débordement de tampon malgré les contrôles.
- Dépassement de tas : écrase d’autres variables mémoire pour modifier le comportement du programme
- Débordement entier : modifie la valeur stockée pour déjouer les contrôles de taille
- Failles exploitées : fonctions gets et strcpy du langage C, historiquement responsables de nombreuses brèches
Le langage C reste particulièrement exposé car il ne vérifie pas automatiquement les limites des tampons. Les fonctions strcpy et gets ne prennent aucun paramètre de taille, laissant le programmeur responsable de la protection de sa mémoire une responsabilité souvent oubliée.
Exemples concrets d’attaques par débordement de tampon
Depuis le début des années 2000, le débordement de tampon est devenu l’une des méthodes d’intrusion les plus prisées par les cybercriminels. L’objectif est presque toujours le même : écraser l’adresse de retour d’une fonction pour rediriger le programme vers un code malveillant. Voici les cibles et scénarios d’exploitation les plus fréquents.
- Serveur OpenSSH : cible historique des attaques, ce service critique a subi plusieurs failles majeures permettant une prise de contrôle à distance sans authentification.
- Bibliothèques d’images : les fonctions de décodage (JPEG, PNG) contenaient des tampons mal dimensionnés, exploitables via un simple fichier piégé.
- Adresse de retour : les attaquants ciblent précisément ce pointeur dans la pile pour détourner le flux d’exécution du programme.
- Systèmes variés : Windows, Linux et macOS ont tous été touchés, preuve que cette faille dépasse les frontières des environnements.
Pourquoi ces attaques restent si redoutables
La force de cette technique réside dans sa capacité à transformer une simple erreur de programmation en compromission totale du système. Un attaquant peut ainsi injecter du code exécutable directement dans la mémoire, sans avoir besoin d’un accès préalable à la machine. Les serveurs publics, les routeurs et les équipements embarqués sont particulièrement exposés, car ils utilisent massivement les langages C et C++. La découverte quotidienne d’environ 130 failles logicielles montre l’ampleur du problème, même si moins de 1% d’entre elles sont réellement exploitées en conditions réelles.
La correction de ces vulnérabilités a longtemps reposé sur des correctifs manuels. Ce n’est qu’à partir de la version 4.9 du compilateur GCC, sortie en 2014, que des protections automatiques comme le Stack-Smashing Protector ont été généralisées, réduisant considérablement la fenêtre de tir des attaquants. Malgré ces progrès, la vigilance reste de mise : chaque nouvelle bibliothèque logicielle peut réintroduire ce type de faille.
Vulnérabilités et risques associés
Les fonctions gets et strcpy du langage C figurent parmi les plus dangereuses, car elles ne vérifient jamais la taille des données copiées. Sur une architecture x86, la pile d’exécution contient l’adresse de retour de chaque fonction ; une écriture au-delà du tampon alloué permet alors à l’attaquant de contrôler le pointeur d’instruction et de rediriger le programme vers son propre code malveillant.
Le risque ne se limite pas à la pile : tout tampon situé ailleurs en mémoire peut être dépassé, notamment ceux du tas. Si la capacité attendue d’un tampon d’identifiants est de 8 bits mais que des 11 bits de données sont reçus, l’excédent déborde dans les zones adjacentes. Les experts identifient environ 130 failles par jour en cyberattaque, même si moins de 1% sont réellement exploitées par les attaquants.
La version 4.9 du compilateur GCC a notablement amélioré les protections intégrées, mais la vigilance reste essentielle. Une seule variable locale mal dimensionnée peut compromettre l’ensemble du système d’exploitation, d’où l’importance de combiner des pratiques de codage sûr, des mécanismes de protection mémoire et une revue régulière du code source.
Comment fonctionne la mémoire dans un processus ?
Pour saisir le mécanisme d’une attaque par débordement de tampon, il faut visualiser l’organisation de la mémoire d’un processus. Elle se divise en zones distinctes : la zone de code stocke les instructions du programme, tandis que la zone de données contient les variables manipulées. Ces segments ont une capacité limitée, comme un tampon.
C’est dans la pile d’exécution que se joue l’essentiel. Cette structure, fonctionnant en dernier arrivé, premier sorti, conserve les paramètres, les variables locales et surtout les adresses de retour des fonctions. Les registres ebp et esp gèrent cette pile en pointant vers son sommet et sa base, ce qui permet aux programmeurs de suivre précisément l’exécution du code.
Un tampon d’identifiants d’une capacité normale de 8 bits peut ainsi recevoir 11 bits de données, corrompant la mémoire adjacente et détournant le flux d’exécution. Comprendre cette architecture est la clé pour appréhender comment un attaquant peut manipuler ces segments et écraser l’adresse de retour pour lancer son propre code.
Impacts d’une attaque buffer overflow
Une attaque par débordement de tampon aboutit fréquemment à l’exécution de code malveillant directement dans le contexte du programme vulnérable. L’attaquant peut alors prendre le contrôle total du processus et contourner les mécanismes de sécurité du système. Les données critiques stockées en mémoire se retrouvent altérées, corrompant le fonctionnement normal de l’application et ouvrant la voie à des actions non autorisées.
Au-delà de la compromission immédiate, les répercussions touchent l’ensemble de l’infrastructure. Un simple écrasement de l’adresse de retour permet de rediriger l’exécution vers un shell distant, offrant à l’attaquant les mêmes privilèges que l’utilisateur légitime. Dans les environnements critiques, cela conduit à une compromission complète du système d’exploitation, avec vol de données sensibles, installation de portes dérobées ou propagation latérale dans le réseau. La rapidité d’exploitation explique pourquoi ces failles restent une priorité pour les équipes de sécurité.
