Aller au contenu

CWE-120 : débordement de tampon classique, la copie sans mesure

CWE-120 : débordement de tampon classique, la copie sans mesure

Section intitulée « CWE-120 : débordement de tampon classique, la copie sans mesure »

Onzième du CWE Top 25 2025. Le libellé officiel, Buffer Copy without Checking Size of Input (‘Classic Buffer Overflow’), se traduit par « copie de tampon sans vérification de la taille de l’entrée ». Le catalogue retient deux appellations : classic buffer overflow, qui dit son ancienneté, et unbounded transfer, « transfert non borné », qui dit beaucoup mieux ce qui se passe.

→ Lire l’explication complète de la marmotte

Le produit copie un tampon d’entrée dans un tampon de sortie sans vérifier que la taille du premier est inférieure à celle du second.

Cette définition dit la cause, là où l’écriture hors limites décrit le geste. La distinction a l’air scolaire ; elle est en réalité la plus utile de toute la famille mémoire pour une équipe de développement. On ne corrige pas une écriture hors limites, qui est un symptôme : on corrige l’endroit où une taille n’a pas été comparée. Et quand un rapport ne cite que CWE-787, il manque à l’équipe l’information qui désigne la ligne fautive.

Le catalogue note d’ailleurs un second parent, dans la vue orientée développement : CWE-20, la validation insuffisante des entrées. Le défaut appartient donc aux deux familles à la fois : une erreur de gestion mémoire pour qui regarde la conséquence, une absence de validation pour qui regarde la cause. C’est l’un des rares endroits où le catalogue assume explicitement cette double lecture.

La classe couvre tous les transferts : copie de chaîne, concaténation, lecture depuis le réseau dans un tampon de taille fixe, copie d’une structure vers une autre. Le vecteur importe peu ; ce qui compte est l’absence de comparaison.

CWE-120 est une base, fille de CWE-787 dans la vue de recherche. Sous elle, deux variantes célèbres précisent où la zone débordée a été allouée : CWE-121, le débordement dans la pile, au rang 14, et CWE-122, le débordement dans le tas, au rang 16, dont le parent direct est d’ailleurs l’écriture hors limites plutôt que CWE-120, le catalogue n’ayant pas une arborescence parfaitement régulière.

Elle porte une variante propre, CWE-785, l’usage d’une fonction de manipulation de chemin sans tampon de taille maximale : cas particulier où la limite existe dans le système mais pas dans l’appel.

Et le catalogue signale qu’elle peut précéder CWE-123, la condition « écrire quoi, où » : un débordement maîtrisé permet parfois d’écrire une valeur choisie à un endroit choisi, ce qui est le degré de contrôle que recherche toute exploitation.

Parce qu’une partie du monde tourne encore sur des interfaces sans borne. La bibliothèque standard du langage C propose historiquement des fonctions qui copient jusqu’au caractère de fin sans se préoccuper de la taille de destination. Leurs remplaçantes bornées existent depuis longtemps, et les compilateurs émettent des avertissements, mais le code qui les emploie encore est précisément celui qu’on ne recompile pas : micrologiciels, pilotes, bibliothèques embarquées dans des produits dont l’éditeur a disparu.

Parce que les données réseau arrivent dans des tampons de taille fixe. Tout protocole implémenté à la main sur un équipement contraint lit un en-tête, en tire une longueur, et copie. Si la longueur annoncée n’est pas comparée à la taille du tampon, le défaut est là : et cette séquence se réécrit à chaque nouveau produit.

Parce que l’analyse statique la détecte bien. Un appel à une fonction de copie non bornée se repère sans exécuter le programme, ce qui alimente régulièrement des campagnes de signalement en série, donc des points dans un classement bâti sur les vulnérabilités publiées.

Le site décrit la mécanique dans comment un débordement de tampon écrase la pile : ce qu’il y a derrière le tampon, pourquoi la zone écrasée contient parfois l’adresse où le programme doit revenir, et ce que cela donne à l’attaquant.

Pour les défenses, ASLR, DEP, NX, canaris et CFI détaille les contre-mesures ajoutées par les compilateurs et les systèmes. Elles sont efficaces et ne corrigent rien : le programme s’arrête au lieu d’obéir. Pour la suppression de la classe elle-même, Rust et la sécurité mémoire par construction explique la vérification des bornes, qui déplace le problème du programmeur vers le compilateur.

Côté chaîne de développement, intégrer SAST, DAST et IAST dans une CI/CD est le bon niveau de réponse : c’est une faiblesse qui se traite par l’outillage, pas par la vigilance.

Bannir les fonctions non bornées par la chaîne de compilation, pas par une consigne. Un interdit vérifié à la compilation est respecté ; un interdit écrit dans une charte est respecté jusqu’au prochain correctif urgent.

Faire voyager la taille avec le pointeur. La plupart des débordements proviennent d’une fonction interne qui reçoit une adresse sans sa longueur, parce que l’appelant « sait » que les données sont assez courtes. Le remède tient à une convention : toute fonction qui reçoit un tampon reçoit sa taille, sans exception, y compris pour les données réputées internes.

Traiter la longueur annoncée comme une entrée hostile dans tout code de protocole. La comparer à la taille réellement disponible, et refuser proprement en cas d’écart, est la seule chose qui distingue un décodeur sûr d’un décodeur vulnérable.

Une équipe qui ne distingue pas la cause du geste reçoit des rapports qui disent « écriture hors limites » et cherche l’erreur à l’endroit du plantage, lequel se produit généralement dans un module innocent qui s’est fait écraser ses données. Le temps perdu est considérable, et la correction qui finit par être écrite rafistole l’appel signalé sans toucher à la convention qui a produit le défaut : de sorte que les cinquante autres copies non bornées du même dépôt restent en place. Le coût final est celui d’une exposition longue : ces faiblesses vivent dans des composants bas niveau dont la mise à jour demande un redémarrage de service, un déploiement de micrologiciel ou une recompilation que personne ne veut assumer, si bien que la fenêtre entre la publication du correctif et son installation effective se mesure en mois, parfois en années pour les équipements embarqués.

Pour ranger des données, un programme réserve en mémoire un espace de taille fixée à l’avance : par exemple soixante-quatre caractères pour un nom. Quand il reçoit un nom, il le recopie dans cet espace.

Le défaut consiste à faire cette copie sans comparer la longueur du nom reçu à la taille de l’espace disponible. Si le nom fait deux cents caractères, les cent trente-six caractères excédentaires s’écrivent au-delà de l’espace prévu, c’est-à-dire sur les données rangées juste après. Le programme n’a rien forcé : il a recopié jusqu’au bout, comme on le lui demandait.

C’est ce défaut que le catalogue CWE appelle CWE-120, le « débordement de tampon classique ». Son nom contient le mot « classique » parce qu’il est documenté depuis les années 1980 et qu’il figure dans tous les manuels. Il reste au onzième rang du classement annuel, ce qui mérite une explication.

Deux raisons. D’abord, certaines fonctions très anciennes des langages de programmation font cette copie sans mesurer, par conception : elles existent toujours, et le code qui les utilise aussi, notamment dans les logiciels embarqués des appareils, qu’on ne réécrit jamais. Ensuite, chaque fois qu’un programme reçoit des données par le réseau, il lit d’abord une longueur annoncée par l’expéditeur. S’il fait confiance à cette annonce au lieu de vérifier la place dont il dispose, le défaut réapparaît, dans du code neuf.

La parade est connue : toujours transmettre la taille avec les données, toujours comparer avant de copier. Et, dans les langages récents, laisser le compilateur refuser les programmes qui ne le font pas : ce qui est plus fiable que de compter sur l’attention de celui qui écrit.

À lire aussi

Pages voisines

: les deux pages se citent l’une l’autre.