Warum ist die Fähigkeit, Funktionen in einer Umgebungsvariablen zu definieren, an sich kein Sicherheitsrisiko?

9

Nach meinem Verständnis wird es im Allgemeinen als sicher angesehen, dass jeder Informationen bereitstellt, die in einer Umgebungsvariablen gespeichert werden. Die Shellshock-Sicherheitsanfälligkeit ist hier ein Problem, da Code am Ende einer Funktionsdefinition innerhalb einer Umgebungsvariablen ausgeführt wird, wenn eine neue Bash-Instanz gestartet wird, und Sie offensichtlich nicht möchten, dass jemand den gewünschten Code auf Ihrem Server ausführt . Funktionsdefinitionen selbst stellen anscheinend kein Sicherheitsrisiko dar und sind zulässig, da sie explizit aufgerufen werden müssen, damit ihr Code ausgeführt werden kann.

Meine Frage ist, warum ein böswilliger Benutzer nicht einfach eine Funktion definieren kann, die seinen bösartigen Code als allgemeinen Befehl enthält, lsund dann hoffen kann, dass das Skript (oder was auch immer ausgeführt wird) diesen Befehl irgendwann verwendet.

Ein Beispiel für das, was ich vorhabe:

$ export ls='() { echo "doing bad things..."; }'
$ bash -c ls
doing bad things...
Reed Espinosa
quelle

Antworten:

10

Es ist ein Sicherheitsrisiko. Dies ist im Allgemeinen der Grund, warum Sie dies nicht tun können, wenn Sie in einen anderen Kontext wechseln (Fernsteuerung eines Systems, Benutzerwechsel usw.).

Wenn Sie eine beliebige Umgebungsvariable erstellen können, gibt es eine Reihe von Möglichkeiten, wie Sie beliebigen Code ausführen können.
Nehmen Sie $LD_PRELOADals Beispiel. Wenn Sie diese Variable festlegen können, können Sie Bibliotheksfunktionen ersetzen und Ihren Code dort einfügen. Sie können die $DISPLAYVariable festlegen und die X-Anzeige umleiten, mit der das Programm verbunden ist, damit Sie die Kontrolle über die App erhalten.

Aus diesem Grund entfernen Dinge wie sudodie Umgebung alle Variablen. sudoerlaubt nur ein paar ausgewählte Variablen durch. Und von diesen Variablen werden sie bereinigt (es durchläuft die $TERMVariable, aber nicht, wenn sie ungewöhnliche Zeichen enthält).

Patrick
quelle
Wow, ich hatte mich immer gefragt, warum einige große Skripte, die ich in BASH mache, seltsame arkane Fehler haben würden, wenn ich mit sudo angefangen habe, insbesondere um Pfade herum, was mich dazu brachte, nach sudo-Starts zu suchen und sie zu blockieren, aber ich wusste nie, warum das passiert ist und war Ein Problem, danke für die gute Erklärung, wie sudo Umgebungsvariablen entfernt.
Lizardx
3

Ich würde sagen, es ist, wenn Bash dein / bin / sh ist. Es ist kein Merkmal der Bourne-Shell, und ich wette, es ist auch kein Merkmal der Posix-Shell, tatsächlich möchten sie es vielleicht ausdrücklich verbieten.

Bash ist wirklich mehr eine Korn-Derivat-Shell als eine Bourne-Shell, trotz ihres Namens, und es ist die einzige Korn-ähnliche Shell, die diese Funktion hat, und meiner Meinung nach ist es eine Küchensenke-Funktion, die keine praktischen Vorteile hat. Entwickler, die Bash-Funktionen für Standards wie die Bourne-Shell, die Posix-Shell oder die ksh88-Teilmenge vermeiden, die moderne Shells gemeinsam haben, oder sich mit anderen Worten zu bewährten Praktiken und Standard-Redewendungen verpflichten, sind schockiert, wenn ihre Software eingeschaltet ist Linux und Mac und jetzt potenziell anfällig, da die Exploit-Autoren die "Bashisms" trotz ihrer Absichten frei verwenden können. Soweit die Kompatibilität verbessert wurde, wenn / bin / sh gegenüber anderen Korn-Shell-Derivaten aufgerufen wird, ist es nur dann, wenn / bin / sh Ihre Login-Shell oder interaktive Shell ist, wenn sich Bash eher wie eine Bourne-Shell als wie eine Korn-Shell verhält.

Ich werde versuchen, Sie davon zu überzeugen, dass es sich um eine Küchenspüle handelt, mit zwei Fällen: Sie sind ein eingebetteter Entwickler, der Geräte wie Router, netzwerkgebundenen Speicher 1. größer macht, mehr bedeutet, Speicher, also mehr Kosten, Wenn dies ein Grund war, diese Funktion von bash zu verwenden, sollten Sie dann nicht stattdessen FPATH und Autoload verwenden, ksh88-Funktionen? anstatt das gesamte Funktionsbyte für Byte in der Umgebung zu übergeben? Sie könnten sogar in Betracht ziehen, die Umgebung im großen Stil zu analysieren und zu bereinigen, bevor es zu einem Shellscript kommt, das eine Variable falsch analysieren könnte, z. B. einfach ^ $ (. *) $ Herausfiltern und dergleichen ...

Das unterstreicht, was daran einzigartig ist, es spielt keine Rolle, was die Variable ist, und das Skript muss nicht auf die Variable verweisen oder sie verwenden, es könnte immer noch anfällig sein.

#!/bin/sh
exec /usr/local/myapp/support/someperlscript.pl

Für alles andere unter der Sonne sollte das oben Genannte so sicher sein wie das Perl-Skript. Sie verwenden keine Variablen. Wie können Sie irgendwelche falsch analysieren? Wechseln zu

#!/bin/bash -norc
exec /usr/local/myapp/support/someperlscript.pl

Hilft auch nicht, das hatte nichts mit ENV oder so etwas zu tun - jeder wird verbrannt, weil Bash einzigartig sein muss. Die Tatsache, dass Bash Version 2 das Problem hat, beweist für mich, dass niemand diese Funktion jemals für seine Anwendungen verwendet, da sie sonst nicht so lange herum lauern sollte . Und was noch schlimmer ist, diese Funktion lässt sich grundsätzlich nicht umgehen . Hier ist ein Beispiel mit: mit 'su -'. Wenn Sie jemanden fragen würden, wäre die Erklärung, dass die Umgebung verworfen wird, die Manpage überprüft wird und Sie nur 99,9% finden. Ich habe das richtig getestet, da auf diesem System / bin / sh die Login-Shell von root ist und / bin / sh Bash ist, ABER in diesem Beispiel versuche ich esum mein .bash_profile zu härten. Ich habe mein bestehendes in root umbenannt (was aktiviert ist), aber ich dachte, wenn su, dann möglicherweise auch sudo, habe ich dies geändert:

exec env -i TERM=vt102 LOGNAME=root USER=root HOME=/var/root /bin/ksh -i

Also werfe ich die Umgebung vollständig um, verwende eine minimale Umgebung und führe dann anstelle des aktuellen Prozesses eine Shell aus, bei der das Problem nicht auftreten sollte. Versuchen Sie dann anstelle des Standardbeispiels:

%dock='() { echo -e "\e[2t\c"; echo dockshock;} ; dock' su 

Dies zeigt, dass es nichts mit dem Parsen einer bestimmten Funktion zu tun hat und ein Exploit auf die Funktion verweisen und sie verwenden kann. Sie können sich vorstellen, dass die Funktion über eine Logik verfügt, mit der getestet werden kann, ob root usw. In diesem Fall handelt es sich lediglich um eine modifizierte Form einer Funktion zum Symbolisieren oder Andocken eines Terminalfensters mithilfe einer Escape-Sequenz, die ziemlich normal ist siehe Dockshock - aber was nun? Versuchen Sie nun Folgendes:

%TERM='() { echo -e "\e[2t\c"; echo dockshock;} ; TERM' su - 

Und rate was? Das Fenster wird in das Dock gesaugt. So sieht es danach aus ..

%TERM='() { echo -e "\e[2t\c"; echo dockshock;} ; TERM' su -
Password:
dockshock
# env
_=/usr/bin/env
HOME=/var/root
LOGNAME=root
TERM=vt102
USER=root
# echo $0
/bin/ksh
#

Also viel dafür! Die exportierten Funktionen haben tatsächlich Vorrang vor RC-Skripten. Du kannst dem nicht ausweichen.

Dan LaBell
quelle
1
POSIX erlaubte exportierbare Funktionen in Entwurf 2 und ließ sie danach nicht mehr zu. Die Funktion ist verrückt.
Mikesserv