ksmbd streams_xattr OOB write → local LPE (CVE-2025-37947)
Tip
Leer & oefen AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Leer & oefen Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Blaai deur die volledige HackTricks Training-katalogus vir die assesseringsroetes (ARTA/GRTA/AzRTA) en Linux Hacking Expert (LHE).
Ondersteun HackTricks
- Kyk na die intekenplanne!
- Sluit aan by die 💬 Discord-groep, die telegram-groep, volg @hacktricks_live op X/Twitter, of kyk na die LinkedIn-bladsy en YouTube-kanaal.
- Deel hacking tricks deur PRs in te stuur na die HackTricks en HackTricks Cloud github repos.
Hierdie bladsy dokumenteer ’n deterministiese out-of-bounds write in ksmbd streams handling wat ’n betroubare Linux kernel privilege escalation op Ubuntu 22.04 LTS (5.15.0-153-generic) moontlik maak, en KASLR, SMEP, en SMAP omseil deur standaard kernel heap primitives (msg_msg + pipe_buffer) te gebruik.
- Affected component: fs/ksmbd/vfs.c — ksmbd_vfs_stream_write()
- Primitive: page-overflow OOB write verby ’n 0x10000-byte kvmalloc() buffer
- Preconditions: ksmbd wat loop met ’n geverifieerde, writable share wat vfs streams_xattr gebruik
Example smb.conf
[share]
path = /share
vfs objects = streams_xattr
writeable = yes
Wortel oorsaak (allokasie geklamp, memcpy by ongeklampte offset)
- Die funksie bereken size = *pos + count, klamp size na XATTR_SIZE_MAX (0x10000) wanneer dit oorskry word, en herbereken count = (*pos + count) - 0x10000, maar doen steeds memcpy(&stream_buf[*pos], buf, count) in ’n 0x10000-byte buffer. As *pos ≥ 0x10000 is die bestemmingswyser reeds buite die allokasie, wat ’n OOB write van count bytes veroorsaak.
streams_xattrstoor SMB alternate data streams binne POSIX extended attributes, so die 0x10000-plafon kom van die Linux single-xattr-grootte limiet eerder as van ’n SMB-protokolveld. Dit maak die bug prakties net wanneer die share uitdruklikvfs objects = streams_xattraktiveer en die filesystem xattrs ondersteun.
Waarom die write offset saak maak
- Die kwesbare pad is nie net “skryf meer as 64KiB” nie. Die ontbrekende check was dat
*posnie teen die huidige stream length (v_len) gevalideer is voor die append/copy logic geloop het nie. - Upstream het dit reggemaak deur writes te weier waar
*pos >= v_lenmet-EINVAL. Voor die fix kon ’n attacker ’n geldige geverifieerde handle na ’n named stream hergebruik en ’n raw SMB2 WRITE stuur waarvan diefile_offsetreeds na of verby die einde van die bestaande stream wys, wat die post-clampmemcpy()in ’n deterministiese page overflow verander. - Die public PoC demonstreer dit deur te verifieer met
libsmb2, ’n stream path soos1337:oop te maak,SessionId/TreeId/FileIdte onttrek, en dan ’n handgemaakte SMB2 WRITE te stuur metfile_offset = 0x10018en ’n kleinLength.
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
- Example: stel lêer offset (pos) op 0x10018 en oorspronklike lengte (count) op 8. Na clamping, count’ = (0x10018 + 8) - 0x10000 = 0x20, maar memcpy skryf 32 bytes vanaf stream_buf[0x10018], d.w.s. 0x18 bytes verby die 16-page allocation.
Triggering the bug via SMB streams write
- Use the same authenticated SMB connection to open a file on the share and issue a write to a named stream (streams_xattr). Stel file_offset ≥ 0x10000 met ’n klein length om ’n deterministic OOB write van controllable size te genereer.
- libsmb2 kan gebruik word om te authenticate en sulke writes oor SMB2/3 te craft.
- In practice, reusing the negotiated SMB session is convenient because the exploit only needs to patch a few dynamic fields in the WRITE request (
TreeId,SessionId,FileId) and can then transmit the malformed packet directly on the same socket.
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
Toewysersgedrag en waarom page shaping vereis word
- kvmalloc(0x10000, GFP_KERNEL|__GFP_ZERO) versoek ’n order-4 (16 aaneenlopende bladsye) toewysing van die buddy allocator wanneer size > KMALLOC_MAX_CACHE_SIZE. Dit is nie ’n SLUB cache object nie.
- memcpy gebeur onmiddellik ná toewysing; spraying ná toewysing is ondoeltreffend. Jy moet fisiese geheue vooraf groom sodat ’n gekose target direk ná die toegewysde 16-page block lê.
- Op Ubuntu trek GFP_KERNEL dikwels uit die Unmovable migrate type in zone Normal. Put order-3 en order-4 freelists uit om die allocator te dwing om ’n order-5 block in ’n aangrensende order-4 + order-3 pair te split, en parkeer dan ’n order-3 slab (kmalloc-cg-4k) direk ná die stream buffer.
Praktiese page shaping-strategie
- Spray ~1000–2000 msg_msg objects van ~4096 bytes (pas in kmalloc-cg-4k) om order-3 slabs te vul.
- Ontvang sommige messages om gate te maak en adjacency aan te moedig.
- Trigger die ksmbd OOB herhaaldelik totdat die order-4 stream buffer direk voor ’n msg_msg slab land. Gebruik eBPF tracing om addresses en alignment te bevestig indien beskikbaar.
Nuttige waarneembaarheid
# 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
Wat om te trace terwyl jy tun
kvmalloc_node(0x10000)bevestig wanneer die kwesbare stream write werklik ’n order-4 allocation verbruik.load_msg/kretprobe:load_msglaat jou toe om te skat hoeveelmsg_msgsegallocations aan elke gesprayed message geheg is, wat nuttig is wanneer jy primary/secondary message sizes vir ’n spesifieke kernel build tun.- As die exploit na ’n ander distro/kernel gepoort word, kontroleer cache name, inline
msg_msgpayload sizes,anon_pipe_buf_opsoffsets, en gadget addresses weer eerder as om aan te neem dat die Ubuntu 22.04 LTS5.15.0-153-genericconstants steeds ooreenstem.
Exploitation plan (msg_msg + pipe_buffer), aangepas van CVE-2021-22555
- Spray baie System V msg_msg primary/secondary messages (4KiB-sized om by kmalloc-cg-4k te pas).
- Trigger ksmbd OOB om ’n primary message se next pointer te korrupteer sodat twee primaries een secondary deel.
- Detecteer die korrupte paar deur queues te tag en te scan met msgrcv(MSG_COPY) om mismatched tags te vind.
- Free die regte secondary om ’n UAF te skep; reclaim dit met controlled data via UNIX sockets (craft ’n fake msg_msg).
- Leak kernel heap pointers deur m_ts over-read in copy_msg te abuse om mlist.next/mlist.prev te verkry (SMAP bypass).
- Met ’n sk_buff spray, rebuild ’n konsekwente fake msg_msg met geldige links en free dit normaalweg om state te stabiliseer.
- Reclaim die UAF met struct pipe_buffer objects; leak anon_pipe_buf_ops om kernel base te bereken (defeat KASLR).
- Spray ’n fake pipe_buf_operations met release wat na ’n stack pivot/ROP gadget wys; close pipes om uit te voer en root te kry.
Bypasses and notes
- KASLR: leak anon_pipe_buf_ops, bereken base (kbase_addr) en gadget addresses.
- SMEP/SMAP: execute ROP in kernel context via pipe_buf_operations->release flow; vermy userspace derefs totdat ná disable/prepare_kernel_cred/commit_creds chain.
- Hardened usercopy: nie van toepassing op hierdie page overflow primitive nie; corruption targets is non-usercopy fields.
Reliability
- Hoog sodra adjacency verkry is; soms word misses of panics gemis (<10%). Tuning spray/free counts verbeter stabiliteit. Om twee LSBs van ’n pointer te oorskryf om spesifieke collisions te veroorsaak, is gerapporteer as effektief (bv. skryf 0x0000_0000_0000_0500 pattern in die overlap).
Key parameters to tune
- Aantal msg_msg sprays en hole pattern
- OOB offset (pos) en die gevolglike OOB length (count’)
- Aantal UNIX socket, sk_buff, en pipe_buffer sprays tydens elke stage
Mitigations and reachability
- Fix: clamp beide allocation en destination/length of bound memcpy teen die allocated size; upstream patches track as CVE-2025-37947.
- Remote exploitation sou addisioneel ’n betroubare infoleak en remote heap grooming vereis; hierdie write-up fokus op local LPE.
See also
Ksmbd Attack Surface And Fuzzing Syzkaller
References PoC and tooling
- libsmb2 vir SMB auth en streams writes
- eBPF tracer script om kvmalloc addresses te log en allocations te histogram (bv. grep 4048 out-4096.txt)
- Minimal reachability PoC en full local exploit is publiek beskikbaar (sien 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
Leer & oefen AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Leer & oefen Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Blaai deur die volledige HackTricks Training-katalogus vir die assesseringsroetes (ARTA/GRTA/AzRTA) en Linux Hacking Expert (LHE).
Ondersteun HackTricks
- Kyk na die intekenplanne!
- Sluit aan by die 💬 Discord-groep, die telegram-groep, volg @hacktricks_live op X/Twitter, of kyk na die LinkedIn-bladsy en YouTube-kanaal.
- Deel hacking tricks deur PRs in te stuur na die HackTricks en HackTricks Cloud github repos.


