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

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_xattr stoor 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 uitdruklik vfs objects = streams_xattr aktiveer 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 *pos nie 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_len met -EINVAL. Voor die fix kon ’n attacker ’n geldige geverifieerde handle na ’n named stream hergebruik en ’n raw SMB2 WRITE stuur waarvan die file_offset reeds na of verby die einde van die bestaande stream wys, wat die post-clamp memcpy() in ’n deterministiese page overflow verander.
  • Die public PoC demonstreer dit deur te verifieer met libsmb2, ’n stream path soos 1337: oop te maak, SessionId/TreeId/FileId te onttrek, en dan ’n handgemaakte SMB2 WRITE te stuur met file_offset = 0x10018 en ’n klein Length.
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_msg laat jou toe om te skat hoeveel msg_msgseg allocations 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_msg payload sizes, anon_pipe_buf_ops offsets, en gadget addresses weer eerder as om aan te neem dat die Ubuntu 22.04 LTS 5.15.0-153-generic constants steeds ooreenstem.

Exploitation plan (msg_msg + pipe_buffer), aangepas van CVE-2021-22555

  1. Spray baie System V msg_msg primary/secondary messages (4KiB-sized om by kmalloc-cg-4k te pas).
  2. Trigger ksmbd OOB om ’n primary message se next pointer te korrupteer sodat twee primaries een secondary deel.
  3. Detecteer die korrupte paar deur queues te tag en te scan met msgrcv(MSG_COPY) om mismatched tags te vind.
  4. Free die regte secondary om ’n UAF te skep; reclaim dit met controlled data via UNIX sockets (craft ’n fake msg_msg).
  5. Leak kernel heap pointers deur m_ts over-read in copy_msg te abuse om mlist.next/mlist.prev te verkry (SMAP bypass).
  6. Met ’n sk_buff spray, rebuild ’n konsekwente fake msg_msg met geldige links en free dit normaalweg om state te stabiliseer.
  7. Reclaim die UAF met struct pipe_buffer objects; leak anon_pipe_buf_ops om kernel base te bereken (defeat KASLR).
  8. 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

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