Cet article vise à décrire les principales options de gcc permettant de renforcer la sécurité des programmes ainsi que les attaques couvertes par ces options.
gcc (GNU Compiler Collection) est le compilateur bien connu maintenu par le projet GNU et disponible sur la plupart des systèmes de type Unix et sous Windows grâce aux projets Cygwin et MinGW. Initialement conçu comme compilateur pour le langage C, gcc a bénéficié, depuis sa première version sortie en 1987, de nombreuses améliorations, que ce soit au niveau des langages acceptés (C++, Objective-C, Fortran, Java, Ada, etc.), mais également en ce qui concerne les architectures matérielles supportées. Parmi ces améliorations, on notera également l'ajout de nouvelles fonctionnalités visant à renforcer la sécurité des programmes générés par gcc. Ces fonctionnalités sont activables au moment de la compilation en spécifiant les options correspondantes en ligne de commandes et peuvent être classées en deux catégories : celles qui influent sur le code machine produit par le compilateur et celles qui tentent d'identifier des problèmes de sécurité en analysant le code source du programme. [...]
En résumé, les options de gcc recommandées pour renforcer le niveau de sécurité d'un programme sont :
$ gcc -O2 -Wunreachable-code -pedantic -Wextra -Wall -Wformat=2 -D_FORTIFY_SOURCE=2 \
-fstack-protector --param ssp-buffer-size=4 -fPIE -pie -Wl,-z,relro,-z,now -o sample sample.c
Sur les versions récentes de gcc (à partir de 4.9), les paramètres -fstack-protector --param ssp-buffer-size=4 peuvent avantageusement être remplacés par -fstack-protector-strong. L'outil hardening-check présent sur les distributions Ubuntu et Debian permet de s'assurer de la bonne prise en compte de ces options :
$ hardening-check sample
sample:
Position Independent Executable: yes
Stack protected: yes
Fortify Source functions: yes
Read-only relocations: yes
Immediate binding: yes
Aujourd'hui, sur une architecture matérielle récente, l'activation de ces options n'impacte que de façon marginale les performances d'un programme. Il serait donc dommage de s'en priver, tout en gardant à l'esprit que ces renforcements ne visent qu'à bloquer des techniques génériques d'exploitation de vulnérabilités. Dans des circonstances particulières, certaines peuvent être contournées par un attaquant suffisamment motivé. Il convient donc d'intégrer ces mesures dans une logique de défense en profondeur pour limiter les risques en cas d'exploitation réussie d'une vulnérabilité.
There will be a new option in gcc 4.9 named “-fstack-protector-strong“, which offers an improved version of “-fstack-protector” without going all the way to “-fstack-protector-all“. The stack protector feature itself adds a known canary to the stack during function preamble, and checks it when the function returns. If it changed, there was a stack overflow, and the program aborts. This is fine, but figuring out when to include it is the reason behind the various options.