ksmbd streams_xattr OOB write → local LPE (CVE-2025-37947)
Reading time: 7 minutes
tip
Lernen & üben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking:
HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
Diese Seite dokumentiert einen deterministischen out-of-bounds write in der ksmbd streams-Verarbeitung, der eine zuverlässige Linux kernel privilege escalation auf Ubuntu 22.04 LTS (5.15.0-153-generic) ermöglicht und KASLR, SMEP und SMAP unter Verwendung standardmäßiger kernel heap primitives (msg_msg + pipe_buffer) umgeht.
- Betroffene Komponente: fs/ksmbd/vfs.c — ksmbd_vfs_stream_write()
- Primitiv: page-overflow OOB write past a 0x10000-byte kvmalloc() buffer
- Voraussetzungen: ksmbd läuft mit einem authentifizierten, beschreibbaren Share, das vfs streams_xattr verwendet
Beispiel smb.conf
[share]
path = /share
vfs objects = streams_xattr
writeable = yes
Ursache (Allokation begrenzt, memcpy bei ungegrenztem Offset)
- Die Funktion berechnet size = *pos + count, begrenzt size auf XATTR_SIZE_MAX (0x10000) wenn überschritten, und berechnet count = (*pos + count) - 0x10000 neu, führt aber weiterhin memcpy(&stream_buf[*pos], buf, count) in einen 0x10000-Byte-Puffer aus. Wenn *pos ≥ 0x10000 ist, liegt der Zielzeiger bereits außerhalb der Allokation, was einen OOB write von count Bytes erzeugt.
Verwundbarer Funktionsausschnitt (ksmbd_vfs_stream_write)
// https://elixir.bootlin.com/linux/v5.15/source/fs/ksmbd/vfs.c#L411
static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos, size_t count)
{
char *stream_buf = NULL, *wbuf;
size_t size;
...
size = *pos + count;
if (size > XATTR_SIZE_MAX) { // [1] clamp allocation, but...
size = XATTR_SIZE_MAX;
count = (*pos + count) - XATTR_SIZE_MAX; // [1.1] ...recompute count
}
wbuf = kvmalloc(size, GFP_KERNEL | __GFP_ZERO); // [2] alloc 0x10000
stream_buf = wbuf;
memcpy(&stream_buf[*pos], buf, count); // [3] OOB when *pos >= 0x10000
...
kvfree(stream_buf);
return err;
}
Offset-Steuerung und OOB-Länge
- Beispiel: Setzen Sie den file offset (pos) auf 0x10018 und die ursprüngliche Länge (count) auf 8. Nach dem Clamping ist count' = (0x10018 + 8) - 0x10000 = 0x20, aber memcpy schreibt 32 bytes beginnend bei stream_buf[0x10018], d.h. 0x18 bytes über die 16-Seiten-Allokation hinaus.
Auslösen des Fehlers über SMB streams write
- Verwenden Sie dieselbe authentifizierte SMB-Verbindung, um eine Datei auf dem Share zu öffnen und einen write an einen benannten Stream (streams_xattr) auszuführen. Setzen Sie file_offset ≥ 0x10000 mit einer kleinen Länge, um einen deterministischen OOB write mit kontrollierbarer Größe zu erzeugen.
- libsmb2 kann verwendet werden, um sich zu authentifizieren und solche writes über SMB2/3 zu erzeugen.
Minimale Erreichbarkeit (Konzept)
// Pseudocode: send SMB streams write with pos=0x0000010018ULL, len=8
smb2_session_login(...);
smb2_open("\\\\host\\share\\file:stream", ...);
smb2_pwrite(fd, payload, 8, 0x0000010018ULL); // yields 32-byte OOB
Allocator-Verhalten und warum page shaping erforderlich ist
- kvmalloc(0x10000, GFP_KERNEL|__GFP_ZERO) fordert eine order-4 (16 zusammenhängende Seiten) Allocation vom buddy allocator an, wenn size > KMALLOC_MAX_CACHE_SIZE. Dies ist kein SLUB cache Objekt.
- memcpy erfolgt unmittelbar nach der Allocation; post-allocation spraying ist wirkungslos. Sie müssen den physischen Speicher pre-groomen, sodass ein gewähltes Target unmittelbar nach dem zugewiesenen 16-Seiten-Block liegt.
- Auf Ubuntu zieht GFP_KERNEL häufig aus dem Unmovable migrate type in zone Normal. Erschöpfen Sie order-3- und order-4-freelists, um den allocator zu zwingen, einen order-5-Block in ein angrenzendes order-4 + order-3-Paar zu splitten, und parken Sie dann einen order-3 slab (kmalloc-cg-4k) direkt nach dem stream buffer.
Practical page shaping strategy
- Spray ~1000–2000 msg_msg objects of ~4096 bytes (fits kmalloc-cg-4k) to populate order-3 slabs.
- Empfange einige Nachrichten, um Löcher zu erzeugen (punch holes) und Adjazenz zu fördern.
- Trigger the ksmbd OOB wiederholt, bis der order-4 stream buffer unmittelbar vor einem msg_msg slab landet. Use eBPF tracing, um Adressen und Alignment zu bestätigen, falls verfügbar.
Nützliche Beobachtbarkeit
# Check per-order freelists and migrate types
sudo cat /proc/pagetypeinfo | sed -n '/Node 0, zone Normal/,/Node/p'
# Example tracer (see reference repo) to log kvmalloc addresses/sizes
sudo ./bpf-tracer.sh
Ausnutzungsplan (msg_msg + pipe_buffer), angepasst an CVE-2021-22555
- Viele System V msg_msg primary/secondary-Nachrichten sprayen (4KiB groß, passend für kmalloc-cg-4k).
- ksmbd OOB auslösen, um den next-Pointer einer primary-Nachricht zu korrumpieren, sodass zwei primaries eine secondary teilen.
- Das korrumpierte Paar erkennen, indem Queues getaggt und mit msgrcv(MSG_COPY) gescannt werden, um nicht übereinstimmende Tags zu finden.
- Die echte secondary freigeben, um einen UAF zu erzeugen; sie mit kontrollierten Daten über UNIX sockets zurückerlangen (ein fake msg_msg erstellen).
- Kernel-Heap-Pointer leak durch Ausnutzung der m_ts-Überlesung in copy_msg erhalten, um mlist.next/mlist.prev zu bekommen (SMAP bypass).
- Mit einem sk_buff-spray ein konsistentes fake msg_msg mit gültigen Links aufbauen und normal freigeben, um den Zustand zu stabilisieren.
- Den UAF mit struct pipe_buffer-Objekten zurückerlangen; anon_pipe_buf_ops leak, um die Kernel-Base (kbase_addr) zu berechnen (KASLR umgehen).
- Ein fake pipe_buf_operations sprayen, dessen release auf einen Stack-Pivot/ROP-Gadget zeigt; Pipes schließen, um auszuführen und root zu erlangen.
Bypasses und Hinweise
- KASLR: anon_pipe_buf_ops leak, Kernel-Base (kbase_addr) und Gadget-Adressen berechnen.
- SMEP/SMAP: ROP im Kernel-Kontext über pipe_buf_operations->release ausführen; userspace-Derefs vermeiden, bis nach der disable/prepare_kernel_cred/commit_creds-Chain.
- Hardened usercopy: nicht auf dieses page-overflow-Primitive anwendbar; die Korruption zielt auf Nicht-usercopy-Felder.
Zuverlässigkeit
- Hoch, sobald Adjazenz erreicht ist; gelegentliche Fehlschläge oder Panics (<10%). Anpassung der Spray/Free-Anzahlen verbessert die Stabilität. Das Überschreiben der zwei LSBs eines Pointers, um spezifische Kollisionen zu induzieren, wurde als effektiv berichtet (z. B., write 0x0000_0000_0000_0500 pattern into the overlap).
Wichtige Parameter zum Tuning
- Anzahl der msg_msg-sprays und Hole-Muster
- OOB-Offset (pos) und resultierende OOB-Länge (count')
- Anzahl der UNIX socket-, sk_buff- und pipe_buffer-Sprays in jeder Phase
Gegenmaßnahmen und Erreichbarkeit
- Fix: sowohl Allocation als auch Ziel/Length begrenzen oder memcpy gegen die zugewiesene Größe absichern; Upstream-Patches sind als CVE-2025-37947 gelistet.
- Remote-Exploitation würde zusätzlich ein zuverlässiges infoleak und remote Heap-Grooming erfordern; dieser Write-up konzentriert sich auf lokalen LPE.
Referenzen, PoC und Werkzeuge
- libsmb2 für SMB auth und streams writes
- eBPF tracer script, um kvmalloc-Adressen zu loggen und Histogramm-Allokationen (z. B. grep 4048 out-4096.txt)
- Minimaler Reachability-PoC und vollständiger lokaler Exploit sind öffentlich verfügbar (siehe Referenzen)
Referenzen
- ksmbd - Exploiting CVE-2025-37947 (3/3) — Doyensec
- libsmb2
- KSMBD-CVE-2025-37947: proof-of-concept.c
- KSMBD-CVE-2025-37947: CVE-2025-37947.c (full exploit)
- bpf-tracer.sh
tip
Lernen & üben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking:
HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
HackTricks