ksmbd streams_xattr OOB write → local LPE (CVE-2025-37947)
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, indem KASLR, SMEP und SMAP mit standardmäßigen Kernel-Heap-Primitives (msg_msg + pipe_buffer) umgangen werden.
- Betroffene Komponente: fs/ksmbd/vfs.c — ksmbd_vfs_stream_write()
- Primitive: page-overflow OOB write über einen 0x10000-Byte-kvmalloc()-Buffer hinaus
- Voraussetzungen: ksmbd läuft mit einer authentifizierten, beschreibbaren Freigabe unter Verwendung von vfs streams_xattr
Beispiel smb.conf
[share]
path = /share
vfs objects = streams_xattr
writeable = yes
Ursache des Problems (Allocation begrenzt, memcpy an ungebremstem Offset)
- Die Funktion berechnet
size = *pos + count, begrenztsizeaufXATTR_SIZE_MAX(0x10000), wenn es überschritten wird, und berechnetcount = (*pos + count) - 0x10000neu, führt aber trotzdemmemcpy(&stream_buf[*pos], buf, count)in einen 0x10000-Byte-Puffer aus. Wenn*pos ≥ 0x10000ist, liegt der Zielpointer bereits außerhalb der Allocation, wodurch ein OOB write voncountBytes entsteht. streams_xattrspeichert SMB alternate data streams in POSIX extended attributes, daher stammt die 0x10000-Grenze vom Linux-Single-xattr-Size-Limit und nicht von einem SMB-Protokollfeld. Das macht den Bug nur dann praktisch ausnutzbar, wenn die Freigabe ausdrücklichvfs objects = streams_xattraktiviert und das Dateisystem xattrs unterstützt.
Warum der Schreib-Offset wichtig ist
- Der verwundbare Pfad ist nicht nur „mehr als 64KiB schreiben“. Die fehlende Prüfung war, dass
*posnicht gegen die aktuelle Stream-Länge (v_len) validiert wurde, bevor die Append/Copy-Logik lief. - Upstream hat das behoben, indem Writes mit
*pos >= v_lenmit-EINVALabgelehnt werden. Vor dem Fix konnte ein Angreifer einen gültig authentifizierten Handle auf einen benannten Stream wiederverwenden und einen rohen SMB2 WRITE senden, dessenfile_offsetbereits auf oder hinter dem Ende des vorhandenen Streams zeigt, wodurch das post-clampmemcpy()zu einem deterministischen Page overflow wird. - Der öffentliche PoC demonstriert das, indem er sich mit
libsmb2authentifiziert, einen Stream-Pfad wie1337:öffnet,SessionId/TreeId/FileIdextrahiert und dann einen handgefertigten SMB2 WRITE mitfile_offset = 0x10018und einer kleinenLengthsendet.
Verwundbarer Funktionsausschnitt (ksmbd_vfs_stream_write)
```c // 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-Steering und OOB-Länge
- Beispiel: Setze 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], also 0x18 Bytes über die 16-Page-Allocation hinaus.
Triggering the bug via SMB streams write
- Verwende dieselbe authentifizierte SMB-Verbindung, um eine Datei auf dem Share zu öffnen und einen Write auf einen named stream (streams_xattr) auszuführen. Setze file_offset ≥ 0x10000 mit einer kleinen Länge, um einen deterministischen OOB write mit kontrollierbarer Größe zu erzeugen.
- libsmb2 kann verwendet werden, um zu authentifizieren und solche Writes über SMB2/3 zu bauen.
- In der Praxis ist es bequem, die ausgehandelte SMB-Session wiederzuverwenden, weil der Exploit nur ein paar dynamische Felder im WRITE-Request (
TreeId,SessionId,FileId) patchen muss und dann das fehlerhafte Paket direkt über denselben Socket senden kann.
Minimal reachability (concept)
// 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-Zuweisung (16 zusammenhängende pages) vom buddy allocator an, wenn size > KMALLOC_MAX_CACHE_SIZE. Das ist kein SLUB cache object.
- memcpy erfolgt unmittelbar nach der Zuweisung; post-allocation spraying ist unwirksam. Du musst den physical memory vorher groomen, damit ein ausgewähltes target direkt hinter dem zugewiesenen 16-page block liegt.
- Auf Ubuntu zieht GFP_KERNEL oft aus dem Unmovable migrate type in zone Normal. Erschöpfe die order-3- und order-4-freelists, um den allocator zu zwingen, einen order-5 block in ein angrenzendes order-4 + order-3 pair zu splitten, und parke dann ein order-3 slab (kmalloc-cg-4k) direkt hinter dem stream buffer.
Praktische page shaping strategy
- Sprite ~1000–2000 msg_msg objects mit ~4096 bytes (passt zu kmalloc-cg-4k), um order-3 slabs zu belegen.
- Empfange einige messages, um holes zu erzeugen und adjacency zu fördern.
- Triggere den ksmbd OOB wiederholt, bis der order-4 stream buffer direkt vor einem msg_msg slab landet. Nutze eBPF tracing, um addresses und alignment zu bestätigen, falls verfügbar.
Nützliche Observability
# 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
Was beim Tuning zu tracen ist
kvmalloc_node(0x10000)bestätigt, wann der verwundbare stream write tatsächlich eine order-4-Allokation verbraucht.load_msg/kretprobe:load_msglässt dich abschätzen, wie vielemsg_msgseg-Allokationen an jede gesprayte Message angehängt sind, was beim Tuning von primary/secondary Message-Größen für einen bestimmten Kernel-Build nützlich ist.- Wenn der exploit auf eine andere Distro/einen anderen Kernel portiert wird, prüfe Cache-Namen, Inline-
msg_msg-Payload-Größen,anon_pipe_buf_ops-Offsets und Gadget-Adressen erneut, statt anzunehmen, dass die Ubuntu 22.04 LTS5.15.0-153-generic-Konstanten noch passen.
Exploitation-Plan (msg_msg + pipe_buffer), angepasst von CVE-2021-22555
- Viele System V
msg_msgprimary/secondary Messages sprayen (4KiB groß, um inkmalloc-cg-4kzu passen). - ksmbd OOB auslösen, um den
next-Pointer einer primary Message zu korrumpieren, sodass zwei primaries eine secondary teilen. - Das korrumpierte Paar durch Taggen von Queues und Scannen mit
msgrcv(MSG_COPY)erkennen, um nicht übereinstimmende Tags zu finden. - Die echte secondary freigeben, um ein UAF zu erzeugen; sie mit kontrollierten Daten via UNIX sockets reclaimen (eine gefälschte
msg_msgbauen). - Kernel-Heap-Pointer leaken, indem
m_ts-Over-read incopy_msgausgenutzt wird, ummlist.next/mlist.prevzu erhalten (SMAP-Bypass). - Mit einem
sk_buff-Spray eine konsistente gefälschtemsg_msgmit gültigen Links wieder aufbauen und sie normal freigeben, um den Zustand zu stabilisieren. - Das UAF mit
struct pipe_buffer-Objekten reclaimen;anon_pipe_buf_opsleaken, um die Kernel-Base zu berechnen (KASLR besiegen). - Eine gefälschte
pipe_buf_operationssprayen, derenreleaseauf einen Stack-Pivot/ROP-Gadget zeigt; Pipes schließen, um auszuführen und root zu erlangen.
Bypasses und Notizen
- KASLR:
anon_pipe_buf_opsleaken, Base (kbase_addr) und Gadget-Adressen berechnen. - SMEP/SMAP: ROP im Kernel-Kontext über den
pipe_buf_operations->release-Flow ausführen; Userspace-Derefs vermeiden, bis diedisable/prepare_kernel_cred/commit_creds-Kette ausgeführt wurde. - Hardened usercopy: für diese Page-Overflow-Primitive nicht relevant; die Korruptionsziele sind keine Usercopy-Felder.
Zuverlässigkeit
- Hoch, sobald Adjazenz erreicht ist; gelegentliche Misses oder Panics (<10%). Das Tuning von Spray-/Free-Counts verbessert die Stabilität. Das Überschreiben der zwei LSBs eines Pointers, um bestimmte Kollisionen zu erzwingen, wurde als effektiv berichtet (z. B. ein
0x0000_0000_0000_0500-Muster in den Overlap schreiben).
Wichtige Parameter zum Tuning
- Anzahl der
msg_msg-Sprays und Hole-Pattern - OOB-Offset (
pos) und resultierende OOB-Länge (count') - Anzahl der UNIX-socket-,
sk_buff- undpipe_buffer-Sprays in jeder Phase
Mitigations und Erreichbarkeit
- Fix: sowohl Allokation als auch Destination/Länge begrenzen oder
memcpygegen die zugewiesene Größe bounds; Upstream-Patches werden als CVE-2025-37947 verfolgt. - Remote exploitation würde zusätzlich einen zuverlässigen infoleak und Remote-Heap-Grooming erfordern; diese Beschreibung konzentriert sich auf lokales LPE.
Siehe auch
Ksmbd Attack Surface And Fuzzing Syzkaller
References PoC und Tooling
libsmb2für SMB-Auth und streams writes- eBPF-Tracer-Script zum Loggen von
kvmalloc-Adressen und zum Erstellen eines Histogramms der Allokationen (z. B.grep 4048 out-4096.txt) - Ein minimales Reachability-PoC und ein vollständiger lokaler exploit sind öffentlich verfügbar (siehe References)
References
- ksmbd - Exploiting CVE-2025-37947 (3/3) — Doyensec
- Linux upstream fix:
ksmbd: prevent out-of-bounds stream writes by validating *pos - KSMBD-CVE-2025-37947 PoC repository
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.


