ksmbd streams_xattr OOB write → local LPE (CVE-2025-37947)
Reading time: 7 minutes
tip
Učite i vežbajte AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking:
HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
Ova stranica dokumentuje deterministički out-of-bounds write u rukovanju ksmbd streams koji omogućava pouzdan Linux kernel privilege escalation na Ubuntu 22.04 LTS (5.15.0-153-generic), zaobilazeći KASLR, SMEP i SMAP koristeći standardne kernel heap primitive (msg_msg + pipe_buffer).
- Pogođena komponenta: fs/ksmbd/vfs.c — ksmbd_vfs_stream_write()
- Primitiv: page-overflow OOB write koji prelazi 0x10000-byte kvmalloc() buffer
- Preduslovi: ksmbd koji radi sa autentifikovanim, zapisivim deljenjem koristeći vfs streams_xattr
Primer smb.conf
[share]
path = /share
vfs objects = streams_xattr
writeable = yes
Osnovni uzrok (alokacija ograničena, memcpy na neograničenom offsetu)
- Funkcija izračunava size = *pos + count, ograničava size na XATTR_SIZE_MAX (0x10000) kada je premašena, i ponovo izračunava count = (*pos + count) - 0x10000, ali i dalje poziva memcpy(&stream_buf[*pos], buf, count) u bafer veličine 0x10000 bajtova. Ako je *pos ≥ 0x10000, destinacioni pokazivač je već izvan alokacije, što dovodi do OOB write od count bajtova.
Ranljiv isječak funkcije (ksmbd_vfs_stream_write)
// 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;
}
Usmeravanje ofseta i OOB dužine
- Primer: set file offset (pos) na 0x10018 i original length (count) na 8. Nakon ograničavanja (clamping), count' = (0x10018 + 8) - 0x10000 = 0x20, ali memcpy upisuje 32 bajta počevši od stream_buf[0x10018], tj. 0x18 bajta izvan alokacije od 16 stranica.
Okidanje buga putem SMB streams write
- Koristite istu autentifikovanu SMB konekciju da otvorite fajl na share-u i izvršite write u imenovani stream (streams_xattr). Set file_offset ≥ 0x10000 sa malom dužinom kako biste generisali deterministički OOB write kontrolisane veličine.
- libsmb2 može biti korišćen za autentifikaciju i kreiranje takvih write-ova preko SMB2/3.
Minimalna dohvatljivost (koncept)
// 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
Ponašanje alokatora i zašto je page shaping neophodan
- 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.
- 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.
Praktična page shaping strategija
- Spray ~1000–2000 msg_msg objekata od ~4096 bajtova (fits kmalloc-cg-4k) da popunite order-3 slab-ove.
- 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.
Korisna observabilnost
# 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
Plan iskorišćavanja (msg_msg + pipe_buffer), prilagođeno iz CVE-2021-22555
- Spray many System V msg_msg primary/secondary messages (4KiB-sized to fit kmalloc-cg-4k).
- Trigger ksmbd OOB da korumpira primary message-ov next pointer tako da dve primaries dele jedan secondary.
- Detektovati korumpirani par tagovanjem queue-ova i skeniranjem sa msgrcv(MSG_COPY) da se pronađu mismatched tags.
- Free-ovati real secondary da se stvori UAF; reclaim-ovati ga kontrolisanim podacima preko UNIX sockets (craft a fake msg_msg).
- Leak kernel heap pointers zloupotrebom m_ts over-read u copy_msg da se dobiju mlist.next/mlist.prev (SMAP bypass).
- Sa sk_buff spray-om, rebuild-ovati konzistentan fake msg_msg sa valid links i free-ovati ga normalno da se stabilizuje stanje.
- Reclaim-ovati UAF sa struct pipe_buffer objektima; leak-ovati anon_pipe_buf_ops da se izračuna kernel base (defeat KASLR).
- Spray-ovati fake pipe_buf_operations sa release koji pokazuje na stack pivot/ROP gadget; close pipes da se izvrši i dobije root.
Zaobiđanja i napomene
- KASLR: leak anon_pipe_buf_ops, compute base (kbase_addr) i adrese gedžeta.
- SMEP/SMAP: execute ROP u kernel kontekstu preko pipe_buf_operations->release toka; izbegavati userspace deref-ove dok se ne izvrši disable/prepare_kernel_cred/commit_creds lanac.
- Hardened usercopy: ne primenjuje se na ovaj page overflow primitive; korupcija cilja non-usercopy fields.
Pouzdanost
- Visoko kada je adjacency postignuta; povremeni promašaji ili panici (<10%). Podešavanje spray/free brojeva poboljšava stabilnost. Overwriting dva LSB-a pokazivača da bi se izazvale specifične kolizije prijavljeno je kao efikasno (npr. pisanje 0x0000_0000_0000_0500 pattern-a u overlap).
Ključni parametri za podešavanje
- Broj msg_msg spray-ova i obrazac rupa
- OOB offset (pos) i rezultujuća OOB dužina (count')
- Broj UNIX socket, sk_buff i pipe_buffer spray-ova tokom svake faze
Mitigacije i mogućnost iskorišćavanja
- Fix: clamp-ovati i allocation i destination/length ili bound memcpy protiv alocirane veličine; upstream zakrpe prate se kao CVE-2025-37947.
- Remote exploitation bi dodatno zahtevao reliable infoleak i remote heap grooming; ovaj write-up se fokusira na local LPE.
References PoC i 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)
References
- 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
Učite i vežbajte AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking:
HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
HackTricks