Aller au contenu

CWE-787 : écriture hors limites, la tête de la famille mémoire

CWE-787 : écriture hors limites, la tête de la famille mémoire

Section intitulée « CWE-787 : écriture hors limites, la tête de la famille mémoire »

Cinquième du CWE Top 25 2025, et surtout la plus haute d’une famille qui en occupe six rangs à elle seule. Le libellé officiel, Out-of-bounds Write, se traduit sans difficulté par « écriture hors limites » ; le catalogue accepte aussi l’appellation générique Memory Corruption, qui a l’avantage de dire le résultat et l’inconvénient de ne rien dire du défaut.

→ Lire l’explication complète de la marmotte

La définition est d’une concision rare : le produit écrit des données au-delà de la fin, ou avant le début, du tampon prévu.

Les deux directions comptent, et la seconde est souvent oubliée. Écrire après la fin d’une zone mémoire est le cas d’école ; écrire avant son début, à cause d’un indice négatif ou d’un calcul de décalage qui passe sous zéro, produit le même genre de dégâts et se repère moins bien à la relecture.

La classe ne dit rien de la cause : elle désigne le geste, pas l’erreur de raisonnement qui y conduit. Une taille mal calculée, une longueur reçue de l’extérieur et crue sur parole, un entier qui déborde avant de servir d’indice, une boucle dont la condition d’arrêt est fausse d’une unité : tout cela aboutit à CWE-787. C’est pourquoi les rapports précisent souvent une classe voisine en plus de celle-ci : la cause et le geste ne portent pas le même numéro.

Elle ne dit rien non plus de la conséquence, qui va du plantage immédiat à l’exécution de code arbitraire selon ce qui se trouvait derrière le tampon. Cette indétermination est la raison pour laquelle la classe pèse si lourd dans un classement pondéré par la gravité : la même faiblesse reçoit, selon le contexte, les notes les plus hautes de l’échelle.

CWE-787 est une base, fille de la classe CWE-119, « restriction incorrecte des opérations dans les limites d’un tampon mémoire », qui couvre aussi bien les lectures que les écritures. Cette classe parente est la racine commune de toute la famille mémoire.

Cinq entrées descendent directement de CWE-787, et trois d’entre elles figurent au Top 25 :

  • CWE-120, la copie de tampon sans vérification de la taille, dite débordement de tampon classique, rang 11 ;
  • CWE-121, le débordement dans la pile, rang 14 ;
  • CWE-122, le débordement dans le tas, rang 16 ;
  • CWE-123, la condition « écrire quoi, où », qui désigne le cas où l’attaquant contrôle à la fois la valeur écrite et son emplacement ;
  • CWE-124, le débordement par le bas, symétrique du débordement classique.

Il faut mesurer ce que cette arborescence implique pour la lecture du classement : les rangs 5, 11, 14 et 16 décrivent le même défaut à quatre niveaux de précision, et le rang 8, la lecture hors limites, en est la version non destructive. Un lecteur pressé en conclut que la mémoire représente six problèmes distincts ; il y en a un, observé par six fenêtres.

Parce que la gravité moyenne est maximale. Une écriture hors limites réussie conduit, dans les cas défavorables, à l’exécution de code. Le score du classement multiplie la fréquence par la gravité : une faiblesse moyennement fréquente mais systématiquement critique monte aussi haut qu’une faiblesse très fréquente et bénigne.

Parce que les produits concernés sont ceux dont on ne peut pas se passer. Noyaux, pilotes, piles réseau, décodeurs d’images et de vidéos, micrologiciels, bibliothèques de compression : tout ce qui est écrit en C ou C++ parce qu’il faut aller vite et parler au matériel. Ces composants sont par ailleurs ceux qui traitent le plus de données non fiables venues du réseau.

Parce que l’outillage de détection a beaucoup progressé. Les techniques de test par génération d’entrées aléatoires et les analyseurs dynamiques trouvent ces défauts en série, et chaque campagne de ce genre produit une rafale de vulnérabilités publiées. Le classement, qui mesure ce qui se signale, enregistre autant le progrès des outils que le danger lui-même.

Le site explique le mécanisme en détail : comment un débordement de tampon écrase la pile décrit ce qui se trouve derrière le tampon et pourquoi l’écraser donne la main à l’attaquant. Inutile de le reprendre ici.

Pour les défenses, ASLR, DEP, NX, canaris et CFI détaille les protections qui rendent l’exploitation difficile sans corriger le défaut, distinction essentielle : ces mécanismes transforment une prise de contrôle en plantage, ce qui est un progrès considérable et pas une correction.

Enfin, la seule approche qui supprime la classe au lieu de la contenir est le choix du langage : Rust et la sécurité mémoire par construction dit ce que cette garantie couvre, et où elle s’arrête (les blocs non sûrs, les liaisons vers du code C, les défauts de logique qu’aucun compilateur ne rattrape).

Mesurer avant d’écrire, pas après. La règle est connue ; ce qui manque généralement est la discipline de propager la taille avec le pointeur, partout, y compris dans les fonctions internes qui « ne reçoivent que des données déjà validées ».

Faire tourner les outils en continu. Analyse statique à chaque validation, test par génération d’entrées sur les parseurs et les décodeurs, analyseurs dynamiques dans les tests d’intégration : c’est l’investissement qui rapporte le plus sur du code existant qu’on ne va pas réécrire.

Réécrire les composants les plus exposés dans un langage à sûreté mémoire, en commençant par ceux qui lisent des données venues du réseau. Réécrire tout est irréaliste ; réécrire le parseur qui reçoit l’inconnu est souvent possible, et c’est là que se trouvent la majorité des vulnérabilités publiées.

Une équipe qui traite chaque débordement comme un bogue isolé corrige des symptômes dans un code qui en produira d’autres, au même rythme, tant que les tailles continueront de voyager séparément des pointeurs. Le défaut a ceci de particulier qu’il ne se manifeste pas forcément là où il a été commis : la zone écrasée appartient à un autre module, qui plante une heure plus tard pour une raison incompréhensible, et l’équipe passe des journées à chercher la cause dans le module innocent. En production, le même défaut donne à qui sait s’en servir l’exécution de code avec les privilèges du processus touché, c’est-à-dire souvent ceux du système lorsqu’il s’agit d’un pilote ou d’un service réseau. Et comme ces composants sont ceux qu’on met à jour le moins volontiers (un noyau, un micrologiciel d’équipement, une bibliothèque embarquée dans quarante produits), la fenêtre d’exposition se compte en années plutôt qu’en semaines.

Un programme réserve dans la mémoire de l’ordinateur des espaces de taille fixe pour y ranger ses données : douze caractères pour un code postal, deux cent cinquante-six pour un nom de fichier. Ces espaces sont contigus, comme les cases d’une feuille de calcul : juste après l’un commence un autre, qui contient autre chose.

Si le programme écrit plus de données que l’espace réservé n’en contient, le surplus ne disparaît pas : il écrase ce qui se trouvait juste après. Les données du voisin sont remplacées par celles qui débordent. Selon ce que contenait la case voisine, le programme se trompe de calcul, s’arrête brutalement, ou (c’est le cas grave) exécute des instructions choisies par celui qui a fourni les données trop longues.

C’est ce défaut que le catalogue CWE appelle CWE-787, « écriture hors limites ». Il est en tête de toute une famille : selon que le débordement se produit dans une zone appelée la pile ou dans une autre appelée le tas, selon qu’il s’agit d’écrire ou seulement de lire au-delà des limites, le catalogue attribue des numéros différents, mais la cause est la même, personne n’a vérifié que la place suffisait.

Deux choses rendent ce défaut durable. D’abord, il concerne surtout les logiciels écrits dans des langages anciens et rapides, utilisés là où la vitesse compte : systèmes d’exploitation, pilotes de matériel, lecteurs vidéo, équipements réseau. Ensuite, les protections ajoutées depuis vingt ans ne corrigent pas le défaut : elles rendent son exploitation difficile, de sorte que le programme s’arrête au lieu d’obéir à l’attaquant. C’est mieux, mais ce n’est pas la même chose, et la seule solution de fond consiste à employer des langages qui rendent ce genre d’erreur impossible à écrire.

À lire aussi

Pages voisines

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