ksmbd streams_xattr OOB write → local LPE (CVE-2025-37947)
Tip
Nauči i vežbaj AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Nauči i vežbaj GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Nauči i vežbaj Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Pregledaj kompletan HackTricks Training katalog za assessment tracks (ARTA/GRTA/AzRTA) i Linux Hacking Expert (LHE).
Podrži HackTricks
- Pogledaj pretplatničke planove!
- Pridruži se 💬 Discord grupi, telegram grupi, prati @hacktricks_live na X/Twitter, ili pogledaj LinkedIn stranicu i YouTube kanal.
- Deli hacking trikove slanjem PR-ova u HackTricks i HackTricks Cloud github repozitorijume.
Ova stranica dokumentuje deterministički out-of-bounds write u ksmbd streams obradi koji omogućava pouzdanu Linux kernel privilege escalation na Ubuntu 22.04 LTS (5.15.0-153-generic), zaobilaženjem KASLR, SMEP i SMAP koristeći standardne kernel heap primitive (msg_msg + pipe_buffer).
- Affected component: fs/ksmbd/vfs.c — ksmbd_vfs_stream_write()
- Primitive: page-overflow OOB write past a 0x10000-byte kvmalloc() buffer
- Preconditions: ksmbd running with an authenticated, writable share using vfs streams_xattr
Example smb.conf
[share]
path = /share
vfs objects = streams_xattr
writeable = yes
Root cause (allocation clamped, memcpy at unclamped offset)
- Funkcija računa size = *pos + count, ograničava size na XATTR_SIZE_MAX (0x10000) kada se prekorači, i ponovo računa count = (*pos + count) - 0x10000, ali i dalje izvršava memcpy(&stream_buf[*pos], buf, count) u buffer od 0x10000 bajtova. Ako je *pos ≥ 0x10000, odredišni pokazivač je već van alokacije, što proizvodi OOB write od count bajtova.
streams_xattrčuva SMB alternate data streams unutar POSIX extended attributes, pa 0x10000 granica dolazi iz Linux single-xattr size limita, a ne iz SMB protocol polja. To čini bug praktičnim samo kada share eksplicitno omogućavavfs objects = streams_xattri filesystem podržava xattrs.
Why the write offset matters
- Vulnerable path nije samo “write više od 64KiB”. Nedostajala je provera da
*posnije validiran u odnosu na trenutnu stream dužinu (v_len) pre nego što su pokrenuti append/copy logic. - Upstream je ovo popravio tako što odbija writes gde je
*pos >= v_lensa-EINVAL. Pre fix-a, attacker je mogao da ponovo iskoristi validan authenticated handle na named stream i pošalje raw SMB2 WRITE čijifile_offsetveć pokazuje na ili iza kraja postojećeg stream-a, što post-clampmemcpy()pretvara u deterministički page overflow. - Public PoC ovo demonstrira tako što se autentifikuje sa
libsmb2, otvori stream path kao što je1337:, izdvojiSessionId/TreeId/FileId, i zatim pošalje handcrafted SMB2 WRITE safile_offset = 0x10018i malimLength.
Vulnerable function snippet (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 and OOB length
- Primer: postavi file offset (pos) na 0x10018 i originalnu dužinu (count) na 8. Nakon clamping-a, count’ = (0x10018 + 8) - 0x10000 = 0x20, ali memcpy upisuje 32 bajta počev od stream_buf[0x10018], tj. 0x18 bajtova iza 16-page allocation.
Triggering the bug via SMB streams write
- Koristi istu authenticated SMB connection da otvoriš fajl na share-u i izvršiš write u named stream (streams_xattr). Postavi file_offset ≥ 0x10000 sa malom dužinom da bi generisao deterministic OOB write kontrolisane veličine.
- libsmb2 može da se koristi za authenticate i craftovanje takvih write-ova preko SMB2/3.
- U praksi, ponovno korišćenje negotiated SMB session-a je zgodno jer exploit treba samo da patch-uje nekoliko dynamic polja u WRITE request-u (
TreeId,SessionId,FileId) i zatim može direktno da pošalje malformed packet na istom socket-u.
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
Ponašanje alokatora i zašto je potrebno page shaping
- kvmalloc(0x10000, GFP_KERNEL|__GFP_ZERO) traži alokaciju order-4 (16 uzastopnih stranica) od buddy allocator-a kada je size > KMALLOC_MAX_CACHE_SIZE. Ovo nije SLUB cache object.
- memcpy se dešava odmah nakon alokacije; spraying nakon alokacije je neefikasan. Morate unapred groomovati fizičku memoriju tako da se izabrani target nalazi odmah nakon dodeljenog 16-page bloka.
- Na Ubuntu-u, GFP_KERNEL često uzima iz Unmovable migrate type u zone Normal. Ispraznite order-3 i order-4 freelists da naterate alokator da podeli order-5 block u susedni order-4 + order-3 par, zatim parkirajte order-3 slab (kmalloc-cg-4k) direktno iza stream buffer-a.
Praktična strategija page shaping
- Spray-ujte ~1000–2000 msg_msg objects od ~4096 bytes (odgovara kmalloc-cg-4k) da popunite order-3 slabs.
- Primite neke poruke da napravite rupe i podstaknete adjacency.
- Pokrenite ksmbd OOB više puta dok order-4 stream buffer ne padne odmah pre msg_msg slab-a. Koristite eBPF tracing da potvrdite adrese i alignment ako je dostupno.
Korisna 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
Šta pratiti tokom tuniranja
kvmalloc_node(0x10000)potvrđuje kada ranjivi stream write zaista troši order-4 alokaciju.load_msg/kretprobe:load_msgomogućava procenu koliko jemsg_msgsegalokacija nakačeno na svaku raspršenu poruku, što je korisno pri tuniranju primary/secondary veličina poruka za određeni kernel build.- Ako se exploit portuje na drugi distro/kernel, ponovo proveri cache imena, inline
msg_msgpayload veličine,anon_pipe_buf_opsoffsete i gadget adrese, umesto da pretpostaviš da Ubuntu 22.04 LTS5.15.0-153-generickonstante i dalje odgovaraju.
Plan eksploatacije (msg_msg + pipe_buffer), prilagođen iz CVE-2021-22555
- Rasprši mnogo System V msg_msg primary/secondary poruka (veličine 4KiB da stanu u kmalloc-cg-4k).
- Okini ksmbd OOB da ošteti next pointer primary poruke tako da dve primarne dele jednu sekundarnu.
- Detektuj oštećeni par tagovanjem queue-ova i skeniranjem sa msgrcv(MSG_COPY) da pronađeš neusklađene tagove.
- Oslobodi stvarnu sekundarnu da bi napravio UAF; preuzmi je kontrolisanim podacima preko UNIX sockets (napravi lažnu msg_msg).
- Leak-uj kernel heap pointere zloupotrebom m_ts over-read u copy_msg da dobiješ mlist.next/mlist.prev (SMAP bypass).
- Uz sk_buff spray, rekonstruiši konzistentnu lažnu msg_msg sa validnim linkovima i oslobodi je normalno da stabilizuješ stanje.
- Ponovo preuzmi UAF sa struct pipe_buffer objektima; leak-uj anon_pipe_buf_ops da izračunaš kernel base (defeat KASLR).
- Rasprši lažni pipe_buf_operations sa release koji pokazuje na stack pivot/ROP gadget; zatvori pipe-ove da izvršiš i dobiješ root.
Bypasses and notes
- KASLR: leak-uj anon_pipe_buf_ops, izračunaj base (kbase_addr) i adrese gadgeta.
- SMEP/SMAP: izvrši ROP u kernel kontekstu preko pipe_buf_operations->release toka; izbegavaj userspace deref-ove dok chain ne uradi disable/prepare_kernel_cred/commit_creds.
- Hardened usercopy: nije primenljivo na ovaj page overflow primitive; mete korupcije su polja koja nisu usercopy.
Pouzdanost
- Visoka kada se postigne susednost; povremeni promašaji ili panici (<10%). Tuniranje broja spray/free operacija poboljšava stabilnost. Prepisivanje dva LSB bita pointera da bi se izazvali specifični kolizije prijavljeno je kao efikasno (npr. upiši 0x0000_0000_0000_0500 pattern u overlap).
Ključni parametri za tuniranje
- Broj msg_msg spray-ova i hole pattern
- OOB offset (pos) i rezultujuća OOB dužina (count’)
- Broj UNIX socket, sk_buff i pipe_buffer spray-ova tokom svake faze
Mitigations and reachability
- Ispravka: ograniči i alokaciju i destination/length ili ograniči memcpy prema veličini alokacije; upstream zakrpe su vođene kao CVE-2025-37947.
- Remote exploitation bi dodatno zahtevao pouzdan infoleak i remote heap grooming; ovaj write-up je fokusiran na lokalni LPE.
Vidi i
Ksmbd Attack Surface And Fuzzing Syzkaller
References PoC and tooling
- libsmb2 za SMB auth i streams writes
- eBPF tracer script za logovanje kvmalloc adresa i histogram alokacija (npr. grep 4048 out-4096.txt)
- Minimal reachability PoC i full local exploit su javno dostupni (vidi 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
Nauči i vežbaj AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Nauči i vežbaj GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Nauči i vežbaj Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Pregledaj kompletan HackTricks Training katalog za assessment tracks (ARTA/GRTA/AzRTA) i Linux Hacking Expert (LHE).
Podrži HackTricks
- Pogledaj pretplatničke planove!
- Pridruži se 💬 Discord grupi, telegram grupi, prati @hacktricks_live na X/Twitter, ili pogledaj LinkedIn stranicu i YouTube kanal.
- Deli hacking trikove slanjem PR-ova u HackTricks i HackTricks Cloud github repozitorijume.


