Open Source im professionellen Einsatz

Double-Free-Fehler in Linux Kernel

 Eine Schwachstelle in dem Linux-Kernel führt dazu, dass ein physisch lokaler Angreifer unter Umständen Befehle mit Kernel-Rechten und Denial-of-Service-Attacken ausführen kann. Die Sicherheitslücke kann nur ausgenutzt werden, wenn der USB-MIDI-Treiber des Kernels geladen ist. Zum Ausführen der Denial-of-Service-Attack benötigt der Angreifer physischen Zugriff auf den Rechner. Konkret muss er in der Lage sein, einen speziell präparierten USB-Stick in den Rechner zu stecken. Alle aktuellen Kernel-Versionen sind scheinbar anfällig für diese Attacke. Das Ausführen von Programmcode mit Ring-0-Privilegien setzt weiter voraus, dass der Angreifer auch einen lokalen Account auf dem System besitzt. Das ist notwendig, damit der Angreifer als nicht priviligierter Nutzer den Exploit ausführen kann.

Ursache für beide Probleme ist ein Programmierfehler in dem Code des Midiman-USB-Gerätes. Hier kommt es zu einem Double-Free-Fehler beim Verarbeiten eines »snd_usb_midi«-Objektes. Dies geschieht immer dann, wenn das Midiman-USB-Gerät mit einer falschen Anzahl von USB-Endpoints initialisiert wird. Beide Schwachstellen können durch das Einstecken des USB-Sticks ausgelöst werden. Nach dem Einstecken führt der Kernel einige Standardroutinen aus. Zunächst ruft er die »probe()«-Funktion auf, um herauszufinden, welcher Treiber für den Stick verantwortlich ist. Dabei werden auch verschiedene Initialisierungsanweisungen ausgeführt. Die Attacke gegen den USB-MIDI-Treiber setzt nun genau hier an. Auch hier werden innerhalb des Probe-Vorgangs einige Initialisierungen vorgenommen. Dies funktioniert problemlos bis zu dem Aufruf der »snd_usbmidi_create()«-Funktion:

if (quirk && quirk->type == QUIRK_MIDI_MIDIMAN)
      err = snd_usbmidi_create_endpoints_midiman(umidi, &endpoints[0]);
else
      err = snd_usbmidi_create_endpoints(umidi, endpoints);

if (err < 0) {        
      snd_usbmidi_free(umidi);
      return err;
}

Da es sich um ein Midiman-Gerät handelt, wird hier der erste If()-Zweig ausgeführt. Damit wird dann die »snd_usbmidi_create_endpoints_midiman()«-Funktion aufgerufen, die die USB-Endpoints für diesen Gerätetyp einrichtet. Für die Attacke wird hier nun aber eine inkorrekte Anzahl von Endpoints spezifiziert (z.b. Null). Dadurch schlägt eine Prüfung innerhalb der Funktion fehl:

if (intfd->bNumEndpoints < (endpoint->out_cables > 0x0001 ? 5 : 3)) {
     dev_dbg(&umidi->dev->dev, "not enough endpoints\n");        
     return -ENOENT;
}

Die »snd_usbmidi_create_endpoints_midiman()«-Funktion liefert einigen negativen Rückgabewert (-ENOENT), weshalb die »snd_usbmidi_create()«-Funktion dann anschließend die »snd_usbmidi_free()«-Funktion aufruft, die das zuvor alloziierte »snd_usb_midi«-Objekt wieder freigibt. Das Problem besteht nun darin, dass durch das Fehlschlagen des Probe-Prozesses weitere Aufräumfunktionen aufgerufen werden, die unter anderem abermals die »snd_usbmidi_free()«-Funktion für das »snd_usb_midi«-Objekt aufrufen. Dies ist dann ein typischer Double-Free-Fehler, der von dem Angreifer ausgenutzt werden kann.

Die Schwachstellen werden nur ausgelöst, wenn eine in Device-ID verwendet wird, die als QUIRK_MIDI_MIDIMAN in der »sound/usb/quirks-table.h«-Datei gelistet ist. Der Patch für diese recht kritische Sicherheitslücke ist sehr einfach: In der »snd_usbmidi_create()«-Funktion (»sound/usb/midi.c«-Datei) muss lediglich der »snd_usbmidi_free()«-Aufruf entfernt werden. Dann kehrt die »snd_usbmidi_create()«-Funktion mit einem Fehlercode zurück, aber gibt nicht zusätzlich das Objekt frei, wodurch der Double-Free-Fehler korrigiert ist. Diese Sicherheitslücke im Kernel wurde mit dem KASAN-Tool entdeckt. KASAN (KernelAddressSanitizer) ist speziell dafür entwickelt Speicherlecks im Linux Kernel zu entdecken. Neben diesem Tool haben die Entdecker der Schwachstelle auch den virtual USB Fuzzer (vUSBf)) verwendet. 

Exploits wurden ebenfalls für die Schwachstelle veröffentlicht. Das Ausführen von Code ist natürlich komplizierter als das reine Ausführen der Denial-of-Service-Attacke. Der Exploit nutzt die Double-free-Schwachstelle, um bestimmte Bereiche des Kernelspeichers zu überschreiben. Konkret überschreibt der Exploit nach einigen Schritten einen Funktionszeiger in der »ubuf_info«-Struktur  und lenkt diesen Zeiger auf eine eigene bereitgestellte Funktion, die dann den Schadcode des Angreifers ausführt.

comments powered by Disqus

Ausgabe 09/2016

Digitale Ausgabe: Preis € 6,40
(inkl. 19% MwSt.)

Artikelserien und interessante Workshops aus dem Magazin können Sie hier als Bundle erwerben.