it-swarm.com.de

Ist es gefährlich, beliebiges C zu kompilieren?

Ich habe einen kleinen Server und möchte die Kompilierungszeiten für C-Programme überprüfen, die von Benutzern bereitgestellt werden. Die Programme würden niemals nur kompiliert ausgeführt.

Welche Risiken bestehen darin, dass Benutzer beliebiges C mit gcc 5.4.0 kompilieren können?

69

Ein bisschen seltsam, aber: Es ist ein Denial-of-Service-Risiko oder eine potenzielle Offenlegung von Informationen.

Da der Präprozessor von C fröhlich jede Datei enthält, die in einer #include - Direktive angegeben ist, kann jemand #include "../../../../../../../../../../dev/zero" Und der Präprozessor wird versuchen, bis zum Ende von /dev/zero Zu lesen (viel Glück).

In ähnlicher Weise könnte jemand versuchen, verschiedene Dateien einzuschließen, die möglicherweise auf Ihrem System vorhanden sind oder nicht, und insbesondere Informationen über Ihren Computer erhalten, insbesondere wenn Sie den Benutzern die Ausgabe ihrer Kompilierungsversuche anzeigen lassen. In Kombination mit der cleveren Verwendung von #pragma poison können sie sogar etwas über den Dateiinhalt lernen, selbst wenn Sie dies nicht tun Keine vollständigen Fehlermeldungen.

In ähnlicher Weise können Pragmas das Verhalten von Präprozessoren, Compilern oder Linkern stark verändern und werden in Quelldateien angegeben. Es gibt wahrscheinlich keine, mit der jemand so etwas wie den Namen der Ausgabedatei oder ähnliches angeben kann, aber wenn dies der Fall ist, könnte es missbraucht werden, um vertraulich zu überschreiben Dateien oder sich selbst ausführen lassen (durch Schreiben in cron oder ähnliches). Es könnte etwas ähnlich Gefährliches geben. Sie sollten wirklich vorsichtig sein, wenn Sie nicht vertrauenswürdigen Code kompilieren.

94
CBHacking

Compilerbomben

C ist eine sehr mächtige Sprache, und einige der schrecklichen Dinge, die Sie damit machen können, würden Sie schockieren. Sie können beispielsweise ein 16-Byte-C-Programm erstellen, dessen Kompilierung 27 Minuten dauert , und wenn es schließlich fertig ist, wird es Kompiliert zu einer 16 Gigabyte ausführbaren Datei. Und das mit nur 16 Bytes. Wenn Sie den Präprozessor und größere Quellcodedateien berücksichtigen, können Sie sicher viel größere Compilerbomben erstellen.

Dies bedeutet, dass jeder, der Zugriff auf Ihren Server hat, effektiv einen DoS Angriff auf Ihren Server ausführen kann. Um fair zu sein, ist dies deutlich weniger gefährlich, als wenn jemand eine Sicherheitsanfälligkeit im Compiler missbraucht oder vertrauliche Dateien einschließt, um Informationen über Ihren Server zu erhalten (wie die anderen Antwortenden, über die gesprochen wurde).

Aber es ist noch eine weitere mögliche Belästigung, die beim Kompilieren von beliebigem Code auftreten kann. Ich bin sicher, Sie könnten ein Zeitlimit für alle Builds festlegen und sicherstellen, dass die Binärdateien niemals gespeichert werden. Obwohl Sie es natürlich immer noch auf der Festplatte behalten müssen, während es erstellt wird . Wenn also jemand hypothetisch eine Compilerbombe größer als Ihre Festplatte gemacht hat, sind Sie es Ich wäre in Schwierigkeiten (wenn Sie den Build beenden lassen).

41
James

@ AndréBorie ist korrekt. Compiler und die entsprechende Konfiguration werden auf Sicherheitsprobleme nicht gut überprüft. Daher sollten Sie im Allgemeinen keinen nicht vertrauenswürdigen Code kompilieren.

Das Risiko besteht darin, dass ein Pufferüberlauf oder eine Sicherheitsanfälligkeit bezüglich der Bibliotheksausführung ausgenutzt wird und der Angreifer Zugriff auf das Benutzerkonto (hoffentlich nicht -root!) Erhält, mit dem der Compiler ausgeführt wurde. Selbst ein nicht -root Hack ist in den meisten Fällen schwerwiegend. Dies könnte in einer gesonderten Frage erläutert werden.

Das Erstellen eines VM ist eine gute Lösung, um potenzielle Exploits einzudämmen, damit sie den Rest Ihrer Anwendung nicht beschädigen können.

Es ist am besten, eine Vorlage Linux VM zu haben, die Sie nach Bedarf mit einer sauberen Slate-Compiler-Umgebung starten können.

Idealerweise würden Sie es nach jedem Gebrauch wegwerfen, dies ist jedoch möglicherweise nicht unbedingt erforderlich. Wenn Sie die VM gut genug isolieren und die Antwortdaten von der VM ordnungsgemäß bereinigen, was Sie sowieso tun sollten; dann ist das Schlimmste, was ein Hack tun kann, DoS oder das Erstellen falscher Kompilierungszeiten Keine ernsthaften Probleme für sich allein, zumindest nicht annähernd so schwerwiegend wie der Zugriff auf den Rest Ihrer Anwendung.

Das Zurücksetzen von VM nach jeder Verwendung (d. H. Anstelle von täglich)) sorgt jedoch insgesamt für eine stabilere Umgebung und kann in bestimmten Edge-Fällen die Sicherheit verbessern.

Einige Betriebssysteme bieten Container als Alternative zu VMs an. Dies mag ein schlankerer Ansatz sein, es gelten jedoch dieselben Grundsätze.

28
Bryan Field

Ja, es ist gefährlich, aber wie die Leute gesagt haben, ist es möglich. Ich bin der Autor und Betreuer der Online-Compiler unter https://gcc.godbolt.org/ , und ich fand es ziemlich praktikabel, sie mit einer Kombination aus:

  • Die gesamte Site wird auf einer VM - Instanz mit geringen Berechtigungen ausgeführt, um etwas zu tun. Das Netzwerk ist stark eingeschränkt, da nur Port 80 sichtbar ist und ssh nur über IPs auf der Whitelist (meine eigenen) aktiviert ist.
  • Jede Kompilierungsinstanz wird in einem wegwerfbaren Docker-Container mit noch weniger Berechtigungen ausgeführt
  • Der Compiler wird von einem Skript ausgeführt, das alle Prozessgrenzen (Speicher, CPU-Zeit usw.) auf niedrige Grenzen setzt, um Codebomben zu verhindern.
  • Der Compiler wird mit einem LD_PRELOAD - Wrapper ( Quelle hier ) ausgeführt, der verhindert, dass der Compiler Dateien öffnet, die nicht in einer expliziten Whitelist enthalten sind. Dies verhindert, dass es/etc/passwd oder ähnliches liest (nicht, dass das allzu viel helfen würde).
  • Zur Sicherheit analysiere ich die Befehlszeilenoptionen und führe den Compiler nicht aus, wenn etwas besonders Verdächtiges vorliegt. Dies ist kein wirklicher Schutz. Nur eine Möglichkeit, eine Fehlermeldung "Ernsthaft, versuchen Sie es nicht" zu geben, anstatt dass LD_PRELOAD schlechtes Verhalten abfängt.

Die gesamte Quelle ist auf GitHub , ebenso wie die Quelle für Docker-Container-Images und Compiler und so weiter.

Ich habe einen Blog-Beitrag geschrieben, der erklärt, wie das gesamte Setup auch ausgeführt wird.

14
Matt G

Sie möchten den Compiler nicht als Root ausführen, obwohl ich dies aus Gründen der "Einfachheit und Bequemlichkeit" gesehen habe. Für einen Angreifer wäre es allzu einfach, Folgendes einzuschließen:

#include "../../../../etc/passwd"
#include "../../../../etc/shadow"

und erhalten Sie den Inhalt dieser Dateien als Teil der Compiler-Fehlermeldung zurück.

Auch Compiler sind Programme wie alles andere und haben ihre Fehler, die anfällig sein könnten. Es wäre für jemanden zu einfach, nur C-Programme zu fuzzeln und Probleme zu verursachen.

Die meiste Anwendungssicherheit wird sich in erster Linie auf die Eingabevalidierung konzentrieren. Leider ist die Definition von "sicheren und gültigen" Eingaben für einen C-Compiler wahrscheinlich mit dem Problem des Anhaltens in Bezug auf die Schwierigkeit verbunden :)

12
Colin Cassidy

Wenn Sie einem Benutzer erlauben, ein Archiv mit dem Code bereitzustellen, können Probleme auftreten, nicht genau mit dem Compiler, sondern mit dem verwendeten Linker;)

ld folgt symbolischen Links, wenn sie auf eine nicht vorhandene Datei verweisen. Dies bedeutet, dass, wenn Sie test.c in die Ausgabe a.out kompilieren, aber bereits einen symbolischen Link mit dem Namen a.out in Ihrem Verzeichnis haben, der auf eine nicht vorhandene Datei verweist, die kompilierte ausführbare Datei an der Stelle geschrieben wird, die auf die verweist Datei (mit der Einschränkung der Benutzerrechte).

In der Praxis könnte ein Angreifer beispielsweise eine Zeichenfolge mit einem öffentlichen SSH-Schlüssel in seinen Code aufnehmen und einen symbolischen Link mit dem Namen a.out bis ~/.ssh/autorisierte_Tasten bereitstellen . Wenn diese Datei noch nicht vorhanden ist, kann der Angreifer seinen SSH-Schlüssel in den Zielcomputer einfügen, sodass er von außen darauf zugreifen kann, ohne ein Kennwort knacken zu müssen.

3
cym13