Wie funktioniert "env X =" () {(a) => \ "sh -c" Echo-Datum "?

7

Nachdem ich über die neueste bashSicherheitsanfälligkeit gelesen hatte , fragte ich mich, wie der Exploit von Tavis Ormandy funktioniert. Wie funktioniert das (a)=>\?

Er hat gepostet:

Das Bash-Patch scheint mir unvollständig zu sein, die Funktionsanalyse ist immer noch spröde. z.B

$ env X='() { (a)=>\' sh -c "echo date"; cat echo
Wondernewbie
quelle
Ich habe unter stackoverflow.com/a/26045918/1126841 geraten . Ich bin mir nicht sicher, ob es richtig ist, also werde ich es hier nicht duplizieren.
Chepner

Antworten:

5

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_FUNCDEFundSEVAL_ONECMD. Wenn die Funktion mit aufgerufen SEVAL_FUNCDEFwird, soll sie die Interpretation anderer Befehle als Funktionsdefinitionen verhindern. Das SEVAL_ONECMDFlag 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/sheine symbolische Verbindung zu ist bash. Wenn die als Operand für angegebene Befehlszeichenfolge -cin 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 dateBefehl ausgeführt wird und seine Standardausgabe in eine aufgerufene Datei umgeleitet wird echo. Der Rest cat echoist nicht Teil des Exploits, sondern zeigt nur, dass jetzt eine Datei namens echomit der Ausgabe von dateexistiert.

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
Thomas Nyman
quelle
3
Das, was mich an diesem gesamten Exploit überrascht, ist nicht die Idee, dass es sich um einen Exploit handelt, sondern die Tatsache, dass er seit BASH 1.13
eyoung100
@ eyoung100 Ich bin mir nicht sicher, was du mit "der Art und Weise, wie Linux erstellt wurde" meinst. echowird nur aufgrund seiner Position im Befehl (bash) als Datei "(Name) behandelt. In echo datedate wird ebenfalls nicht als Befehl behandelt. In >echo dateEcho ist jedoch der Name der Datei angegeben, in die die Ausgabe des dateBefehls umgeleitet wird.
Leiaz
@Liaz die Tatsache, dass dies überhaupt funktioniert, ist die Natur, auf die ich mich einließ. Versuchen Sie, einen Befehl wie echo unter Windows als Datei zu behandeln, und Windows teilt Ihnen mit, dass echo ein Befehl ist. Die Natur hier ist, dass Linux sich nicht darum kümmert, da alles in Linux eine Datei / ein Dateistream usw. ist. Siehe diesen Artikel
eyoung100
1
@ eyoung100 Vielen Dank für das Korrekturlesen, obwohl ich zu unterscheiden bin, dass dies irgendetwas damit zu tun hat, dass "alles eine Datei ist" . Zum Beispiel dir>echoist es in Windows vollkommen gültig. Der einzige Unterschied besteht darin, dass Bash Umleitungsoperatoren erlaubt, einem Befehl vorauszugehen .
Thomas Nyman
1
@ eyoung100 Sicher, und ich stimme zu, dass der Grund, warum echoes als Outfile endet, ziemlich dunkel ist (und die Verwendung hier macht es noch verwirrender, aber das war es, was die Frage spezifizierte). Ich versuche nur darauf hinzuweisen, dass ich nicht glaube, dass dies wirklich daran liegt, dass " die Art und Weise, wie Linux erstellt wurde" , sondern nur daran, wie Bash die Verwendung von Umleitungsoperatoren ermöglicht. Trotzdem danke für deine Verbesserungen. Sie haben darauf hingewiesen, wo ich nicht klar war, und ich habe versucht, die Antwort genauer zu bearbeiten.
Thomas Nyman