ksmbd streams_xattr OOB write → LPE locale (CVE-2025-37947)
Tip
Impara e pratica il hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.
Questa pagina documenta una scrittura deterministica out-of-bounds nella gestione dei streams di ksmbd che permette un affidabile privilege escalation del kernel Linux su Ubuntu 22.04 LTS (5.15.0-153-generic), bypassando KASLR, SMEP e SMAP usando primitive standard dell’heap del kernel (msg_msg + pipe_buffer).
- Componente interessato: fs/ksmbd/vfs.c — ksmbd_vfs_stream_write()
- Primitiva: page-overflow OOB write past a 0x10000-byte kvmalloc() buffer
- Prerequisiti: ksmbd in esecuzione con una condivisione autenticata e scrivibile che usa vfs streams_xattr
Esempio smb.conf
[share]
path = /share
vfs objects = streams_xattr
writeable = yes
Causa principale (allocation clamped, memcpy at unclamped offset)
- La funzione calcola size = *pos + count, clampa size a XATTR_SIZE_MAX (0x10000) quando viene superato, e ricalcola count = (*pos + count) - 0x10000, ma esegue comunque memcpy(&stream_buf[*pos], buf, count) in un buffer di 0x10000-byte. Se *pos ≥ 0x10000 il puntatore di destinazione è già fuori dall’allocazione, producendo una OOB write di count bytes.
Snippet della funzione vulnerabile (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 e OOB length
- Esempio: impostare file offset (pos) a 0x10018 e original length (count) a 8. Dopo il clamping, count’ = (0x10018 + 8) - 0x10000 = 0x20, ma memcpy scrive 32 byte a partire da stream_buf[0x10018], cioè 0x18 byte oltre l’allocazione di 16 pagine.
Triggering the bug via SMB streams write
- Usa la stessa connessione SMB autenticata per aprire un file sulla share e effettuare una write a uno stream nominato (streams_xattr). Imposta file_offset ≥ 0x10000 con una lunghezza piccola per generare una OOB write deterministica di dimensione controllabile.
- libsmb2 può essere usato per autenticare e craftare tali write su SMB2/3.
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
Comportamento dell’allocatore e perché è necessario il page shaping
- 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. You must pre-groom physical memory so that a chosen target lies immediately after the allocated 16-page block.
- Su Ubuntu, GFP_KERNEL spesso attinge dal migrate type Unmovable nella zone Normal. Esaurisci le freelists di order-3 e order-4 per forzare l’allocatore a split un blocco order-5 in una coppia adiacente order-4 + order-3, poi parcheggia uno slab order-3 (kmalloc-cg-4k) direttamente dopo lo stream buffer.
Practical page shaping strategy
- Spray ~1000–2000 msg_msg objects of ~4096 bytes (fits kmalloc-cg-4k) per popolare gli slab order-3.
- Ricevi alcuni messaggi per punch holes e favorire l’adiacenza.
- Trigger the ksmbd OOB repeatedly fino a quando lo stream buffer order-4 non si posiziona immediatamente prima di uno slab msg_msg. Usa eBPF tracing per confermare indirizzi e allineamento se disponibile.
Useful 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
Piano di sfruttamento (msg_msg + pipe_buffer), adattato da CVE-2021-22555
- Eseguire uno spray di numerosi messaggi System V msg_msg primary/secondary (4KiB per adattarsi a kmalloc-cg-4k).
- Triggerare ksmbd OOB per corrompere il puntatore next di un primary in modo che due primaries condividano una sola secondary.
- Rilevare la coppia corrotta taggando le code e scandendo con msgrcv(MSG_COPY) per trovare tag non corrispondenti.
- Liberare la secondary reale per creare una UAF; riconquistarla con dati controllati via UNIX sockets (craft a fake msg_msg).
- Leak kernel heap pointers abusando di un over-read di m_ts in copy_msg per ottenere mlist.next/mlist.prev (SMAP bypass).
- Con uno spray di sk_buff, ricostruire un fake msg_msg consistente con link validi e rilasciarlo normalmente per stabilizzare lo stato.
- Riconquistare la UAF con oggetti struct pipe_buffer; leak anon_pipe_buf_ops per calcolare il kernel base (sconfiggere KASLR).
- Spruzzare un fake pipe_buf_operations con release che punta a uno stack pivot/gadget ROP; chiudere le pipe per eseguire e ottenere root.
Bypass e note
- KASLR: leak anon_pipe_buf_ops, calcolare base (kbase_addr) e indirizzi gadget.
- SMEP/SMAP: eseguire ROP in kernel context tramite il flusso pipe_buf_operations->release; evitare deref in userspace fino a dopo la catena disable/prepare_kernel_cred/commit_creds.
- Hardened usercopy: non applicabile a questo primitive di page overflow; i campi corrotti non sono usercopy.
Affidabilità
- Alta una volta ottenuta l’adjacency; occasionali fallimenti o panic (<10%). Tuning dei conteggi di spray/free migliora la stabilità. È stato riportato efficace sovrascrivere due LSB di un puntatore per indurre collisioni specifiche (es., scrivere il pattern 0x0000_0000_0000_0500 nell’overlap).
Parametri chiave da tarare
- Numero di spray di msg_msg e pattern dei buchi
- OOB offset (pos) e conseguente lunghezza OOB (count’)
- Numero di spray di UNIX socket, sk_buff e pipe_buffer in ogni fase
Mitigazioni e raggiungibilità
- Fix: clampare sia l’allocazione che destination/length o limitare memcpy contro la dimensione allocata; le patch upstream sono tracciate come CVE-2025-37947.
- L’exploitation remota richiederebbe inoltre un infoleak affidabile e remote heap grooming; questa descrizione si concentra su LPE locale.
Riferimenti PoC e tooling
- libsmb2 for SMB auth and streams writes
- eBPF tracer script to log kvmalloc addresses and histogram allocations (e.g., grep 4048 out-4096.txt)
- Minimal reachability PoC and full local exploit are publicly available (see References)
Riferimenti
- ksmbd - Exploiting CVE-2025-37947 (3/3) — Doyensec
- libsmb2
- KSMBD-CVE-2025-37947: proof-of-concept.c
- KSMBD-CVE-2025-37947: CVE-2025-37947.c (full exploit)
- bpf-tracer.sh
Tip
Impara e pratica il hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.
HackTricks

