ksmbd streams_xattr OOB write → local LPE (CVE-2025-37947)
Tip
AWS Hacking’i öğrenin ve pratik yapın:
HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın:HackTricks Training GCP Red Team Expert (GRTE)
Azure Hacking’i öğrenin ve pratik yapın:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter’da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.
Bu sayfa, ksmbd streams işlemesi sırasında ortaya çıkan deterministik bir out-of-bounds write’i belgeliyor; bu zafiyet, Ubuntu 22.04 LTS (5.15.0-153-generic) üzerinde güvenilir bir Linux kernel privilege escalation’e olanak tanıyor ve standart kernel heap primitives (msg_msg + pipe_buffer) kullanarak KASLR, SMEP ve SMAP’i atlatıyor.
- Etkilenen bileşen: fs/ksmbd/vfs.c — ksmbd_vfs_stream_write()
- Primitif: page-overflow OOB write past a 0x10000-byte kvmalloc() buffer
- Önkoşullar: ksmbd, vfs streams_xattr kullanan kimlik doğrulamalı, yazılabilir bir paylaşım ile çalışıyor
Example smb.conf
[share]
path = /share
vfs objects = streams_xattr
writeable = yes
Kök neden (ayırma sınırlandırıldı, memcpy sınırlandırılmamış offset’te)
- Fonksiyon size = *pos + count hesaplıyor, aşılması durumunda size’ı XATTR_SIZE_MAX (0x10000) ile sınırlıyor ve count’u count = (*pos + count) - 0x10000 olarak yeniden hesaplıyor, ancak yine de memcpy(&stream_buf[*pos], buf, count) işlemini 0x10000 baytlık bir buffer içine yapıyor. Eğer *pos ≥ 0x10000 ise hedef işaretçi zaten ayrmanın dışında olur ve count baytlık bir OOB write oluşur.
Zafiyetli fonksiyon kesiti (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 ve OOB uzunluğu
- Örnek: set file offset (pos) to 0x10018 and original length (count) to 8. After clamping, count’ = (0x10018 + 8) - 0x10000 = 0x20, but memcpy writes 32 bytes starting at stream_buf[0x10018], i.e., 0x18 bytes beyond the 16-page allocation.
Triggering the bug via SMB streams write
- Aynı kimlik doğrulanmış SMB bağlantısını kullanarak paylaşımda bir dosya açın ve named stream (streams_xattr) için bir write gerçekleştirin. file_offset ≥ 0x10000 olacak şekilde ve küçük bir length belirleyin; böylece kontrol edilebilir boyutta deterministik bir OOB write oluşturulur.
- libsmb2, SMB2/3 üzerinden kimlik doğrulama ve bu tür write’ları oluşturmak için kullanılabilir.
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
Allocator behavior and why page shaping is required
- 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.
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.
Kullanışlı gözlemlenebilirlik
# 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
İstismar planı (msg_msg + pipe_buffer), CVE-2021-22555’ten uyarlanmıştır
- Çok sayıda System V msg_msg birincil/ikincil mesaj spray (4KiB boyutunda, kmalloc-cg-4k’ye sığacak şekilde).
- ksmbd OOB tetikleyerek bir birincil mesajın next işaretçisini bozuk hale getir, böylece iki birincil bir ikinciliği paylaşsın.
- Kuyrukları etiketleyip msgrcv(MSG_COPY) ile tarayarak bozulmuş çifti tespit et ve uyumsuz etiketleri bul.
- Gerçek ikinciliği free ederek bir UAF oluştur; UNIX sockets üzerinden kontrollü verilerle yeniden ele geçir (sahte bir msg_msg oluştur).
- copy_msg’deki m_ts aşırı okumasını suistimal ederek mlist.next/mlist.prev elde edip kernel heap pointer’larını leak et (SMAP bypass).
- sk_buff ile spray yaparak, geçerli bağlantılara sahip tutarlı bir sahte msg_msg yeniden oluştur ve durumu stabilize etmek için normal şekilde free et.
- UAF’ı struct pipe_buffer nesneleriyle yeniden ele geçir; anon_pipe_buf_ops leak ederek kernel base’i hesapla (KASLR’ı yen).
- release’i bir stack pivot/ROP gadget’ına işaret eden sahte bir pipe_buf_operations spray yap; pipe’ları kapatarak yürüt ve root elde et.
Atlatmalar ve notlar
- KASLR: anon_pipe_buf_ops leak et, base (kbase_addr) ve gadget adreslerini hesapla.
- SMEP/SMAP: ROP’u kernel bağlamında pipe_buf_operations->release akışı üzerinden yürüt; userspace deref’lerinden disable/prepare_kernel_cred/commit_creds zincirinden önce kaçın.
- Hardened usercopy: bu page overflow primitive’i için uygulanamaz; bozulma hedefleri non-usercopy alanlardır.
Güvenilirlik
- Adjacency sağlandığında yüksek; ara sıra kaçırmalar veya panikler (<%10). Spray/free sayılarını ayarlamak stabiliteyi artırır. Belirli çarpışmaları tetiklemek için bir pointer’ın iki LSB’sini overwrite etmek etkili olduğu bildirildi (ör. overlap’e 0x0000_0000_0000_0500 desenini yazmak).
Ayarlanacak ana parametreler
- msg_msg spray sayısı ve hole deseni
- OOB offset (pos) ve ortaya çıkan OOB uzunluğu (count’)
- Her aşamada yapılacak UNIX socket, sk_buff ve pipe_buffer spray sayısı
Mitigasyonlar ve erişilebilirlik
- Fix: hem allocation’u hem de destination/length’i sınırlayın veya memcpy’yi ayrılan boyuta karşı bağlayın; upstream yamalar CVE-2025-37947 olarak takip edilir.
- Remote exploitation ek olarak güvenilir bir infoleak ve uzak heap grooming gerektirir; bu yazı yerel LPE’ye odaklanır.
References PoC and 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
AWS Hacking’i öğrenin ve pratik yapın:
HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın:HackTricks Training GCP Red Team Expert (GRTE)
Azure Hacking’i öğrenin ve pratik yapın:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter’da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.
HackTricks

