Gibt es eine Shell, die überprüft, ob der Code signiert ist?

19

Ich habe diese Woche mit PowerShell rumgespielt und festgestellt, dass Sie Ihre Skripte signieren müssen, damit sie ausgeführt werden können. Gibt es eine ähnliche sichere Funktionalität in Linux, die die Ausführung von Bash-Skripten verhindert?

Die einzige ähnliche Funktionalität, die mir bekannt ist, ist die von SSH, für die ein bestimmter Schlüssel erforderlich ist.

leeand00
quelle
2
Klingt ein bisschen nach einer Ad-hoc-Lösung für die Paketsignatur. Ich weiß nicht, ob Windows ein Verschlüsselungspaket hat, das wie Linux signiert.
Wildcard
6
@ leeand00 Ein Skript ist ein Sonderfall eines Softwarepakets, und ich sehe keinen Grund, diesen Fall herauszugreifen.
Gilles 'SO- hör auf böse zu sein'
2
Der Mechanismus, den ich am meisten mag, ist die Art und Weise, wie ChromeOS dies tut - das einzige Dateisystem, das nicht noexecauf einer schreibgeschützten Partition auf einem mit dm-verity signierten Blockgerät markiert ist .
Charles Duffy
1
source.android.com/security/verifiedboot spricht über die Übernahme dieser Funktion durch Android (ursprünglich ChromeOS).
Charles Duffy
1
Sie können bash als eine Reihe von Befehlen betrachten, die manuell über die Befehlszeilenschnittstelle eingegeben werden können. Was nützt es, die Skripte einzuschränken, wenn Sie den Inhalt trotzdem in die Befehlszeile eingeben können?
Ding-Yi Chen

Antworten:

11

Wenn Sie die Möglichkeit der Benutzer sperren, Skripts über auszuführen, können sudoSie die digestFunktionalität verwenden.
Sie können den Hash eines Skripts / einer ausführbaren Datei angeben, in dem / sudoersder sudovor der Ausführung überprüft wird . Obwohl dies nicht mit dem Signieren identisch ist, erhalten Sie eine grundlegende Garantie dafür, dass das Skript zumindest nicht geändert wurde, ohne dass auch die Sudoer geändert wurden.

Wenn einem Befehlsnamen ein Digest_Spec vorangestellt ist, stimmt der Befehl nur dann erfolgreich überein, wenn er mit dem angegebenen SHA-2-Digest überprüft werden kann. Dies kann in Situationen nützlich sein, in denen der Benutzer, der sudo aufruft, Schreibzugriff auf den Befehl oder sein übergeordnetes Verzeichnis hat. Die folgenden Digest-Formate werden unterstützt: sha224, sha256, sha384 und sha512. Die Zeichenfolge kann entweder im Hex- oder im Base64-Format angegeben werden (Base64 ist kompakter). Es gibt verschiedene Dienstprogramme, die SHA-2-Digests im Hex-Format generieren können, z. B. openssl, shasum, sha224sum, sha256sum, sha384sum, sha512sum.

http://www.sudo.ws/man/1.8.13/sudoers.man.html

batfastad
quelle
Das wird mich aufhalten, bis ich über SE Linux gelesen habe und es richtig mache.
leeand00
13

Ja und nein.

Die Linux-Softwareverteilung funktioniert etwas anders als die Windows-Softwareverteilung. In der (nicht eingebetteten) Linux-Welt erfolgt die Verbreitung von Software in erster Linie über eine Distribution (Ubuntu, Debian, RHEL, Fedora, Arch usw.). Alle großen Distributionen unterzeichnen ihre Pakete seit etwa einem Jahrzehnt systematisch.

Wenn Software unabhängig verteilt wird, kann der Anbieter selbst entscheiden, wie er seine Software versendet. Gute Anbieter stellen Paketquellen bereit, die mit den Hauptdistributionen kompatibel sind (es gibt keinen einheitlichen Verteilungsmechanismus für Linux: Die Softwareverteilung ist einer der Hauptunterscheidungspunkte zwischen Distributionen) und die mit dem Schlüssel des Anbieters signiert sind. Linux-Distributionen fungieren selten als Signaturautorität für Drittanbieter (Canonical tut dies mit Ubuntu-Partnern, dies gilt jedoch nur für sehr wenige Anbieter), und ich denke, dass alle wichtigen Distributionen das PGP-Web of Trust anstelle der TLS-Infrastruktur für öffentliche Schlüssel verwenden Es ist Sache des Benutzers, herauszufinden, ob er einem Schlüssel vertrauen möchte.

Es gibt keinen speziellen Mechanismus, der Softwarepakete, die aus einem einzelnen Skript bestehen, aus Softwarepaketen herausfiltert, die aus einer nativen ausführbaren Datei, einer Datendatei oder mehreren Dateien bestehen. Ebenso wenig ist eine Signaturüberprüfung in einen gängigen Skriptinterpreter integriert, da die Überprüfung eines Softwarepakets eine völlig orthogonale Angelegenheit bei der Ausführung eines Skripts ist.

Ich denke, Windows beschriftet Dateien mit ihrem Ursprung und benötigt eine Bestätigung des Benutzers, um eine Datei auszuführen, deren Ursprung "heruntergeladen" und nicht "lokal" ist. Linux hat nicht wirklich einen ähnlichen Mechanismus. Das Nächste ist die Ausführungsberechtigung: Eine heruntergeladene Datei hat keine Ausführungsberechtigung. Der Benutzer muss sie explizit aktivieren ( chmod +xin der Befehlszeile oder der entsprechenden Aktion in einem Dateimanager).

Gilles 'SO - hör auf böse zu sein'
quelle
2
FWIW kann PowerShell (über Richtlinieneinstellungen) so konfiguriert werden, dass nur signierte Skripten ausgeführt werden. Diese Richtlinie kann so konfiguriert werden, dass alle Skripten signiert werden müssen oder nur Skripten mit "Remote-Ursprung" oder keine Skripten. Es funktioniert am besten in einer AD-Umgebung mit Schlüsselverwaltung und zentraler Richtlinienverwaltung. Es kann umgangen werden :-)
Stephen Harris
@ Stephen Harris Nun ja, wenn Sie es auf Bypass setzen ...
leeand00
@ leeand00 - Anscheinend funktioniert die Base64-Codierung auch als Bypass, aber ich weiß nicht, ob dies in neueren Versionen von PowerShell geschlossen wurde.
Stephen Harris
1
@ leeand00 - siehe darkoperator.com/blog/2013/3/5/… für ein bisschen Spaß :-) Übergebe das base64-codierte Skript als Parameter in der Befehlszeile :-) Einfach genug, um es zu verpacken!
Stephen Harris
2
SeLinux kommentiert Dateien mit ihrem Ursprung. Es ist eines der Hauptgebäude.
loa_in_
10

Linux bietet keine Möglichkeit, die Ausführung von Bash-Skripten basierend auf digitalen Signaturen einzuschränken.

Es gibt einige Arbeiten zur Authentifizierung von ausführbaren Binärdateien. Weitere Informationen finden Sie unter https://lwn.net/Articles/488906/ .

Quentin Fennessy
quelle
Stimmen Sie für eine direkte Antwort zu, ohne eine Abhilfe vorzuschlagen.
User394
8

Mit einem Wort "nein".

Linux unterscheidet nicht wirklich zwischen ausführbaren Dateien und Skripten. Der #!Anfang ist eine Möglichkeit, dem Kernel mitzuteilen, welches Programm ausgeführt werden soll, um die Eingabe auszuwerten. Es ist jedoch nicht die einzige Möglichkeit, ein Skript auszuführen.

Also zum Beispiel, wenn ich ein Skript habe

$ cat x
#!/bin/sh 
echo hello

Dann kann ich das mit dem Befehl ausführen

$ ./x

Dadurch versucht der Kernel, ihn auszuführen, erkennt den Kernel #!und wird /bin/sh xstattdessen effektiv ausgeführt .

Ich könnte aber auch jede dieser Varianten ausführen:

$ sh ./x
$ bash ./x
$ cat x | sh
$ cat x | bash
$ sh < x

oder auch

. ./x

Selbst wenn der Kernel versucht hat, das Signieren auf der execEbene zu erzwingen, können wir dies umgehen, indem wir den Interpreter nur mit dem Skript als Parameter ausführen.

Dies bedeutet, dass sich der Signaturcode im Interpreter selbst befinden muss. Und was würde einen Benutzer daran hindern, eine eigene Kopie einer Shell ohne den Signatur-Erzwingungscode zu kompilieren?

Die Standardlösung hierfür ist nicht die Verwendung von Signaturen, sondern die Verwendung von obligatorischen Zugriffskontrollen (Mandatory Access Controls, MAC) wie z SELinux. Bei MAC-Systemen können Sie genau festlegen, was jeder Benutzer ausführen und Layer wechseln darf. Sie können also beispielsweise sagen, dass "normale Benutzer alles ausführen können, außer dass der Webserver und CGI-Prozesse nur auf Daten aus dem /var/httpdVerzeichnis zugreifen können ; alles andere wird abgelehnt".

Stephen Harris
quelle
1
This means that signing code would have to be in the interpreter itself. And what would stop a user from compiling their own copy of a shell without the signing enforcement code?Nicht erlaubt die Ausführung beliebiger unsigned Executables würde es tun, wenn der Benutzer nicht über die Signaturschlüssel. Hierfür gibt es bereits verschiedene * nix-Projekte.
Alzee
2

Linux-Distributionen haben normalerweise gnupg . Für mich klingt alles, was Sie wollen, wie ein einfacher Bash-Wrapper, der eine getrennte gpg-Signatur mit dem Argument-Skript vergleicht und das Skript nur dann ausführt, wenn die Prüfung erfolgreich ist:

#!/bin/sh
gpgv2 $1.asc && bash "$@"
PSkocik
quelle
Das Einzige, was hier nicht
angezeigt
2

Die Gegenfrage, die sofort in den Sinn kommt, lautet: "Warum sollten Sie jemals verhindern wollen, dass Benutzer Programme ausführen, die sie geschrieben haben? " Es gibt verschiedene Möglichkeiten:

  1. Es ist buchstäblich unmöglich zu erkennen, wer den Code überhaupt geschrieben hat. Der Eigentümer der Skriptdatei ist nur derjenige, der den Inhalt dieser Datei tatsächlich gespeichert hat, unabhängig davon, woher er stammt. Das Erzwingen einer Signatur ist also nur ein komplizierter Ersatz für ein Bestätigungsdialogfeld: "Sind Sie sicher, dass Sie dies tun möchten?" In Linux wird ein Teil dieses Problems transparent mit signierten Paketen gelöst und durch die Tatsache gemildert, dass Benutzer standardmäßig nur eingeschränkten Zugriff haben. Der Benutzer muss außerdem wissen, dass das Ausführen des Codes anderer Benutzer gefährlich sein kann *.
  2. Ebenso ist das Signieren eines Skripts viel komplexer als das Speichern einer Datei. Im besten Fall wird der Benutzer dazu aufgefordert, zu erkennen, dass er eine Aktion ausführt, die dem Signieren eines Dokuments ähnelt, und die darin enthaltenen Informationen zu überprüfen, bevor er fortfährt. Höchstwahrscheinlich wird nur ein Minimum an technischen Kenntnissen des Benutzers sichergestellt , damit das Skript ausgeführt werden kann. Im schlimmsten Fall zeigt es die Bereitschaft, durch eine lange Reihe von Reifen zu springen, um zu laufen, was sie wollten. Technische Kenntnisse werden unter Linux * vorausgesetzt.
  3. Es ist wahrscheinlicher, dass Benutzer offensichtlich bösartigen Code erkennen, wenn sie eine Reihe von Befehlen in ihre Befehlszeile eingeben / einfügen . Klartext-Snippets, die kopiert und eingefügt werden sollen, sind normalerweise kleiner als die Befehlsfolge, die erforderlich ist, um etwas richtig Schändliches zu tun. Der Benutzer kann auch sorgfältig jede Zeile einzeln kopieren und einfügen, um zu verstehen, was passiert, wenn es passiert. Mit einem Skript ist es möglich, dass der Benutzer den Code noch nie gesehen hat. Dies kann eine nützliche Anwendung für signierte Skripte sein, die nach dem 12. Mal zu den allzu üblichen Selbstgefälligkeitskosten führt.

* Das wird wahrscheinlich immer weniger wahr, je mehr Leute anfangen, Linux zu benutzen

l0b0
quelle
1

Der Grund, warum sich die Systeme unterschiedlich entwickelt haben, ist, dass Linux das Dateiattribut 'exec' hat und Windows Dateierweiterungen verwendet, um die Ausführbarkeit zu bestimmen.

Unter Windows ist es daher einfach, den Benutzer zum Herunterladen einer Datei mit der Erweiterung ".exe", ".bat", ".scr" zu verleiten, die standardmäßig ausgeblendet ist . Ein Doppelklick auf diese Datei würde Ihnen die Ausführung von beliebigem Code ermöglichen. Daher wurde ein umfassender Mechanismus zur Herkunftsverfolgung und zum Signieren von ausführbaren Dateien / Skripten entwickelt, um dieses Risiko zu minimieren.

Unter Linux können Sie möglicherweise eine Datei an den Benutzer senden, das 'exec'-Bit kann jedoch nicht einfach gesetzt werden. Außerdem ist es möglich, ganze Dateisysteme zu "noexec" zu machen.

Sie können ein Skript auf jeden Fall explizit ausführen, indem Sie den Interpreter aufrufen. Sie können sogar Shell-Skripte zur Laufzeit erstellen und diese an "sh" weiterleiten oder "sh -c" ausführen.

pjc50
quelle
0

Viele Archivierungsprogramme bewahren standardmäßig das Ausführungsbit für enthaltene Dateien nicht auf. Dies macht es unmöglich, beliebige ausführbare Dateien auszuführen. Naja fast.

Der Punkt ist, was in einer anderen Antwort beschrieben wurde, dass das Fehlen eines Ausführungsbits Sie nicht daran hindert, ein solches Skript direkt an zu übergeben bash. Während es sich bei den meisten solchen Skripten wohl um bashSkripten handelt, kann der shebang jedes Programm als Interpreter angeben. Dies bedeutet, dass der Benutzer einen geeigneten Interpreter ausführen muss, wenn er die ausführbare Semantik ignorieren möchte.

Dies ist zwar nicht viel, deckt jedoch die Verhinderung der Ausführung nicht vertrauenswürdiger ausführbarer Dateien auf * Nixen mit nur Kernel und Shell ab .

Wie ich in einem der Kommentare erwähnt habe, gibt es eine weitere Schutzebene - SeLinux-, die den Ursprung von Dateien anhand einer Reihe von Regeln nachverfolgt. Eine Einrichtung SeLinuxwürde es beispielsweise root nicht erlauben, eine ausführbare Datei mit ausführbaren Bits auszuführen, die aus dem Internet heruntergeladen wurde, selbst wenn Sie die Datei kopieren und verschieben. Man kann eine Regel hinzufügen, die besagt, dass solche Dateien nur über eine andere Binärdatei ausgeführt werden können, die die Signatur überprüft, ähnlich wie Sie es in Ihrer Frage erwähnt haben.

Letztendlich handelt es sich also um die Konfiguration häufig vorinstallierter Tools, und die Antwort lautet Ja .

loa_in_
quelle
Viele Archivierungsprogramme bewahren das Ausführungsbit für enthaltene Dateien nicht auf . Nun, das ist eine Art Handicap, wenn Sie es tatsächlich für die Archivierung verwenden möchten. Zum Glück tar bleibt das Ausführungsbit erhalten.
pjc50
Du musst tar -p source
loa_in_
-p, --preserve-permissions, --same-permissionsbedeutet, Informationen über Dateiberechtigungen zu extrahieren (Standard für Superuser)
loa_in_
Nein, Sie brauchen -p NICHT. Ich sehe, was die Manpage sagt, aber es ist nicht das, was passiert. touch permtest; chmod +x permtest; tar cf permtest.tar.gz permtest; rm permtest; tar xf permtest.tar.gz; ls -l permtest- es ist hier ausführbar und ich bin nicht root.
Domen
Ich werde dann versuchen, meine Antwort zu verbessern.
loa_in_