GNU Bash exportiert Shell-Funktionen in Umgebungsvariablen, die die Funktionsdefinitionen enthalten:
$ function foo { echo bar; }
$ export -f foo
$ env | grep -A1 foo
foo=() { echo bar
}
Wenn eine neue Bash-Instanz erzeugt wird, sucht sie nach Umgebungsvariablen, die einem bestimmten Muster entsprechen. Der Inhalt dieser Variablen wird automatisch als Shell-Funktionen importiert. Wie Stéphane Chazelas erklärt , erfolgte der Import von Funktionen seit Einführung dieser Funktion in Bash 1.03 einfach durch Ersetzen =
des entsprechenden Eintrags im Array der Umgebungsvariablen und Interpretieren des Ergebnisses als Funktionsdefinition. Vor dem Patch , mit dem CVE-2014-6271 behoben wurde , wurde die Umgebungsvariable vollständig interpretiert, einschließlich aller Befehle, die dem eigentlichen Funktionskörper folgen. Der Patch führt zwei spezielle Modi in die parse_and_execute()
Funktion ein, SEVAL_FUNCDEF
undSEVAL_ONECMD
. Wenn die Funktion mit aufgerufen SEVAL_FUNCDEF
wird, soll sie die Interpretation anderer Befehle als Funktionsdefinitionen verhindern. Das SEVAL_ONECMD
Flag soll verhindern, dass die Funktion mehr als einen einzelnen Befehl auswertet.
Die speziell gestaltete Umgebungsvariable von Tavis Ormandy macht etwas subtil anderes. Es soll den Parser verwirren und den Puffer beschädigen, der zum Speichern der auszuwertenden Befehle verwendet wird. Reste der Umgebungsvariablen im Puffer ändern die Interpretation des nachfolgenden Befehls . Dieses verwandte Problem hat die CVE-Kennung CVE-2014-7169 erhalten .
Die Bestandteile der Definition von Umgebungsvariablen X='() { (a)=>\'
sind:
() {
Dies wird vom Parser als Beginn einer Funktionsdefinition interpretiert
(a)=
soll den Parser verwirren und dazu führen, dass Reste der Umgebungsvariablen im Puffer verbleiben
>\
ist die tatsächliche Nutzlast, die im Puffer verbleibt
Der Zweck der Nutzdaten besteht darin, die Interpretation des Befehls zu ändern, der in der von aufgerufenen Subshell ausgeführt wird sh -c "echo date";
. Dies setzt natürlich voraus, dass dies /bin/sh
eine symbolische Verbindung zu ist bash
. Wenn die als Operand für angegebene Befehlszeichenfolge -c
in den Puffer gestellt wird, lautet der Inhalt des Puffers:
>\[0xA]echo date
Das [0xA]
ist ein ASCII-Zeilenumbruchzeichen, das normalerweise als Befehlstrennzeichen fungiert, jetzt jedoch \
von der Nutzlast entfernt wird. Infolgedessen wird der Inhalt des Puffers als interpretiert
>echo date
Da mit Bash Umleitungsoperatoren Befehle vorangestellt werden können , entspricht dies
date > echo
Dies führt einfach dazu, dass der date
Befehl ausgeführt wird und seine Standardausgabe in eine aufgerufene Datei umgeleitet wird echo
. Der Rest cat echo
ist nicht Teil des Exploits, sondern zeigt nur, dass jetzt eine Datei namens echo
mit der Ausgabe von date
existiert.
In (a)=
Bezug auf den Grund, warum die Zeichenfolge den Parser in diesem Fall verwirrt, scheint es, dass die damit verbundene Zeichenfolge als (fehlerhafte) verschachtelte Funktionsdefinition angezeigt wird. Die vereinfachte Variante des Exploits zeigt dies deutlicher:
$ X='() { function a a>\' bash -c echo
$ ls echo
echo