
CVE-2026-68398 Ubuntu PPPoL2TP use-after-free local privilege escalation

Dieses Repository enthält einen an ein bestimmtes Build gebundenen Exploit zur lokalen Privilegienerweiterung für CVE-2026-68398, einen Use-after-free-Race zwischen der Empfangsverarbeitung von PPPoL2TP und der Zerstörung eines nicht angehängten PPP-Kanals. Es wurde in QEMU gegen das offizielle Ubuntu-22.04-Paket linux-image-5.15.0-187-generic (5.15.0-187.197) validiert.
Der finale Test startet als dedizierter Benutzer mit UID 1001, ohne zusätzliche Gruppen, ohne Capabilities und ohne sudo-Zugriff, und erlangt danach UID 0 im initialen Namespace. KASLR, SMEP, SMAP und AppArmor bleiben aktiviert. Der Gast wird nicht mit nokaslr, nopti, nosmep oder nosmap gebootet.
Warnung
Dieser Code beschädigt absichtlich den Kernel-Heap-Zustand und ist an genau einen Ubuntu-Kernel-Build gebunden. Ein fehlgeschlagenes Race kann einen Kernel-Panic auslösen oder das System beschädigen. Führe ihn nur in einer isolierten, wegwerfbaren VM aus, die dir gehört.
pppol2tp_recv() wird im L2TP-UDP-Empfangspfad innerhalb eines kritischen RCU-Leseabschnitts ausgeführt und ruft schließlich ppp_input(&po->chan) auf. Der PPPoX-Socket und sein eingebetteter ppp_channel sind RCU-sicher, aber das interne struct channel, das von ppp_input() verwendet wird, ist eine separate Allokation.
Bei einem Kanal, der mit PPPIOCGCHAN gebunden, aber weder an eine PPP-Einheit angehängt noch gebrückt ist, gab der Schließpfad dieses interne Objekt sofort frei:
RX: l2tp_udp_encap_recv -> pppol2tp_recv -> ppp_input(channel)
CLOSE: pppol2tp_release -> pppox_unbind_sock
-> ppp_unregister_channel -> ppp_release_channel -> kfree(channel)
Der Empfangspfad kann daher auf der skb-Warteschlange und der Waitqueue des freigegebenen Kanals operieren. Der Fix fügt struct channel einen RCU-Callback hinzu und verschiebt das Leeren der Warteschlange sowie die Freigabe, bis eine RCU-Grace-Period verstrichen ist.
Die Schwachstelle wurde upstream von Norbert Szetei von Doyensec entdeckt und behoben. Der Mainline-Fix ist ec4215683e47424c9c4762fd3c60f552a3119142.
Der Linux-CNA-Eintrag gibt an, dass die verwundbare Linie mit Linux 4.15 beginnt. Herstellerkernel können den Fix unter einer anderen Versionsnummer enthalten; daher haben der exakte Quellcode bzw. das Paket-Changelog Vorrang vor dieser Tabelle.
Ältere unterstützte Herstellerlinien benötigen einen Backport. Stand 2026-08-12 markiert der Ubuntu-CVE-Tracker das linux-Paket von Jammy als needs-triage; es wurde kein korrigiertes Ubuntu-Jammy-Paket identifiziert. Der getestete Quellcode von 5.15.0-187.197 ruft weiterhin direkt kfree(pch) auf und ist verwundbar.
Der Kernel wurde nicht neu kompiliert. Dem minimalen Cloud-Image fehlte linux-modules-extra-5.15.0-187-generic, daher wurde dieses offizielle Ubuntu-Paket installiert, um l2tp_ppp bereitzustellen. Eine normale Jammy-Installation über das Metapaket linux-generic hängt bereits vom passenden modules-extra-Paket ab. Das Protokollmodul wird automatisch geladen, wenn der Exploit seinen PPPoL2TP-Socket erstellt.
Der automatische KASLR-Detektor nutzt einen x86-Prefetch-Timing-Seitenkanal und erfordert RDTSCP und inaktives KPTI. Die getestete Host-CPU stellt rdtscp, smep und smap bereit, ist nicht von Meltdown betroffen, und Ubuntu lässt KPTI daher ohne Boot-Override inaktiv. Auf einer CPU, bei der /proc/cpuinfo das pti-Flag meldet, weigert sich der Detektor zu laufen. Dabei handelt es sich um eine exploit-spezifische Hardwarebedingung: Die zugrunde liegende CVE bleibt erreichbar, aber diese Version beansprucht keinen KASLR-Bypass auf einem System mit aktivem KPTI. Ein manuell angegebener Slide existiert nur für kontrollierte Diagnosen.
struct channel wieder. Der weiterhin laufende RX-Pfad behandelt kontrollierte Key-Bytes als seine skb-Warteschlange und Waitqueue.core_pattern als Offenlegungs-Scratch und legt einen Key-Allokationszeiger offen.override_creds() mit den gefälschten Credentials auf. UID-/GID-Felder, Capabilities sowie die erforderlichen User-, Namespace-, Ucount- und Gruppen-Pointer entsprechen exakt dem Ubuntu-Build./proc/self/exe in eine eindeutige Datei in /tmp, ändert sie auf Root-Besitz mit Modus 4755 und verifiziert diese Attribute./usr/bin/id aus.Der letzte Brückenschritt ist notwendig, weil override_creds() die subjektiven Credentials der aktiven Kernel-Task ändert; das Installieren und Ausführen der verifizierten SUID-Kopie verwandelt diese kurzlebige Primitive in normale Prozess-Credentials.
Das Makefile linkt den Exploit statisch. Das zeitkritische Prefetch-Objekt wird bewusst mit -O0 kompiliert; der Exploit selbst verwendet -O2.
make
Äquivalente Befehle:
gcc -O0 -Wall -Wextra -Werror -c -o build/kaslr_prefetch.o kaslr_prefetch.c
gcc -O2 -static -pthread -Wall -Wextra -Werror \
-o build/CVE-2026-68398 exploit.c build/kaslr_prefetch.o
Aus dem normalen Benutzerkonto auf dem exakt validierten Kernel:
id
grep '^Cap' /proc/self/status
./CVE-2026-68398 auto 60
Der Quellcode prüft uname() und verweigert jede andere Version als 5.15.0-187-generic. Der Race ist probabilistisch; starte nach einem Fehlversuch oder Absturz einen Wegwerf-Snapshot neu, bevor du es erneut versuchst.
Ein erfolgreicher Lauf endet mit:
[KASLR] image_base=0xffffffffb9200000 slide=0x38200000
CVE-2026-68398 Ubuntu local privilege-escalation exploit
uid=1001 euid=1001 slide=0x38200000
...
[9/9] invoking override_creds and installing the SUID transition...
override callback: uid=0 euid=0 gid=0 egid=0
installed root-owned mode 4755 helper: /tmp/.cve-2026-68398-root-948
SUID helper ready; executing it from the original unprivileged task...
SUID transition: uid=0 euid=0 gid=0 egid=0
uid=0(root) gid=0(root) groups=0(root),1001(poc)
Das vollständige kompakte Transkript dieses realen QEMU-Laufs ist in docs/example-output.txt zu finden.
Die Kette wurde auf drei frischen, normal randomisierten Ubuntu-Boots abgeschlossen. Die automatisch ermittelten Image-Basen waren 0xffffffff90800000, 0xffffffffa5a00000 und 0xffffffffb9200000. Der finale Lauf verwendete das oben beschriebene dedizierte nicht-administrative Konto mit UID 1001 und verifizierte, dass die temporäre SUID-Datei danach entfernt wurde.
Derselbe finale Race wurde außerdem 60 Sekunden lang mit dem exakten Upstream-Fix-Commit, aktiviertem KASAN und derselben Vier-vCPU-Topologie ausgeführt. Er durchlief 5969 Kanal-/Schlüssel-Zyklen, meldete stage 1: no controlled reclaim und erzeugte weder einen KASAN-Bericht noch einen Exploit-Stufenübergang.
Geprüft am 2026-08-12, bevor dieses private Repository erstellt wurde. SearchSploit/Exploit-DB lieferte keinen Exploit; Packet Storm lieferte keine passende Datei; die GitHub-Suche nach exaktem Code lieferte 22 CVE-/Advisory-Spiegel und keinen PoC; und exakte Websuchen fanden nur den Upstream-Fix und Metadaten. Dies ist eine Momentaufnahme und keine Garantie, dass nicht später ein weiterer PoC erscheint.
kaslr_prefetch.c istDer Exploit wurde von A. Ramos <[email protected]> geschrieben (Twitter: @aramosf). Die Entdeckung der Schwachstelle und der Upstream-Fix werden Norbert Szetei (Doyensec) zugeschrieben.
exploit.c ist GPL-2.0-only. kaslr_prefetch.c und kaslr_prefetch.h sind MIT-lizenziert und behalten die KASLD-Zuschreibung sowie den vollständigen Berechtigungshinweis in den Quelldateien.
| Kernel-Serie | Erste behobene Version | Fix-Commit |
|---|
| 6.6.y | 6.6.148 | 4bb84e964ff0 |
| 6.12.y | 6.12.101 | 3ab32218d718 |
| 6.18.y | 6.18.42 | c9574b8a8ede |
| 7.1.y | 7.1.6 | 06213c85d8c0 |
| Mainline | 7.2-rc4 | ec4215683e47 |
| Eigenschaft | Wert |
|---|
| Distribution | Ubuntu 22.04.5 LTS (Jammy) |
| Kernel-Paket | linux-image-5.15.0-187-generic / 5.15.0-187.197 |
| Kernel-Release | 5.15.0-187-generic #197-Ubuntu |
| Architektur | x86-64 |
| VM | QEMU/KVM, -cpu host, vier vCPUs, 5 GiB RAM |
| Anfängliche Identität | uid=1001(poc) gid=1001(poc) groups=1001(poc) |
| Anfängliche Capabilities | inheritable, permitted, effective und ambient alle null |
| Endgültige Identität | uid=0(root) gid=0(root) in den initialen Namespaces |
| Boot-Änderungen | Keine; Standard-Befehlszeile, KASLR aktiviert |
| Anforderung | Zustand bei Ubuntu 5.15.0-187 | Exploit-Nutzung |
|---|
| PPP | CONFIG_PPP=y | Eingebaut |
| L2TP / PPPoL2TP | CONFIG_L2TP=m, CONFIG_PPPOL2TP=m | Offizielles Modul aus linux-modules-extra |
| User-Keys | CONFIG_KEYS=y | Belegt den freigegebenen kmalloc-256-Kanal wieder |
| AppArmor | CONFIG_SECURITY_APPARMOR=y | Bleibt aktiv; die gefälschten Credentials enthalten ein gültiges unconfined-Label |
| KASLR | CONFIG_RANDOMIZE_BASE=y | Bleibt aktiv; der Slide wird zur Laufzeit ermittelt |
| SMAP | CONFIG_X86_SMAP=y | Bleibt aktiv |
| User-/Netzwerk-Namespaces | Von Ubuntu aktiviert, aber nicht verwendet | Kein Namespace-Setup oder Capability-Gewinn erforderlich |
/dev/ppp | Nicht erforderlich | Der Kanal ist gebunden, aber nie mit einer PPP-Einheit verbunden |