Linux ignoriert das setuid¹-Bit in allen interpretierten ausführbaren Dateien (dh ausführbaren Dateien, die mit einer #!
Zeile beginnen). In den häufig gestellten Fragen zu comp.unix.questions werden die Sicherheitsprobleme mit setuid-Shell-Skripten erläutert. Es gibt zwei Arten von Problemen: shebang-bezogene und shell-bezogene; Ich gehe unten auf weitere Details ein.
Wenn Ihnen die Sicherheit egal ist und Sie setuid-Skripte zulassen möchten, müssen Sie unter Linux den Kernel patchen. Ab dem 3.x-Kernel muss install_exec_creds
der load_script
Funktion vor dem Aufruf von ein Aufruf hinzugefügt werden open_exec
, aber ich habe ihn nicht getestet.
Setuid Shebang
Die #!
Implementierung von shebang ( ) unterliegt einer Racebedingung:
- Der Kernel öffnet die ausführbare Datei und stellt fest, dass sie mit beginnt
#!
.
- Der Kernel schließt die ausführbare Datei und öffnet stattdessen den Interpreter.
- Der Kernel fügt den Pfad zum Skript in die Argumentliste ein (as
argv[1]
) und führt den Interpreter aus.
Wenn mit dieser Implementierung Setuid-Skripte zulässig sind, kann ein Angreifer ein beliebiges Skript aufrufen, indem er einen symbolischen Link zu einem vorhandenen Setuid-Skript erstellt, ausführt und anordnet, den Link zu ändern, nachdem der Kernel Schritt 1 ausgeführt hat und bevor der Interpreter zu ausgeführt hat Eröffnung seines ersten Arguments. Aus diesem Grund ignorieren die meisten Unices das Setuid-Bit, wenn sie einen Shebang erkennen.
Eine Möglichkeit, diese Implementierung zu sichern, besteht darin, dass der Kernel die Skriptdatei sperrt, bis der Interpreter sie geöffnet hat (beachten Sie, dass dies nicht nur das Aufheben oder Überschreiben der Verknüpfung der Datei, sondern auch das Umbenennen eines Verzeichnisses im Pfad verhindern muss). Unix-Systeme scheuen jedoch in der Regel obligatorische Sperren, und symbolische Verknüpfungen würden eine korrekte Sperrfunktion besonders schwierig und invasiv machen. Ich glaube nicht, dass es jemand so macht.
Einige Unix-Systeme (hauptsächlich OpenBSD, NetBSD und Mac OS X, für die alle eine Kernel-Einstellung erforderlich ist) implementieren Secure Setuid Shebang mit einer zusätzlichen Funktion: Der Pfad bezieht sich auf die Datei, die bereits im Dateideskriptor N geöffnet ist (also wird geöffnet) ungefähr äquivalent zu ). Viele Unix-Systeme (einschließlich Linux) haben aber keine setuid-Skripte./dev/fd/N
/dev/fd/N
dup(N)
/dev/fd
- Der Kernel öffnet die ausführbare Datei und stellt fest, dass sie mit beginnt
#!
. Angenommen, der Dateideskriptor für die ausführbare Datei lautet 3.
- Der Kernel öffnet den Interpreter.
- Der Kernel fügt
/dev/fd/3
die Argumentliste (as argv[1]
) ein und führt den Interpreter aus.
Die shebang-Seite von Sven Mascheck enthält viele Informationen zu shebang across unices, einschließlich der Unterstützung von setuid .
Setuid-Dolmetscher
Nehmen wir an, Sie haben es geschafft, Ihr Programm als Root auszuführen, entweder weil Ihr Betriebssystem setuid shebang unterstützt oder weil Sie einen nativen Binär-Wrapper (wie sudo
) verwendet haben. Haben Sie eine Sicherheitslücke geöffnet? Vielleicht . Hier geht es nicht um interpretierte oder kompilierte Programme. Das Problem ist, ob sich Ihr Laufzeitsystem sicher verhält, wenn es mit Berechtigungen ausgeführt wird.
Jede dynamisch verknüpfte native ausführbare Binärdatei wird auf eine Weise vom Dynamic Loader (z. B. /lib/ld.so
) interpretiert , der die vom Programm benötigten dynamischen Bibliotheken lädt. Auf vielen Unices können Sie den Suchpfad für dynamische Bibliotheken über die Umgebung konfigurieren ( LD_LIBRARY_PATH
ist ein gebräuchlicher Name für die Umgebungsvariable) und sogar zusätzliche Bibliotheken in alle ausgeführten Binärdateien laden ( LD_PRELOAD
). Die Aufrufer des Programms kann in diesem Programm Kontext beliebigen Code auszuführen , indem er eine speziell gestaltete Platzierung libc.so
in $LD_LIBRARY_PATH
(unter anderem Taktik). Alle vernünftigen Systeme ignorieren die LD_*
Variablen in den ausführbaren Dateien von setuid.
In Shells wie sh, csh und Derivaten werden Umgebungsvariablen automatisch zu Shell-Parametern. Durch Parameter wie PATH
, IFS
und vieles mehr, hat der Aufrufer des Skripts viele Möglichkeiten , beliebigen Code in den Shell - Skripten Kontext auszuführen. Einige Shells setzen diese Variablen auf vernünftige Standardeinstellungen, wenn sie feststellen, dass das Skript mit Berechtigungen aufgerufen wurde, aber ich weiß nicht, dass es eine bestimmte Implementierung gibt, der ich vertrauen würde.
Die meisten Laufzeitumgebungen (ob native, Bytecode oder interpretiert) haben ähnliche Funktionen. Nur wenige Benutzer treffen spezielle Vorsichtsmaßnahmen in setuid-ausführbaren Dateien, obwohl diejenigen, die systemeigenen Code ausführen, häufig nichts Schöneres tun als dynamisches Verknüpfen (was Vorsichtsmaßnahmen erfordert).
Perl ist eine bemerkenswerte Ausnahme. Es unterstützt explizit setuid-Skripte auf sichere Weise. Tatsächlich kann Ihr Skript setuid ausführen, selbst wenn Ihr Betriebssystem das setuid-Bit in Skripten ignoriert. Dies liegt daran, dass Perl mit einem setuid-Root-Helfer geliefert wird, der die erforderlichen Überprüfungen durchführt und den Interpreter für die gewünschten Skripte mit den gewünschten Berechtigungen erneut aufruft. Dies wird im perlsec- Handbuch erklärt. Früher brauchte man #!/usr/bin/suidperl -wT
stattdessen setuid-Perl-Skripte #!/usr/bin/perl -wT
, aber auf den meisten modernen Systemen #!/usr/bin/perl -wT
ist dies ausreichend.
Beachten Sie, dass die Verwendung eines systemeigenen Binär- Wrappers nichts an sich bewirkt, um diese Probleme zu vermeiden . Tatsächlich kann dies die Situation verschlimmern , da Ihre Laufzeitumgebung möglicherweise nicht erkennt, dass sie mit Berechtigungen aufgerufen wird, und die Laufzeitkonfigurierbarkeit umgeht.
Ein nativer binärer Wrapper kann ein Shell-Skript sicher machen, wenn der Wrapper die Umgebung bereinigt . Das Skript muss darauf achten, nicht zu viele Annahmen zu machen (zB über das aktuelle Verzeichnis), aber das geht. Sie können sudo dafür verwenden, sofern es so eingerichtet ist, dass die Umgebung bereinigt wird. Das Blacklisting von Variablen ist fehleranfällig, daher immer eine Whitelist. Stellen Sie mit sudo sicher, dass die env_reset
Option aktiviert und deaktiviert setenv
ist env_file
und env_keep
nur harmlose Variablen enthält.
TL, DR:
- Setuid shebang ist unsicher, wird aber normalerweise ignoriert.
- Wenn Sie ein Programm mit Berechtigungen ausführen (entweder über sudo oder setuid), schreiben Sie systemeigenen Code oder Perl oder starten Sie das Programm mit einem Wrapper, der die Umgebung bereinigt (z. B. sudo mit der
env_reset
Option).
¹ Diese Diskussion gilt auch, wenn Sie "setuid" durch "setgid" ersetzen. Beide werden vom Linux-Kernel in Skripten ignoriert