ksmbd streams_xattr OOB write → local LPE (CVE-2025-37947)
Tip
Aprende y practica AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Revisa el catálogo completo de HackTricks Training para las rutas de evaluación (ARTA/GRTA/AzRTA) y Linux Hacking Expert (LHE).
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord, al grupo de telegram, sigue @hacktricks_live en X/Twitter, o revisa la página de LinkedIn y el canal de YouTube.
- Comparte hacking tricks enviando PRs a los repositorios de github HackTricks y HackTricks Cloud.
Esta página documenta una escritura determinista fuera de límites en el manejo de streams de ksmbd que permite una escalada de privilegios fiable en el kernel de Linux en Ubuntu 22.04 LTS (5.15.0-153-generic), eludiendo KASLR, SMEP y SMAP usando primitivas estándar de heap del kernel (msg_msg + pipe_buffer).
- Componente afectado: fs/ksmbd/vfs.c — ksmbd_vfs_stream_write()
- Primitive: page-overflow OOB write más allá de un buffer kvmalloc() de 0x10000 bytes
- Preconditions: ksmbd ejecutándose con un share autenticado y escribible usando vfs streams_xattr
Example smb.conf
[share]
path = /share
vfs objects = streams_xattr
writeable = yes
Root cause (allocation clamped, memcpy at unclamped offset)
- La función calcula size = *pos + count, lo limita a XATTR_SIZE_MAX (0x10000) cuando se excede, y vuelve a calcular count = (*pos + count) - 0x10000, pero aun así realiza
memcpy(&stream_buf[*pos], buf, count)dentro de un buffer de 0x10000 bytes. Si *pos ≥ 0x10000, el puntero de destino ya está fuera de la asignación, produciendo una escritura OOB de count bytes. streams_xattralmacena SMB alternate data streams dentro de POSIX extended attributes, así que el límite de 0x10000 proviene del límite de tamaño de un único xattr en Linux y no de un campo del protocolo SMB. Eso hace que el bug sea práctico solo cuando el share habilita explícitamentevfs objects = streams_xattry el filesystem soporta xattrs.
Why the write offset matters
- La ruta vulnerable no es solo “escribir más de 64KiB”. La comprobación que faltaba era que
*posno se validaba contra la longitud actual del stream (v_len) antes de que se ejecutara la lógica de append/copy. - Upstream corrigió esto rechazando escrituras donde
*pos >= v_lencon-EINVAL. Antes del fix, un atacante podía reutilizar un handle autenticado válido a un named stream y enviar un SMB2 WRITE bruto cuyofile_offsetya apunta al final o más allá del stream existente, lo que convierte elmemcpy()posterior al clamp en un desbordamiento de página determinista. - El PoC público lo demuestra autenticándose con
libsmb2, abriendo una ruta de stream como1337:, extrayendoSessionId/TreeId/FileId, y luego enviando un SMB2 WRITE construido a mano confile_offset = 0x10018y unLengthpequeño.
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
- Ejemplo: establece el file offset (pos) en 0x10018 y la longitud original (count) en 8. Después del clamping, count’ = (0x10018 + 8) - 0x10000 = 0x20, pero memcpy escribe 32 bytes comenzando en stream_buf[0x10018], es decir, 0x18 bytes más allá de la asignación de 16 páginas.
Triggering the bug via SMB streams write
- Usa la misma conexión SMB autenticada para abrir un archivo en el share e iniciar una escritura a un named stream (streams_xattr). Establece file_offset ≥ 0x10000 con una longitud pequeña para generar un OOB write determinista de tamaño controlable.
- libsmb2 puede usarse para autenticar y construir esas escrituras sobre SMB2/3.
- En la práctica, reutilizar la sesión SMB negociada es conveniente porque el exploit solo necesita parchear unos pocos campos dinámicos en la solicitud WRITE (
TreeId,SessionId,FileId) y luego puede transmitir el paquete malformado directamente en el mismo 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
Comportamiento del allocator y por qué se requiere page shaping
- kvmalloc(0x10000, GFP_KERNEL|__GFP_ZERO) solicita una asignación de order-4 (16 páginas contiguas) del buddy allocator cuando size > KMALLOC_MAX_CACHE_SIZE. Esto no es un objeto de SLUB cache.
- memcpy ocurre inmediatamente después de la asignación; el spraying post-asignación es inefectivo. Debes pre-groom la memoria física para que un target elegido quede inmediatamente después del bloque asignado de 16 páginas.
- En Ubuntu, GFP_KERNEL a menudo toma del tipo de migración Unmovable en zone Normal. Agota las freelists de order-3 y order-4 para forzar al allocator a dividir un bloque de order-5 en un par adyacente order-4 + order-3, y luego estaciona un slab de order-3 (kmalloc-cg-4k) directamente después del stream buffer.
Estrategia práctica de page shaping
- Haz spray de ~1000–2000 objetos msg_msg de ~4096 bytes (encaja en kmalloc-cg-4k) para poblar slabs de order-3.
- Recibe algunos mensajes para abrir holes y fomentar la adjacency.
- Dispara el ksmbd OOB repetidamente hasta que el stream buffer de order-4 caiga inmediatamente antes de un msg_msg slab. Usa eBPF tracing para confirmar addresses y alignment si está disponible.
Observabilidad útil
# 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
Qué rastrear al ajustar
kvmalloc_node(0x10000)confirma cuándo la escritura vulnerable de stream realmente consume una asignación de order-4.load_msg/kretprobe:load_msgte permite estimar cuántas asignacionesmsg_msgsegse adjuntan a cada mensaje sprayed, lo cual es útil al ajustar los tamaños de los mensajes primary/secondary para una build concreta del kernel.- Si el exploit se porta a otra distro/kernel, vuelve a comprobar los nombres de cache, los tamaños inline del payload
msg_msg, los offsets deanon_pipe_buf_opsy las direcciones de gadgets en lugar de asumir que las constantes de Ubuntu 22.04 LTS5.15.0-153-genericsiguen coincidiendo.
Plan de explotación (msg_msg + pipe_buffer), adaptado de CVE-2021-22555
- Haz spray de muchos mensajes msg_msg de System V primary/secondary (de tamaño 4KiB para encajar en kmalloc-cg-4k).
- Dispara el OOB de ksmbd para corromper el puntero next de un mensaje primary de modo que dos primaries compartan un secondary.
- Detecta el par corrompido etiquetando colas y escaneando con msgrcv(MSG_COPY) para encontrar tags que no coinciden.
- Libera el secondary real para crear un UAF; recupéralo con datos controlados vía sockets UNIX (forja un msg_msg falso).
- Filtra punteros de kernel heap abusando del m_ts over-read en copy_msg para obtener mlist.next/mlist.prev (bypass de SMAP).
- Con un spray de sk_buff, reconstruye un msg_msg falso consistente con enlaces válidos y libéralo normalmente para estabilizar el estado.
- Recupera el UAF con objetos struct pipe_buffer; filtra anon_pipe_buf_ops para calcular la base del kernel (derrota KASLR).
- Haz spray de un fake pipe_buf_operations con release apuntando a un stack pivot/ROP gadget; cierra las pipes para ejecutar y obtener root.
Bypasses y notas
- KASLR: filtra anon_pipe_buf_ops, calcula la base (kbase_addr) y las direcciones de gadgets.
- SMEP/SMAP: ejecuta ROP en contexto del kernel mediante el flujo pipe_buf_operations->release; evita dereferencias a userspace hasta después de la cadena disable/prepare_kernel_cred/commit_creds.
- Hardened usercopy: no aplica a este primitive de desbordamiento de página; los objetivos de la corrupción son campos que no son de usercopy.
Confiabilidad
- Alta una vez que se logra la adyacencia; fallos o panics ocasionales (<10%). Ajustar los conteos de spray/liberación mejora la estabilidad. Se informó que sobrescribir los 2 LSB de un puntero para inducir colisiones específicas era efectivo (por ejemplo, escribir el patrón 0x0000_0000_0000_0500 en el overlap).
Parámetros clave a ajustar
- Número de sprays de msg_msg y patrón de agujeros
- Offset OOB (pos) y la longitud OOB resultante (count’)
- Número de sprays de sockets UNIX, sk_buff y pipe_buffer durante cada etapa
Mitigaciones y alcance
- Fix: limita tanto la asignación como el destino/longitud o acota memcpy contra el tamaño asignado; los patches upstream se rastrean como CVE-2025-37947.
- La explotación remota además requeriría un infoleak fiable y heap grooming remoto; este write-up se centra en local LPE.
Ver también
Ksmbd Attack Surface And Fuzzing Syzkaller
PoC y tooling de referencias
- libsmb2 para autenticación SMB y escrituras de streams
- script tracer de eBPF para registrar direcciones de kvmalloc y hacer histogramas de asignaciones (por ejemplo, grep 4048 out-4096.txt)
- Hay disponibles públicamente un PoC mínimo de reachability y un exploit local completo (ver 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
Aprende y practica AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Revisa el catálogo completo de HackTricks Training para las rutas de evaluación (ARTA/GRTA/AzRTA) y Linux Hacking Expert (LHE).
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord, al grupo de telegram, sigue @hacktricks_live en X/Twitter, o revisa la página de LinkedIn y el canal de YouTube.
- Comparte hacking tricks enviando PRs a los repositorios de github HackTricks y HackTricks Cloud.


