
Bildungsfallstudie und Exploit-Entwicklungsdurchgang für CVE-2022-0185, einen Heap-basierten Pufferüberlauf im Linux-Kernel, der eine lokale Privilegienausweitung ermöglicht. Enthält POC, QEMU-Debugging und Ubuntu-Exploit mit detaillierter technischer Analyse.
Diese Fallstudie ist das Ergebnis einer Aufgabe des Kurses ECE 9069: Einführung in das Hacking: https://whisperlab.org/introduction-to-hacking/
CVE-2022-0185 ist ein heap-basierter Pufferüberlauffehler, der in der Art und Weise gefunden wurde, wie die Funktion legacy_parse_param in der Funktionalität des Dateisystemkontexts des Linux-Kernels die Länge der übergebenen Parameter überprüft. Ein nicht privilegierter (falls nicht privilegierte Benutzernamensräume aktiviert sind, andernfalls benötigt es das CAP_SYS_ADMIN-Privileg im Namensraum) lokaler Benutzer, der ein Dateisystem öffnen kann, das die Filesystem-Context-API nicht unterstützt (und daher auf die Legacy-Behandlung zurückfällt), könnte diesen Fehler nutzen, um seine Privilegien auf dem System zu erweitern. [1]
Nachdem diese Schwachstelle gemeldet wurde, wurde ein Patch zur Behebung dieses Fehlers veröffentlicht:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=722d94847de2
https://ubuntu.com/security/CVE-2022-0185#impact-score
Es gibt eine ausführliche Beschreibung vom Entdecker: https://www.hackthebox.com/blog/CVE-2022-0185:_A_case_study
In diesem Repository werde ich die grundlegenden Schritte und die damit verbundenen Hintergrundinformationen zur Reproduktion dieser Schwachstelle erklären. Falls etwas unklar ist, können Sie mir eine E-Mail an [email protected] senden. Ich beantworte die Frage gerne.
Die Schwachstelle CVE-2022-0185 wurde am 02.11.2022 mit einem CVSS 3.x-Basiswert von 8,4 (Hoch) veröffentlicht.[1] Diese Schwachstelle ist ein heap-basierter Pufferüberlauf, der durch einen vorzeichenlosen Integer-Unterlauf verursacht wird.
Die Schwachstelle wurde im Linux-Kernel v5.1 eingeführt und betrifft alle Linux-Distributionen mit Kernelversionen höher als 5.1. Beispielsweise war Ubuntu 20.04 LTS (focal) von diesem Fehler betroffen. Ein Patch wurde jedoch veröffentlicht und ist seit Version 5.4.0-96.109 verfügbar.[3]
Die Ausnutzung dieser Schwachstelle ermöglicht es einem nicht privilegierten lokalen Benutzer, seine Privilegien auf dem System zu erweitern und möglicherweise das gesamte System zu gefährden.[1] [2]
Hier ist eine detaillierte Analyse des CVSS-Scores: Basis-Score: 8,4, was auf ein erhebliches Sicherheitsrisiko hinweist, das sofortige Aufmerksamkeit erfordert. Auswirkungs-Score: 5,9, was auf einen erheblichen potenziellen Schaden hindeutet, falls die Schwachstelle ausgenutzt wird. Die hohen Werte für Vertraulichkeit, Integrität und Verfügbarkeit tragen zu diesem Score bei. Ausnutzbarkeits-Score: 2,5, was auf eine relativ hohe Ausnutzbarkeit hindeutet. Der lokale Angriffsvektor, die hohe Integrität und die hohe Verfügbarkeit tragen zu diesem Score bei.
Tabelle 1.1 und Tabelle 1.2 enthalten weitere Informationen zu diesen Scores und ihren Komponenten.
| CVSS v3.1 Schweregrad | Wert |
|---|---|
| Basis-Score | 8,4 HOCH |
| Auswirkungs-Score | 5,9 |
| Ausnutzbarkeits-Score | 2,5 |
Tabelle 1.1 CVSS-Schweregrad-Scores[1]
| CVSS v3.1 Metriken | Wert |
|---|---|
| Angriffsvektor (AV) | Lokal |
| Erforderliche Privilegien (PR) | Keine |
| Benutzerinteraktion (UI) | Keine |
| Vertraulichkeit (C) | Hoch |
| Integrität (I) | Hoch |
| Verfügbarkeit (A) | Hoch |
Tabelle 1.2 CVSS-Vektor[1]
Es gibt in modernen Computern zwei Integer-Typen: vorzeichenbehaftet und vorzeichenlos. Die Darstellung vorzeichenbehafteter Zahlen erfolgt üblicherweise durch eine Operation namens Zweierkomplement.[4] "Das Zweierkomplement verwendet das Binärbit mit dem größten Stellenwert als Vorzeichen, um anzuzeigen, ob die Binärzahl positiv oder negativ ist"[4]
Die Einführung des Zweierkomplements wandelt die Berechnung der Subtraktion in eine Addition um, was das Design und die Implementierung der CPU vereinfacht. Die Erzeugung des Zweierkomplements einer Ganzzahl umfasst drei Schritte:[4]
Abb. 2.1.1.1 zeigt den Konvertierungsprozess in einem Diagramm mit einem konkreten Beispiel der Konvertierung von "-6" in sein Zweierkomplement-Format.

Abb. 2.1.1.1 Zweierkomplement-Konvertierung
Abbildung 2.1.1.2 zeigt den Prozess der Addition des Zweierkomplements von '-6' zu '+6'. Dies demonstriert, wie die Verwendung des Zweierkomplements die Addition als Ersatz für die Subtraktion ermöglicht.

Abb. 2.1.1.2 Addition mittels Zweierkomplement
Aus Abschnitt 2.1.1 wissen wir bereits, was das Zweierkomplement ist. Betrachten wir nun das Szenario des vorzeichenlosen Integer-Unterlaufs in Computern. In modernen Computern wird bei der Verwendung vorzeichenloser Zahlen das höchstwertige Bit nicht als Vorzeichenbit behandelt, sondern ist Teil der vorzeichenlosen Zahl selbst. Diese Situation bedeutet, dass bei der Subtraktion mit vorzeichenlosen Zahlen Vorsicht geboten ist, da dies zu einem Zustand führen kann, der als vorzeichenloser Integer-Unterlauf bekannt ist.[5]
Abb. 2.1.2.1 veranschaulicht die Situation, in der bei einer 8-Bit vorzeichenlosen Zahl 6 von 5 subtrahiert wird. Das Endergebnis ist 255, da die vorzeichenlose Zahl sich umschlägt. Wenn dieser Unterlauf in einer Bedingungsanweisung auftritt, kann er die Funktionalität der Anweisung stören.

Abb. 2.1.2.1 Vorzeichenloser Integer-Unterlauf
Im Linux-Kernel ist der Slab-Allokator ein Speicherverwaltungsmechanismus, der zur effizienten Allokation und Freigabe kleiner Speicherblöcke verwendet wird. Er bietet Leistungsvorteile, indem er mehrere Caches von Slabs verwaltet, die jeweils Speicherblöcke mit fester Größe enthalten. Typischerweise allokiert kmalloc-32 32 Bytes Speicher (ein kmalloc-32-Slab), während kmalloc-4k 4096 Bytes Speicher allokiert (ein kmalloc-4k-Slab).[6]
Darüber hinaus erfolgt die Slab-Allokation im Linux-Kernel typischerweise durch die Allokation von Speicher aus einem zusammenhängenden Adressraum innerhalb des Heap-Speicherbereichs des Kernels. Dieser zusammenhängende Adressraum wird vom Kernel verwaltet und zur Allokation von Speicher für verschiedene Kernel-Objekte und Datenstrukturen verwendet. Abb. 2.2.1.1 zeigt das Layout der Slabs im Linux-Kernel-Speicher.

Abb. 2.2.1.1 Slab-Allokator in Linux [7] (Der Autor dieser Abbildung ist https://leviathan.vip/)
Wenn Sie den Prozess mit einem selbst kompilierten Linux-Kernel reproduzieren möchten, lesen Sie bitte die folgenden Markdown-Dateien, um die Hintergrundinformationen zu erhalten: