So kompilieren Sie den C-Compiler von Grund auf neu und anschließend Unix / Linux von Grund auf neu


64

Nehmen wir an, ich arbeite für eine große Dienstleistungsorganisation außerhalb der USA / Großbritanniens. Wir verwenden häufig UNIX- und Linux-Server.

Beim Lesen dieses Artikels wird erwähnt, dass es einfach wäre, eine Backdoor in einen C-Compiler einzufügen. Dann würde jeder mit diesem Compiler kompilierte Code auch eine Backdoor enthalten. Angesichts der jüngsten Lücken in Bezug auf das Mandat der NSA / GCHQ, Hintertüren / Schwachstellen in allen Verschlüsselungsmethoden, Hardware und Software zu beseitigen, ist der Compiler jetzt ein kritischer Fehlerpunkt. Möglicherweise können alle Standard-UNIX / Linix-Distributionen kompromittiert werden. Wir können es uns nicht leisten, dass unsere Systeme, Daten und Kundendaten von betrügerischen Regierungen kompromittiert werden.

Angesichts dieser Informationen möchte ich einen vertrauenswürdigen Compiler von Grund auf neu erstellen, dann habe ich eine sichere Basis, auf der ich aufbauen kann, damit ich das Betriebssystem und die Anwendungen mithilfe dieses Compilers aus dem Quellcode erstellen kann.

Frage

Was ist der richtige (und sichere) Weg, um einen Compiler aus dem Quellcode zu kompilieren (ein scheinbar Hühnerei-Szenario) und dann eine vertrauenswürdige Unix / Linux-Distribution von Grund auf neu zu kompilieren?

Sie können davon ausgehen, dass ich oder andere Benutzer in der Lage sind, den Quellcode auf Sicherheitslücken hin zu lesen und zu verstehen. Daher wird der Quellcode vor dem Kompilieren zunächst überprüft. Was ich wirklich brauche, ist eine Arbeitsanleitung, um diesen Compiler von Grund auf sicher zu erstellen und kann verwendet werden, um den Kernel, andere Teile des Betriebssystems und Anwendungen zu kompilieren.

Der Sicherheitsstapel muss auf der Basisebene beginnen, wenn Sie dem Betriebssystem oder den Anwendungen, die auf diesem Stapel ausgeführt werden, vertrauen möchten. Ja, ich verstehe, dass es möglicherweise Hardware-Hintertüren gibt, die beim Erstellen einen Mikrocode in den Compiler einfügen. Momentan können wir nicht viel dagegen tun, es sei denn, wir verwenden Chips, die nicht in den USA entwickelt wurden. Lassen Sie uns diese Ebene zunächst sortieren und davon ausgehen, dass ich sie möglicherweise auf einem alten Computer erstellen könnte, bevor Backdoors eingefügt wurden.

Wie Bruce Schneier sagt: "Den Ingenieuren sage ich Folgendes: Wir haben das Internet aufgebaut, und einige von uns haben dazu beigetragen, es zu untergraben. Jetzt müssen diejenigen von uns, die die Freiheit lieben, es reparieren."

Zusätzliche Links:


7
Verdammt, das ist eine sehr interessante Frage, und ich möchte sie nicht migrieren, aber ich glaube nicht, dass sie hier zum Thema gehört. Es ist besser für stackoverflow.com geeignet, da Ihre grundlegende Frage darin besteht, wie ein Compiler von Grund auf neu kompiliert werden kann, der ziemlich betriebssystemunabhängig und sehr programmierbezogen ist. Wenn Sie hier nach einer Weile keine Antwort erhalten, können Sie den Link "flag" unter den Tags Ihrer Frage verwenden und einen Moderator bitten, dies auf SO zu verschieben.
Terdon

2
@terdon Es ist möglicherweise besser für Programmierer geeignet.SE, da es sich eher um allgemeine Programmierprobleme als um ein bestimmtes Entwicklungsproblem handelt. In der Tat könnte es ein Duplikat sein .
ein CVn

2
GCC ist Open Source, wie würde eine Backdoor eingefügt werden?
Michael Pankov

2
Beachten Sie, dass für den stabilen Thompson-Exploit Code erforderlich ist, der erkennt, wann das Anmeldeprogramm oder der Compiler kompiliert wird. Wenn Sie die Quelle manuell in ein Formular umwandeln können, das für den Compiler nicht als eines dieser Programme erkennbar ist, wird die Hintertür nicht weitergegeben.
Russell Borogove

2
@Constantius - Lesen Sie den Thompson-Artikel in der ersten Zeile. Wer kompiliert den Compiler?
Russell Borogove

Antworten:


30

AFAIK bietet die einzige Möglichkeit, die vollständige Sicherheit zu gewährleisten, darin, einen Compiler in Assembler-Sprache zu schreiben (oder die Festplatte direkt selbst zu ändern ). Nur dann können Sie sicherstellen, dass Ihr Compiler keine Hintertür einfügt - dies funktioniert, da Sie den Compiler tatsächlich vollständig entfernen.

Von dort aus können Sie Ihren von Grund auf neu erstellten Compiler verwenden, um z. B. die GNU-Toolchain zu booten. Dann können Sie Ihre benutzerdefinierte Toolchain verwenden, um ein Linux From Scratch- System zu kompilieren .

Beachten Sie, dass Sie zur Vereinfachung einen zweiten Intermediary Compiler in C (oder einer anderen Sprache) haben können. Sie würden also Compiler A in Assembly schreiben und diesen Compiler dann in C / C ++ / Python / Brainfuck / whatever umschreiben, um Compiler B zu erhalten, den Sie mit Compiler A kompilieren würden. Dann würden Sie Compiler B verwenden, um gcc und friends zu kompilieren.


13
Dies schützt jedoch nur vor einem böswilligen Compiler. Sie müssen weiterhin dem System vertrauen, auf dem der Compiler ausgeführt wird. Keine Software ist isoliert vorhanden.
ein CVn

3
Alles Autonome ist von Natur aus gefährlich. Sie schlagen effektiv einen Toolchain-Compiler vor (wenn auch einen seltsamen), was bedeutet, dass er wahrscheinlich genau so modifiziert werden kann, wie Sie es vermeiden möchten. Noch besser ist, dass es während des Transits über MitM geändert werden kann.
Strugee

1
Ihr müsst euch darüber im Klaren sein, dass diese Antwort von einem 15-Jährigen stammt. Mach weiter so!
Mtahmed

3
Man sollte nicht vergessen, auch einen Code-Editor von Grund auf neu zu schreiben - wer weiß, ob Ihr vorkompilierter <code> vim </ code> oder der <code> vim </ code>, den Sie mit Ihrem guten Compiler kompilieren, aus einer Quelle, die Sie nur mit infiziertem Code überprüft haben <code> vim </ code> ist vertrauenswürdig?
Hagen von Eitzen

1
Vergessen Sie niemals, dass Sie jede einzelne Codezeile, die Sie kompilieren, lesen und überprüfen , wenn Sie nicht persönlich diesen ersten Maschinencode (nicht den eigentlichen Maschinencode der Baugruppe) geschrieben haben und ein Experte für das Erkennen von Sicherheitslücken sind… oder zumindest wissen die Person, die das persönlich getan hat und die ihm das anvertraut ... nichts davon wird überhaupt helfen. Das ist der Grund, warum der Versuch, dies zu starten, den ganzen Punkt ruiniert. Welches ist: Hohe Vertrauenswürdigkeit.
Evi1M4chine

22

Ein möglicher Weg, obwohl es in der Praxis sehr lange dauern würde, wäre, zu den Wurzeln zurückzukehren. Die Entwicklung von GNU begann 1984 und die ursprüngliche Version von Minix (die während der frühen Linux-Entwicklung für Bootstrapping-Zwecke verwendet wurde) wurde 1987 veröffentlicht.

Die gesamte Antwort basiert auf der Annahme, dass "[Sie] oder andere die Fähigkeit haben, Quellcode auf Sicherheitslücken hin zu lesen und zu verstehen, sodass der Quellcode vor dem Kompilieren zuerst überprüft wird" und dass Sie dem Ergebnis einer solchen Analyse vertrauen können . Ohne das ist diese Antwort wahrscheinlich schlimmer als wertlos, da Sie viel Zeit für absolut keinen Nutzen aufwenden werden.

Wenn Sie eine Kopie des ursprünglichen Minix-Buches mit Quellcode finden, können Sie sie aus dem Buch eingeben. Kompilieren Sie es und verwenden Sie dann einen anderen Dekompiler auf einem anderen System, um sicherzustellen, dass der Compiler die erwartete Maschinensprachen-Binärausgabe generiert. (Der Code besteht nur aus 12.000 Zeilen, vermutlich C, was zwar zeitaufwändig ist, aber immer noch in Ordnung ist, wenn Sie ein solches Projekt ernst meinen.) Sie könnten sogar Ihren eigenen Disassembler schreiben; das sollte nicht sehr schwierig sein.

Besorgen Sie sich die ältesten Versionen der GNU-Dienstprogramme, die Sie möglicherweise in die Finger bekommen können (da diese vermutlich weniger Code enthalten und weniger von externen Bibliotheken abhängig sind), lesen Sie den Code durch und erstellen Sie ihn für Minix (dies kann jedoch einige Arbeit erfordern; was Sie tun) Es ist unbedingt zu vermeiden, Anpassungen am Quellcode vorzunehmen, da dies das Hinzufügen von Patches zu einem späteren Zeitpunkt sehr fehleranfällig macht und einen ähnlichen Disassemble-Verifizierungszyklus für die GNU-Tools durchläuft. An diesem Punkt vertrauen Sie dem Betriebssystem und der Toolchain, sodass Sie nur den Quellcode im Patchset durchgehen müssen (alles, was nicht im Patchset enthalten ist, ist bereits vertrauenswürdig), aber die Tools sind im Vergleich zu Ihrer Verwendung immer noch sehr primitiv und grob bis heute. Erwarten Sie zum Beispiel nicht, dass mehr als die grundlegendste Funktionalität der Systemtools funktioniert.Lose XKCD lesen.

Irgendwann werden Sie ein System haben, das eine frühe Version des Linux-Kernels kompilieren und booten kann, ähnlich wie es in den frühen neunziger Jahren der Fall war, als Linux unter Hackern an Bedeutung gewann. Ich würde empfehlen, zu diesem Zeitpunkt auf Linux zu migrieren (die Systembibliotheken und die Toolchain gegen Linux neu zu erstellen, den Linux-Kernel zu erstellen, in Linux zu booten und möglicherweise den Linux-Kernel und die GNU-Toolchain unter Linux neu zu erstellen; der letzte Beweis, dass das System jetzt selbstständig ist). Hosting), aber das liegt weitgehend bei Ihnen. Überprüfen Sie weiterhin die Patches, patchen Sie den Kernel, die Bibliotheken und die grundlegenden GNU-Tools und erstellen Sie sie neu, bis Sie zu modernen Versionen gelangen.

Dann haben Sie ein vertrauenswürdiges Basis-Betriebssystem und einen Compiler, mit denen Sie moderne Software erstellen können. Bis dahin können Sie z. B. den Linux From Scratch- Anleitungen folgen , um ein System zu erstellen, das nützliche Aufgaben ausführen kann .

Das "Compiler" -System kann zu keinem Zeitpunkt in irgendeiner Weise mit einem Netzwerk verbunden werden (auch nicht als VM auf einem vernetzten Host). Sie würden das Risiko eingehen, durch netzwerkfähige Komponenten einschließlich des Kernels zu gelangen. Wenn Sie sich Sorgen über einen Thompson-Compiler-Angriff machen , müssen Sie damit rechnen, dass auch jeder VM-Host kompromittiert wird. Verwenden Sie sneakernet, um den Quellcode von dem physischen Host, auf dem Sie die Dinge kompilieren, und die Binärdateien abzurufen. Erwarten Sie Probleme beim Ein- und Ausschalten von Dateien auf dem System, bevor Sie den Punkt erreichen, an dem die Unterstützung für USB-Massenspeicher implementiert wurde. Wenn Sie wirklich paranoid, Code Druckquelle Listings und geben Sie sie mit der Hand in (und hoffen , dass der Druckertreiber und Drucker nicht über einen ähnlichen Code in ihnen) oder lesen Sie den Code auf einem Computermonitor und tippen Sie ihn in einen anderen Computer ein, der sich physisch neben dem Computer befindet, aber nicht mit ihm verbunden ist.

Ja, das wird viel Zeit in Anspruch nehmen . Der Vorteil dieses Ansatzes besteht jedoch darin, dass jeder Schritt inkrementell ist, was bedeutet, dass es für etwas Bösartiges viel schwieriger ist, durchzukommen, wenn es nicht über einen Zeitraum von vielen Versionen hinweg sehr allmählich eingeführt wird. Dies ist darauf zurückzuführen, dass die Anzahl der Änderungen bei jedem Schritt vergleichsweise gering ist und daher leichter zu überblicken ist. Vergleichen Sie das Patchset mit dem Changelog und stellen Sie sicher, dass Sie genau bestimmen können, welcher Changelog-Eintrag jeder Änderung im Quellcode entspricht. Dies setzt wiederum voraus, dass Sie die Möglichkeit haben (möglicherweise durch jemanden, dem Sie vertrauen), zu überprüfen, dass solche Änderungen nicht in die Codebasis eingeschleust wurden, aber Sie sollten einem vertrauenswürdigen System so nahe kommen wie einem reinen Software-System. Firmware Ansatz kann.


Die Methode zur Überprüfung des Zerlegens ist sehr fehlerhaft, da immer noch die große Annahme besteht, dass der Überprüfungscomputer vollständig vertrauenswürdig ist. Dies wird nicht passieren, es sei denn, Sie haben die Maschine und ihre Software von Grund auf neu erstellt oder Sie kennen die Person, die es persönlich getan hat, und vertrauen ihr. Das ist also immer noch unsicher. Es tut uns leid. …… Auch in diesen Angelegenheiten bedeutet „so nah an…“ immer noch „unsicher“, da nur ein einziger nicht vertrauenswürdiger Punkt erforderlich ist, um den ganzen Punkt zu ruinieren.
Evi1M4chine

9

Wenn Sie einen vertrauenswürdigen Compiler benötigen, können Sie sich akademische Arbeiten wie das compcert- Projekt ansehen . Es ist ein Compiler, der vom INRIA (einem französischen öffentlichen IT-Labor) entwickelt wurde, um "zertifiziert" zu werden, dh um eine semantisch perfekt dem Code entsprechende ausführbare Datei zu erstellen (und natürlich wurde dies mathematisch bewiesen).


1
Jeder braucht einen vertrauenswürdigen Compiler. Wie funktioniert die Mathematik, dass sie einen "vertrauenswürdigen" Compiler erzeugen kann?
David J

@ DavidJ Bootstrapping, am wahrscheinlichsten. Erstellen Sie ein winziges Teil, das Sie vollständig überprüfen und als richtig erweisen können, und verwenden Sie es dann als Grundlage, um komplexere Compiler zu erstellen.
ein Lebenslauf vom

1
"" Was CompCert C von allen anderen Produktionscompilern unterscheidet, ist, dass es mit maschinengestützten mathematischen Beweisen formal verifiziert wurde, um von Problemen mit der Fehlkompilierung ausgenommen zu sein. "" Compcert.inria.fr/compcert-C.html Compilation ist nicht mehr so ​​empirisch wie früher.
Lgeorget

1
@ MichaelKjörling die wahrscheinlich dauert nicht berücksichtigt , dass der Kernel eine Backdoor in die Compiler Quelle durch einen Compiler , wenn zu lesen ist kompromittiert kann
Freak Ratsche

1
Ich habe auch diesen Link gefunden, der auch funktionieren könnte.
David J

2

Während das manuelle Erstellen eines eigenen Compilers als Ausgangspunkt am sichersten ist, besteht eine andere Möglichkeit darin, ein System von einer 5 (oder 10) Jahre alten Installations-CD zu installieren, von der Sie überzeugt sind, dass sie erstellt wurde, bevor diese Exploits existierten. Verwenden Sie dies dann als Grundlage, um die neue geprüfte Quelle zu kompilieren.


5
Der Angriff ist seit 1984 öffentlich bekannt. Vermutlich war Thompson nicht der erste, der über die Möglichkeit nachdachte. So weit zurückzugehen bedeutet, dass die meisten Dinge, die wir heute für selbstverständlich halten, nicht vorhanden waren. Überlegen Sie, wozu Computer vor 20 Jahren in der Lage waren, und vergleichen Sie sie mit ihrem aktuellen Status. Sogar das ursprüngliche Linux-Bootstrap-System Minix wurde erst 1987 veröffentlicht , und die Entwicklung von GNU begann 1984. Während dies theoretisch die Frage beantworten mag, ist es in der Praxis als Antwort weitgehend nutzlos.
CVn

2
Der früheste Computer, den ich möglicherweise in die Hände bekommen könnte, wäre ein 286. Ich werde sehen müssen, ob meine Großeltern ihn noch haben.
David J

1
Bonuspunkte, wenn man das tatsächlich bedenkt :-). @DavidJ
11684

@ MichaelKjörling: Nicht wirklich; da es nur Ihre Bootstrap-Kette länger macht. Aber vielleicht nicht, solange Sie Ihren eigenen Compiler komplett in Maschinensprache schreiben.
Evi1M4chine
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.