Wir haben einige Build-Systeme in der Produktion, die niemanden interessieren, und auf diesen Maschinen werden alte Versionen von GCC wie GCC 3 oder GCC 2 ausgeführt.
Und ich kann das Management nicht davon überzeugen, es auf ein neueres zu aktualisieren: Sie sagen: "Wenn es nicht kaputt ist, reparieren Sie es nicht."
Da wir eine sehr alte Codebasis (geschrieben in den 80ern) beibehalten, wird dieser C89-Code auf diesen Compilern problemlos kompiliert.
Aber ich bin mir nicht sicher, ob es eine gute Idee ist, diese alten Sachen zu verwenden.
Meine Frage ist:
Kann die Verwendung eines alten C-Compilers die Sicherheit des kompilierten Programms beeinträchtigen?
AKTUALISIEREN:
Der gleiche Code wird von Visual Studio 2008 für Windows-Ziele erstellt, und MSVC unterstützt C99 oder C11 noch nicht (ich weiß nicht, ob neuere MSVC dies tun), und ich kann ihn mit dem neuesten GCC auf meiner Linux-Box erstellen. Wenn wir also nur ein neueres GCC einbinden würden, würde es wahrscheinlich genauso gut funktionieren wie zuvor.
-O3 -Wall -Wextra -fsanitize=undefined
sollte helfen , alle Probleme zu beheben, die mit modernem gcc und clang identifiziert wurden .Antworten:
Eigentlich würde ich das Gegenteil argumentieren.
Es gibt eine Reihe von Fällen, in denen das Verhalten nicht durch den C-Standard definiert ist, aber es offensichtlich ist, was mit einem "dummen Compiler" auf einer bestimmten Plattform passieren würde. Fälle wie das Überlaufenlassen einer vorzeichenbehafteten Ganzzahl oder der Zugriff auf denselben Speicher über Variablen zweier verschiedener Typen.
Neuere Versionen von gcc (und clang) haben begonnen, diese Fälle als Optimierungsmöglichkeiten zu behandeln, die sich nicht darum kümmern, wenn sie das Verhalten der Binärdatei im Zustand "undefiniertes Verhalten" ändern. Dies ist sehr schlecht, wenn Ihre Codebasis von Personen geschrieben wurde, die C wie einen "tragbaren Assembler" behandelten. Im Laufe der Zeit haben die Optimierer begonnen, bei diesen Optimierungen immer größere Codestücke zu untersuchen, was die Wahrscheinlichkeit erhöht, dass die Binärdatei etwas anderes tut als "was eine von einem dummen Compiler erstellte Binärdatei" tun würde.
Es gibt Compiler-Schalter, um das "traditionelle" Verhalten wiederherzustellen (-fwrapv und -fno-strict-aliasing für die beiden oben genannten), aber zuerst müssen Sie sie kennen.
Während im Prinzip ein Compiler-Fehler konformen Code in eine Sicherheitslücke verwandeln könnte, würde ich das Risiko dafür im großen Schema der Dinge als vernachlässigbar betrachten.
quelle
people who treated C like a "portable assembler"
ist es nicht was C ist?In beiden Vorgehensweisen bestehen Risiken.
Ältere Compiler haben den Vorteil der Reife, und was auch immer in ihnen kaputt war, wurde wahrscheinlich (aber es gibt keine Garantie) erfolgreich umgangen.
In diesem Fall ist ein neuer Compiler eine potenzielle Quelle für neue Fehler.
Auf der anderen Seite verfügen neuere Compiler über zusätzliche Tools :
Das Instrumentieren Ihrer Binärdatei mit den Desinfektionsprogrammen (Address Sanitizer, Memory Sanitizer oder Undefined Behavior Sanitizer) und das anschließende Fuzzing ( z. B. mit American Fuzzy Lop ) hat Schwachstellen in einer Reihe hochkarätiger Software aufgedeckt, siehe beispielsweise diesen LWN.net-Artikel .
Auf diese neuen Tools und alle zukünftigen Tools kann nur zugegriffen werden, wenn Sie Ihren Compiler aktualisieren.
Wenn Sie auf einem Compiler mit geringer Leistung bleiben, stecken Sie Ihren Kopf in den Sand und drücken die Daumen, damit keine Sicherheitslücke gefunden wird. Wenn Ihr Produkt ein hochwertiges Ziel ist, fordere ich Sie auf, es sich noch einmal zu überlegen.
Hinweis: Selbst wenn Sie den Produktions-Compiler NICHT aktualisieren, möchten Sie möglicherweise trotzdem einen neuen Compiler verwenden, um nach Sicherheitslücken zu suchen. Beachten Sie jedoch, dass die Garantien verringert werden, da es sich um unterschiedliche Compiler handelt.
quelle
Ihr kompilierter Code enthält Fehler, die ausgenutzt werden könnten. Die Fehler stammen aus drei Quellen: Fehler in Ihrem Quellcode, Fehler im Compiler und in den Bibliotheken und undefiniertes Verhalten in Ihrem Quellcode, das der Compiler in einen Fehler verwandelt. (Undefiniertes Verhalten ist ein Fehler, aber noch kein Fehler im kompilierten Code. Als Beispiel ist i = i ++; in C oder C ++ ist es ein Fehler, aber in Ihrem kompilierten Code kann es i um 1 erhöhen und in Ordnung sein oder gesetzt werden Ich zu etwas Müll und ein Käfer sein).
Die Fehlerrate in Ihrem kompilierten Code ist vermutlich aufgrund von Tests und der Behebung von Fehlern aufgrund von Kundenfehlerberichten niedrig. Es mag also anfangs eine große Anzahl von Fehlern gegeben haben, aber das ist gesunken.
Wenn Sie auf einen neueren Compiler aktualisieren, können Sie Fehler verlieren, die durch Compiler-Fehler verursacht wurden. Aber diese Fehler wären alle Fehler, die Ihrer Kenntnis nach niemand gefunden und ausgenutzt hat. Der neue Compiler kann jedoch selbst Fehler aufweisen, und vor allem neuere Compiler neigen stärker dazu, undefiniertes Verhalten in Fehler im kompilierten Code umzuwandeln.
Sie werden also eine Menge neuer Fehler in Ihrem kompilierten Code haben. Alle Fehler, die Hacker finden und ausnutzen konnten. Und wenn Sie nicht viele Tests durchführen und Ihren Code den Kunden überlassen, um Fehler für lange Zeit zu finden, ist er weniger sicher.
quelle
getaddrinfo()
: access.redhat.com/articles/2161461 . Dieses Beispiel ist eigentlich keine Sicherheitslücke des Compilers, aber über 10 Jahre hinweg müssen einige bekannte Fehler behoben sein.Wenn es nicht kaputt ist, reparieren Sie es nicht
Ihr Chef klingt richtig, wenn er dies sagt. Der wichtigere Faktor ist jedoch die Sicherung von Ein- und Ausgängen sowie Pufferüberläufen. Das Fehlen dieser ist aus dieser Sicht immer das schwächste Glied in der Kette, unabhängig vom verwendeten Compiler.
Wenn die Codebasis jedoch uralt ist und Anstrengungen unternommen wurden, um die Schwächen des verwendeten K & R C zu verringern, wie z. B. mangelnde Typensicherheit, unsichere Geräte usw., wird die Frage abgewogen, ob der Compiler auf ein moderneres C99 aktualisiert werden soll / C11-Standards brechen alles? "
Vorausgesetzt, dass es einen klaren Weg für die Migration zu den neueren C-Standards gibt, der Nebenwirkungen hervorrufen kann, ist es möglicherweise am besten, eine Abzweigung der alten Codebasis zu versuchen, diese zu bewerten und zusätzliche Typprüfungen und Sanitätsprüfungen durchzuführen und festzustellen, ob ein Upgrade auf durchgeführt wird Der neuere Compiler hat Auswirkungen auf Eingabe- / Ausgabedatensätze.
Dann können Sie es Ihrem Chef zeigen: " Hier ist die aktualisierte Codebasis, überarbeitet, mehr im Einklang mit den branchenüblichen C99 / C11-Standards ... ".
Das ist das Glücksspiel , das auf abgewogen werden müssten, sehr sorgfältig , resistence Änderungen in dieser Umgebung kann es zeigen und sich weigern , kann die neueren Sachen zu berühren.
BEARBEITEN
Ich habe mich nur ein paar Minuten zurückgelehnt und festgestellt, dass K & R generierter Code auf einer 16-Bit-Plattform ausgeführt werden kann. Die Wahrscheinlichkeit besteht, dass ein Upgrade auf einen moderneren Compiler tatsächlich die Codebasis sprengt. Ich denke in Bezug auf die Architektur, dass 32-Bit-Code generiert wird Dies könnte lustige Nebenwirkungen auf die Strukturen haben, die für Eingabe- / Ausgabedatensätze verwendet werden. Dies ist ein weiterer wichtiger Faktor, der sorgfältig abgewogen werden muss.
Da OP die Verwendung von Visual Studio 2008 zum Erstellen der Codebasis erwähnt hat, kann die Verwendung von gcc dazu führen, dass entweder MinGW oder Cygwin in die Umgebung gebracht werden, was sich auf die Umgebung auswirken kann, es sei denn, das Ziel ist Linux einen Versuch wert, muss möglicherweise zusätzliche Schalter zum Compiler enthalten, um das Rauschen auf der alten K & R-Codebasis zu minimieren. Die andere wichtige Sache ist, viele Tests durchzuführen, um sicherzustellen, dass keine Funktionalität beeinträchtigt wird. Dies kann sich als schmerzhafte Übung herausstellen.
quelle
Natürlich kann es sein, wenn der alte Compiler bekannte Fehler enthält, von denen Sie wissen, dass sie Ihr Programm beeinflussen würden.
Die Frage ist, oder? Um sicher zu sein, müssten Sie das gesamte Änderungsprotokoll von Ihrer Version bis zum aktuellen Datum lesen und jeden einzelnen Fehler überprüfen, der im Laufe der Jahre behoben wurde.
Wenn Sie keine Hinweise auf Compiler-Fehler finden, die sich auf Ihr Programm auswirken könnten, erscheint die Aktualisierung von GCC nur aus diesem Grund etwas paranoid. Sie müssen bedenken, dass neuere Versionen möglicherweise neue Fehler enthalten, die noch nicht entdeckt wurden. In letzter Zeit wurden viele Änderungen mit Unterstützung von GCC 5 und C11 vorgenommen.
Abgesehen davon ist der in den 80er Jahren geschriebene Code höchstwahrscheinlich bereits randvoll mit Sicherheitslücken und dem Vertrauen in schlecht definiertes Verhalten, unabhängig vom Compiler. Wir sprechen hier von Pre-Standard C.
quelle
Es besteht ein Sicherheitsrisiko, bei dem ein böswilliger Entwickler eine Hintertür durch einen Compiler-Fehler schleichen kann. Abhängig von der Anzahl der bekannten Fehler im verwendeten Compiler kann die Hintertür mehr oder weniger unauffällig aussehen (in jedem Fall ist der Punkt, dass der Code auf Quellenebene korrekt ist, auch wenn er verschlungen ist. Quellcode überprüft und testet mit Ein nicht fehlerhafter Compiler findet die Hintertür nicht, da die Hintertür unter diesen Bedingungen nicht vorhanden ist. Für zusätzliche Verleugnungspunkte kann der böswillige Entwickler auch selbst nach bisher unbekannten Compiler-Fehlern suchen. Auch hier hängt die Qualität der Tarnung von der Auswahl der gefundenen Compiler-Fehler ab.
Dieser Angriff wird im Programm sudo in diesem Artikel dargestellt . bcrypt hat ein großartiges Follow-up für Javascript-Minifier geschrieben .
Abgesehen von dieser Sorge hat sich die Entwicklung von C - Compiler wurden nicht definiertes Verhalten zu nutzen mehr und mehr und mehr aggressiv, so alt C - Code, der in gutem Glauben geschrieben wurde eigentlich mehr wäre mit einem C - Compiler aus der Zeit zusammengestellt sicher oder kompiliert bei -O0 (aber einige neue programmbrechende UB-Exploiting-Optimierungen werden in neuen Versionen von Compilern sogar bei -O0 eingeführt ).
quelle
Ältere Compiler sind möglicherweise nicht vor bekannten Hacking-Angriffen geschützt. Beispielsweise wurde der Stapelschlagschutz erst mit GCC 4.1 eingeführt . Also ja, mit älteren Compilern kompilierter Code kann auf eine Weise anfällig sein, vor der neuere Compiler schützen.
quelle
Ein weiterer Aspekt, über den Sie sich Sorgen machen müssen, ist die Entwicklung neuen Codes .
Ältere Compiler verhalten sich bei einigen Sprachfunktionen möglicherweise anders als vom Programmierer standardisiert und erwartet. Diese Nichtübereinstimmung kann die Entwicklung verlangsamen und subtile Fehler verursachen, die ausgenutzt werden können.
Ältere Compiler bieten weniger Funktionen (einschließlich Sprachfunktionen!) Und optimieren auch nicht. Programmierer werden sich um diese Mängel herum hacken - z. B. indem sie fehlende Funktionen neu implementieren oder cleveren Code schreiben, der dunkel ist, aber schneller ausgeführt wird - und neue Möglichkeiten für die Erstellung subtiler Fehler schaffen.
quelle
Nee
Der Grund ist einfach: Der alte Compiler weist möglicherweise alte Fehler und Exploits auf, der neue Compiler weist jedoch neue Fehler und Exploits auf.
Sie "beheben" keine Fehler, indem Sie auf einen neuen Compiler aktualisieren. Sie tauschen alte Fehler und Exploits gegen neue Fehler und Exploits aus.
quelle
Nun, es besteht eine höhere Wahrscheinlichkeit, dass Fehler im alten Compiler bekannt und dokumentiert sind, anstatt einen neuen Compiler zu verwenden, sodass Maßnahmen ergriffen werden können, um diese Fehler durch Codierung zu vermeiden. Auf eine Weise, die als Argument für ein Upgrade nicht ausreicht. Wir haben die gleichen Diskussionen, in denen ich arbeite, wir verwenden GCC 4.6.1 auf einer Codebasis für eingebettete Software und es gibt eine große Zurückhaltung (unter den Managern), auf den neuesten Compiler zu aktualisieren, weil wir Angst vor neuen, nicht dokumentierten Fehlern haben.
quelle
Ihre Frage besteht aus zwei Teilen:
Vielleicht können Sie beides beantworten, indem Sie einen ausnutzbaren Fehler in Ihrer vorhandenen Codebasis finden und zeigen, dass ein neuerer Compiler ihn erkannt hätte. Natürlich kann Ihr Management sagen, dass Sie das mit dem alten Compiler gefunden haben, aber Sie können darauf hinweisen, dass es einen erheblichen Aufwand gekostet hat. Oder Sie führen es durch den neuen Compiler, um die Sicherheitsanfälligkeit zu finden, und nutzen es dann aus, wenn Sie den Code mit dem neuen Compiler kompilieren können / dürfen. Sie möchten vielleicht Hilfe von einem freundlichen Hacker, aber das hängt davon ab, ob Sie ihnen vertrauen und in der Lage / erlaubt sind, ihnen den Code anzuzeigen (und den neuen Compiler zu verwenden).
Wenn Ihr System jedoch keinen Hackern ausgesetzt ist, sollten Sie sich vielleicht mehr dafür interessieren, ob ein Compiler-Upgrade Ihre Effektivität erhöht: MSVS 2013 Code Analysis findet potenzielle Fehler häufig viel früher als MSVS 2010 und unterstützt mehr oder weniger C99 / C11 -
for
Ich bin mir nicht sicher, ob dies offiziell der Fall ist, aber Deklarationen können Anweisungen folgen und Sie können Variablen in -loops deklarieren.quelle