Nous avons des systèmes de construction en production dont personne ne se soucie et ces machines exécutent des versions anciennes de GCC comme GCC 3 ou GCC 2.
Et je ne peux pas persuader la direction de le mettre à niveau vers un plus récent: ils disent, "si ce n'est pas cassé, ne le réparez pas".
Puisque nous maintenons une base de code très ancienne (écrite dans les années 80), ce code C89 se compile très bien sur ces compilateurs.
Mais je ne suis pas sûr que ce soit une bonne idée d'utiliser ces vieux trucs.
Ma question est:
L'utilisation d'un ancien compilateur C peut-elle compromettre la sécurité du programme compilé?
METTRE À JOUR:
Le même code est construit par Visual Studio 2008 pour les cibles Windows, et MSVC ne prend pas encore en charge C99 ou C11 (je ne sais pas si le nouveau MSVC le fait), et je peux le construire sur ma machine Linux en utilisant le dernier GCC. Donc, si nous abandonnions simplement un GCC plus récent, il serait probablement aussi bien construit qu'avant.
-O3 -Wall -Wextra -fsanitize=undefined
avec gcc et clang modernes devrait aider.Réponses:
En fait, je dirais le contraire.
Il existe un certain nombre de cas où le comportement n'est pas défini par le standard C mais où il est évident ce qui se passerait avec un "compilateur stupide" sur une plate-forme donnée. Des cas comme permettre à un entier signé de déborder ou d'accéder à la même mémoire via des variables de deux types différents.
Les versions récentes de gcc (et clang) ont commencé à traiter ces cas comme des opportunités d'optimisation ne se souciant pas de savoir si elles modifient le comportement du binaire dans la condition de «comportement indéfini». C'est très mauvais si votre base de code a été écrite par des personnes qui traitaient C comme un "assembleur portable". Au fil du temps, les optimiseurs ont commencé à regarder des morceaux de code de plus en plus gros lors de ces optimisations, augmentant les chances que le binaire finisse par faire autre chose que "ce qu'un binaire construit par un compilateur stupide" ferait.
Il existe des commutateurs de compilateur pour restaurer le comportement "traditionnel" (-fwrapv et -fno-strict-aliasing pour les deux que j'ai mentionnés ci-dessus), mais vous devez d'abord les connaître.
Alors qu'en principe un bogue du compilateur pourrait transformer un code conforme en une faille de sécurité, je considérerais le risque comme négligeable dans le grand schéma des choses.
la source
people who treated C like a "portable assembler"
n'est-ce pas ce que C est?Il y a des risques dans les deux modes d'action.
Les compilateurs plus anciens ont l'avantage de la maturité, et tout ce qui y était cassé a probablement (mais il n'y a aucune garantie) été contourné avec succès.
Dans ce cas, un nouveau compilateur est une source potentielle de nouveaux bogues.
D'autre part, les nouveaux compilateurs sont livrés avec des outils supplémentaires :
L'instrumentation de votre binaire avec les désinfectants (Address Sanitizer, Memory Sanitizer ou Undefined Behavior Sanitizer) puis le fuzzing (en utilisant American Fuzzy Lop par exemple) a découvert des vulnérabilités dans un certain nombre de logiciels de haut niveau, voir par exemple cet article de LWN.net .
Ces nouveaux outils, et tous les futurs outils, vous sont inaccessibles à moins que vous ne mettiez à niveau votre compilateur.
En restant sur un compilateur sous-alimenté, vous mettez la tête dans le sable et croisez les doigts qu'aucune vulnérabilité n'est trouvée. Si votre produit est une cible de grande valeur, je vous exhorte à reconsidérer.
Remarque: même si vous ne mettez PAS à niveau le compilateur de production, vous voudrez peut-être utiliser un nouveau compilateur pour vérifier la vulnérabilité de toute façon; sachez que, comme ce sont des compilateurs différents, les garanties sont cependant amoindries.
la source
Votre code compilé contient des bogues qui pourraient être exploités. Les bogues proviennent de trois sources: des bogues dans votre code source, des bogues dans le compilateur et les bibliothèques, et un comportement indéfini dans votre code source que le compilateur transforme en bogue. (Un comportement non défini est un bogue, mais pas encore un bogue dans le code compilé. Par exemple, i = i ++; en C ou C ++ est un bogue, mais dans votre code compilé, il peut augmenter i de 1 et être OK, ou définir i à des ordures et être un bogue).
Le taux de bogues dans votre code compilé est probablement faible en raison des tests et de la correction de bogues dus aux rapports de bogues des clients. Il peut donc y avoir eu un grand nombre de bogues au départ, mais cela a disparu.
Si vous mettez à niveau vers un compilateur plus récent, vous risquez de perdre les bogues introduits par les bogues du compilateur. Mais ces bogues seraient tous des bogues que, à votre connaissance, personne n'a trouvé et personne n'a exploité. Mais le nouveau compilateur peut avoir des bogues en lui-même, et surtout les nouveaux compilateurs ont une tendance plus forte à transformer un comportement non défini en bogues dans le code compilé.
Vous aurez donc beaucoup de nouveaux bogues dans votre code compilé; tous les bogues que les pirates pourraient trouver et exploiter. Et à moins que vous ne fassiez beaucoup de tests et que vous ne laissiez votre code aux clients pour trouver des bogues pendant longtemps, il sera moins sécurisé.
la source
getaddrinfo()
: access.redhat.com/articles/2161461 . Cet exemple n'est pas en fait une faille de sécurité du compilateur, mais sur plus de 10 ans, il y aura forcément des failles corrigées connues.Si ce n'est pas cassé, ne le répare pas
Votre patron a raison de dire cela, cependant, le facteur le plus important est la protection des entrées, des sorties et des débordements de tampon. L'absence de ceux-ci est invariablement le maillon le plus faible de la chaîne de ce point de vue quel que soit le compilateur utilisé.
Cependant, si la base de code est ancienne et que des travaux ont été mis en place pour atténuer les faiblesses du K&R C utilisé, telles que le manque de sécurité de type, les fgets non sécurisés, etc., posez la question "La mise à niveau du compilateur vers un C99 plus moderne / Les normes C11 cassent tout? "
À condition qu'il existe un chemin clair pour migrer vers les nouvelles normes C, ce qui pourrait induire des effets secondaires, il serait peut-être préférable d'essayer un fork de l'ancienne base de code, de l'évaluer et de mettre en place des vérifications de type supplémentaires, des vérifications de cohérence et de déterminer si la mise à niveau vers le nouveau compilateur a un effet sur les ensembles de données d'entrée / sortie.
Ensuite, vous pouvez le montrer à votre patron, " Voici la base de code mise à jour, refactorisée, plus conforme aux normes C99 / C11 acceptées par l'industrie ... ".
C'est le pari sur lequel il faudrait peser, très soigneusement , la résistance au changement pourrait apparaître dans cet environnement et refuser de toucher aux nouveautés.
ÉDITER
Je me suis assis pendant quelques minutes, j'ai réalisé cela, le code généré par K&R pourrait fonctionner sur une plate-forme 16 bits, il y a de fortes chances que la mise à niveau vers un compilateur plus moderne puisse en fait casser la base de code, je pense en termes d'architecture, du code 32 bits serait généré , cela pourrait avoir des effets secondaires amusants sur les structures utilisées pour les ensembles de données d'entrée / sortie, c'est un autre facteur énorme à peser avec soin.
De plus, comme OP a mentionné l'utilisation de Visual Studio 2008 pour créer la base de code, l'utilisation de gcc pourrait induire l'introduction dans l'environnement de MinGW ou de Cygwin, ce qui pourrait avoir un impact sur l'environnement, à moins que la cible soit pour Linux, alors ce serait vaut le détour, peut devoir inclure des commutateurs supplémentaires dans le compilateur pour minimiser le bruit sur l'ancienne base de code K&R, l'autre chose importante est d'effectuer de nombreux tests pour s'assurer qu'aucune fonctionnalité n'est interrompue, cela peut s'avérer un exercice douloureux.
la source
Bien sûr, cela peut, si l'ancien compilateur contient des bogues connus qui, selon vous, affecteront votre programme.
La question est, n'est-ce pas? Pour être sûr, vous devrez lire l'intégralité du journal des modifications de votre version à la date actuelle et vérifier chaque bogue corrigé au fil des ans.
Si vous ne trouvez aucune preuve de bogues du compilateur qui pourraient affecter votre programme, mettre à jour GCC juste pour le plaisir semble un peu paranoïaque. Vous devez garder à l'esprit que les versions plus récentes peuvent contenir de nouveaux bogues, qui ne sont pas encore découverts. De nombreux changements ont été apportés récemment avec le support de GCC 5 et C11.
Cela étant dit, le code écrit dans les années 80 est probablement déjà rempli à ras bord de failles de sécurité et de dépendance à un comportement mal défini, quel que soit le compilateur. Nous parlons ici de C pré-standard.
la source
Il existe un risque de sécurité où un développeur malveillant peut se faufiler en dérobant un bogue du compilateur. En fonction de la quantité de bogues connus dans le compilateur utilisé, la porte dérobée peut paraître plus ou moins discrète (dans tous les cas, le fait est que le code est correct, même s'il est alambiqué, au niveau de la source. Revues et tests du code source à l'aide de un compilateur non bogué ne trouvera pas la porte dérobée, car la porte dérobée n'existe pas dans ces conditions). Pour des points de déni supplémentaire, le développeur malveillant peut également rechercher lui-même des bogues de compilateur auparavant inconnus. Encore une fois, la qualité du camouflage dépendra du choix des bogues du compilateur trouvés.
Cette attaque est illustrée sur le programme sudo dans cet article . bcrypt a écrit un excellent suivi pour les minificateurs Javascript .
En dehors de cette préoccupation, l'évolution des compilateurs C a été d'exploiter un comportement non défini plus et plus et plus agressive, si vieux code C qui a été écrit de bonne foi serait effectivement plus sûr compilé avec un compilateur C à partir du moment ou compilé à -O0 (mais de nouvelles optimisations exploitant UB révolutionnaires sont introduites dans les nouvelles versions des compilateurs même à -O0 ).
la source
Les compilateurs plus anciens peuvent ne pas avoir de protection contre les attaques de piratage connues. La protection contre le bris de pile, par exemple, n'a pas été introduite avant GCC 4.1 . Donc oui, le code compilé avec des compilateurs plus anciens peut être vulnérable d'une manière contre laquelle les nouveaux compilateurs se protègent.
la source
Un autre aspect à craindre est le développement d'un nouveau code .
Les compilateurs plus anciens peuvent avoir un comportement différent pour certaines fonctionnalités du langage que ce qui est normalisé et attendu par le programmeur. Cette discordance peut ralentir le développement et introduire des bogues subtils qui peuvent être exploités.
Les compilateurs plus anciens offrent moins de fonctionnalités (y compris les fonctionnalités de langage!) Et n'optimisent pas aussi. Les programmeurs contourneront ces lacunes - par exemple en réimplémentant des fonctionnalités manquantes, ou en écrivant du code intelligent qui est obscur mais s'exécute plus rapidement - créant de nouvelles opportunités pour la création de bogues subtils.
la source
Nan
La raison est simple, l'ancien compilateur peut avoir d'anciens bogues et exploits, mais le nouveau compilateur aura de nouveaux bogues et exploits.
Vous ne "corrigez" aucun bogue en passant à un nouveau compilateur. Votre changement d'anciens bogues et exploits pour de nouveaux bogues et exploits.
la source
Eh bien, il y a une probabilité plus élevée que les bogues de l'ancien compilateur soient bien connus et documentés par opposition à l'utilisation d'un nouveau compilateur, donc des actions peuvent être prises pour éviter ces bogues en codant autour d'eux. Donc, d'une manière qui n'est pas suffisante comme argument pour la mise à niveau. Nous avons les mêmes discussions là où je travaille, nous utilisons GCC 4.6.1 sur une base de code pour les logiciels embarqués et il y a une grande réticence (parmi la direction) à mettre à niveau vers le dernier compilateur par crainte de nouveaux bogues non documentés.
la source
Votre question se divise en deux parties:
Peut-être pouvez-vous répondre aux deux en trouvant une faille exploitable dans votre base de code existante et en montrant qu'un compilateur plus récent l'aurait détectée. Bien sûr, votre direction peut dire «vous avez trouvé cela avec l'ancien compilateur», mais vous pouvez souligner que cela a coûté des efforts considérables. Ou vous l'exécutez via le nouveau compilateur pour trouver la vulnérabilité, puis l'exploitez, si vous êtes en mesure / autorisé à compiler le code avec le nouveau compilateur. Vous pouvez avoir besoin de l'aide d'un pirate informatique amical, mais cela dépend de leur confiance et de la capacité / l'autorisation de leur montrer le code (et d'utiliser le nouveau compilateur).
Mais si votre système n'est pas exposé aux pirates, vous devriez peut-être être plus intéressé par la question de savoir si une mise à niveau du compilateur augmenterait votre efficacité: l'analyse de code MSVS 2013 trouve assez souvent des bogues potentiels beaucoup plus tôt que MSVS 2010, et prend plus ou moins en charge C99 / C11 - je ne sais pas si c'est officiellement le cas, mais les déclarations peuvent suivre des instructions et vous pouvez déclarer des variables dans
for
-loops.la source