Les codes fantastiques : rester dans la moyenne
Continuons cette série sur les codes fantastiques avec un problème apparemment simple : calculer la moyenne de deux entiers.
Bienvenue sur la base documentaire des Éditions Diamond !
Continuons cette série sur les codes fantastiques avec un problème apparemment simple : calculer la moyenne de deux entiers.
Continuons cette série sur les codes fantastiques avec deux drapeaux qui interagissent avec l’interposition de symboles.
La sécurité des codes… En voilà un sujet fourre-tout où n’importe quel article de MISC trouverait sa place ! Pour apporter une petite touche personnelle, et faire un petit clin d’œil à mon héritage familial, j’ai choisi de prendre un axe historique pour la constitution de ce dossier.
C, C++, Python, ADA, Ruby, Java, Rust, MISRA-C, Swift et j’en passe. Autant de noms de langages qui se voient associés pour leur plus grand bien ou pour leur malheur à la question de la sécurité. Ou de la sûreté. Ou les deux. En cinquante ans, les besoins ont évolué et avec eux les contraintes auxquelles les développeurs — et donc les langages qu’ils utilisent — sont soumis. Petite rétrospective à travers différents langages qui ont, ou ont eu, leur heure de gloire.
Il y a 19 ans, Ulrich Drepper, alors développeur chez Red Hat et un des contributeurs principaux de la glibc, ajoutait au changelog de la glibc la ligne suivante : sysdeps/i386/bsd-_setjmp.S: Use PTR_MANGLE for PC if defined, inaugurant ainsi l’arrivée de la protection des pointeurs de fonction stockés dans des structures internes à la glibc.
L’histoire, ou plutôt l’Histoire, est une coquine. Et quand Dennis Ritchie et Ken Thompson inventent le langage C en 1972, ils prennent une décision anodine, une micro-optimisation qui fait gagner quelques octets, mais qui aura un impact important sur la sécurité de nombreux systèmes : en C, les chaînes de caractères sont terminées par un octet positionné à zéro.
En 1996, Aleph One publiait dans l’e-zine Phrack un article intitulé « Smashing the Stack for Fun and Profit ». C’était il y a plus de 25 ans et les principes énoncés dans cet article sont toujours valides, même si leur exploitation est devenue plus technique.De manière plus conventionnelle, l’écriture dans une zone mémoire non-autorisée est un vecteur d’attaque classique connu sous le doux nom de CWE-787.Dans cet article, on se concentrera sur les attaques ciblant la pile, en détaillant quelques bugs classiques, leur exploitation historique et quelques contre-mesures qui ont été mises en place au fil du temps.
En regardant la liste des 25 failles les plus dangereuses éditées par MITRE chaque année, on ne peut qu’être frappé par la présence (ou la persistance) de thèmes bien connus : écriture illégale dans une zone mémoire, utilisation d’une zone mémoire désallouée, lecture illégale d’une zone mémoire, déréférencement de pointeur NULL, dépassement de la capacité d’un entier… Autant de sujets qui sont pourtant abordés dans les premiers chapitres de tout bouquin traitant de la sécurité logicielle. Ce qui n’en fait pas pour autant des sujets faciles dès lors que les considérations de base de code existant et de performances rentrent en compte. C’est compliqué l’optimisation multicritère !
La fonction system(3), disponible dans la bibliothèque C standard et standardisée dès C89, est symptomatique d’une époque où la sécurité n’était pas la priorité des développeurs. La lecture de sa page de manuel est pleine d’avertissements, qui sont autant d’enseignements potentiels. Allez, c’est parti, man 3 system.