ksmbd streams_xattr OOB write → local LPE (CVE-2025-37947)

Reading time: 7 minutes

tip

Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Leer en oefen Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

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, deur KASLR, SMEP en SMAP te omseil met standaard kernel heap primitives (msg_msg + pipe_buffer).

  • Aangedane komponent: fs/ksmbd/vfs.c — ksmbd_vfs_stream_write()
  • Primitiw: page-overflow OOB write verby 'n 0x10000-byte kvmalloc() buffer
  • Voorvereistes: ksmbd loop met 'n geauthentiseerde, skryfbare share wat vfs streams_xattr gebruik

Voorbeeld smb.conf

ini
[share]
path = /share
vfs objects = streams_xattr
writeable = yes

Hoofoorsaak (toewysing beperk, memcpy by onbeperkte offset)

  • Die funksie bereken size = *pos + count, beperk size tot XATTR_SIZE_MAX (0x10000) wanneer dit oorskry word, en herbereken count = (*pos + count) - 0x10000, maar voer steeds memcpy(&stream_buf[*pos], buf, count) uit na 'n 0x10000-byte buffer. As *pos ≥ 0x10000 is die bestemmingswyser reeds buite die toewysing, wat 'n OOB write van count bytes veroorsaak.
Kwetsbare funksiefragment (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

  • Voorbeeld: stel file offset (pos) op 0x10018 en oorspronklike lengte (count) op 8. Na begrensing word count' = (0x10018 + 8) - 0x10000 = 0x20, maar memcpy skryf 32 bytes begin by stream_buf[0x10018], d.w.s. 0x18 bytes buite die 16-bladsy toewysing.

Triggering the bug via SMB streams write

  • Gebruik dieselfde geverifieerde SMB-verbinding om 'n file op die share oop te maak en 'n write na 'n benoemde stream (streams_xattr) uit te voer. Stel file_offset ≥ 0x10000 met 'n klein lengte om 'n deterministiese OOB write van beheerbare grootte te genereer.
  • libsmb2 kan gebruik word om te autentiseer en sulke writes oor SMB2/3 te vervaardig.

Minimal reachability (concept)

c
// 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

Gedrag van die allocator en waarom page shaping vereis word

  • kvmalloc(0x10000, GFP_KERNEL|__GFP_ZERO) requests an order-4 (16 contiguous pages) allocation from the buddy allocator when size > KMALLOC_MAX_CACHE_SIZE. This is not a SLUB cache object.
  • memcpy occurs immediately after allocation; post-allocation spraying is ineffective. Jy moet die fisiese geheue vooraf pre-groom sodat 'n gekose target direk ná die toegewezen 16-page blok lê.
  • On Ubuntu, GFP_KERNEL often pulls from the Unmovable migrate type in zone Normal. Exhaust order-3 and order-4 freelists to force the allocator to split an order-5 block into an adjacent order-4 + order-3 pair, then park an order-3 slab (kmalloc-cg-4k) directly after the stream buffer.

Practical page shaping strategy

  • Spray ~1000–2000 msg_msg objects of ~4096 bytes (fits kmalloc-cg-4k) to populate order-3 slabs.
  • Receive some messages to punch holes and encourage adjacency.
  • Trigger the ksmbd OOB repeatedly until the order-4 stream buffer lands immediately before a msg_msg slab. Use eBPF tracing to confirm addresses and alignment if available.

Useful observability

bash
# 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

Uitbuitingsplan (msg_msg + pipe_buffer), aangepas vanaf CVE-2021-22555

  1. Spray baie System V msg_msg primary/secondary messages (4KiB-groot om in kmalloc-cg-4k te pas).
  2. Trigger ksmbd OOB om 'n primêre boodskap se next-pointer te korrupteer sodat twee primaries een secondary deel.
  3. Detecteer die gekorrupteerde paar deur queues te tag en te skandeer met msgrcv(MSG_COPY) om wanpassende tags te vind.
  4. Free die werklike secondary om 'n UAF te skep; herwin dit met beheerde data via UNIX sockets (craft 'n fake msg_msg).
  5. Leak kernel heap pointers deur misbruik van m_ts over-read in copy_msg om mlist.next/mlist.prev te bekom (SMAP bypass).
  6. Met 'n sk_buff spray, herbou 'n konsekwente fake msg_msg met geldige links en free dit normaalweg om toestand te stabiliseer.
  7. Herwin die UAF met struct pipe_buffer-objekte; leak anon_pipe_buf_ops om kernel base te bereken (verslaan 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 verkry.

Omseilings en notas

  • KASLR: leak anon_pipe_buf_ops, bereken base (kbase_addr) en gadget-adresse.
  • SMEP/SMAP: execute ROP in kernel-konteks via pipe_buf_operations->release-stroom; vermy userspace derefs totdat disable/prepare_kernel_cred/commit_creds-ketting voltooi is.
  • Hardened usercopy: nie van toepassing op hierdie page overflow-primitive nie; korrupsie rig op nie-usercopy-velde.

Betroubaarheid

  • Hoog sodra adjacency bereik is; af en toe mislukke of panics (<10%). Afstemming van spray/free-aantalle verbeter stabiliteit. Oorskryf van twee LSBs van 'n pointer om spesifieke botsings te veroorsaak is gerapporteer as effektief (bv. skryf 0x0000_0000_0000_0500 patroon in die overlap).

Sleutelparameters om af te stel

  • Aantal msg_msg sprays en gatpatroon
  • OOB offset (pos) en resulterende OOB-lengte (count')
  • Aantal UNIX socket, sk_buff, en pipe_buffer sprays tydens elke fase

Mitigasies en bereikbaarheid

  • Fix: clamp beide toewysing en bestemming/lengte of begrens memcpy teen die toegewezen grootte; upstream patches track as CVE-2025-37947.
  • Remote exploitation sou verder 'n betroubare infoleak en remote heap grooming vereis; hierdie uiteensetting fokus op lokale LPE.

Verwysings PoC en gereedskap

  • libsmb2 for SMB auth and streams writes
  • eBPF tracer script om kvmalloc addresses en histogram allocations te log (bv. grep 4048 out-4096.txt)
  • Minimal reachability PoC en full local exploit is publicly available (sien References)

References

tip

Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Leer en oefen Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Ondersteun HackTricks