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

Reading time: 7 minutes

tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें

यह पृष्ठ ksmbd streams हैंडलिंग में एक deterministic out-of-bounds write का दस्तावेज़ है जो Ubuntu 22.04 LTS (5.15.0-153-generic) पर एक विश्वसनीय Linux kernel privilege escalation को सक्षम बनाता है, और मानक kernel heap primitives (msg_msg + pipe_buffer) का उपयोग करके KASLR, SMEP, और SMAP को बायपास करता है।

  • प्रभावित घटक: fs/ksmbd/vfs.c — ksmbd_vfs_stream_write()
  • Primitive: page-overflow OOB write past a 0x10000-byte kvmalloc() buffer
  • पूर्वशर्तें: ksmbd vfs streams_xattr का उपयोग करने वाले एक authenticated, writable share के साथ चल रहा होना

उदाहरण smb.conf

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

मूल कारण (आवंटन क्लैंप किया गया, अनक्लैंप्ड ऑफ़सेट पर memcpy)

  • फंक्शन size = *pos + count की गणना करता है, जब यह XATTR_SIZE_MAX (0x10000) से अधिक होता है तो size को क्लैंप कर देता है, और फिर count = (*pos + count) - 0x10000 फिर से गणना करता है, लेकिन फिर भी memcpy(&stream_buf[*pos], buf, count) को 0x10000-बाइट के बफ़र में करता है। यदि *pos ≥ 0x10000 है तो डेस्टिनेशन पॉइंटर पहले से ही आवंटन के बाहर होगा, जिससे count बाइट्स का OOB write होता है।
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

  • उदाहरण: फाइल offset (pos) को 0x10018 पर और मूल लंबाई (count) को 8 पर सेट करें। क्लैंपिंग के बाद, count' = (0x10018 + 8) - 0x10000 = 0x20, लेकिन memcpy 32 bytes stream_buf[0x10018] से लिखता है, यानी 16-page allocation से 0x18 bytes बाहर।

Triggering the bug via SMB streams write

  • इसी authenticated SMB connection का उपयोग करके share पर फाइल खोलें और एक नामांकित stream (streams_xattr) में write जारी करें। file_offset ≥ 0x10000 और छोटी length सेट करें ताकि नियंत्रित आकार का deterministic OOB write जनरेट हो।
  • libsmb2 का उपयोग ऐसे writes को authenticate और craft करने के लिए SMB2/3 पर किया जा सकता है।

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

Allocator व्यवहार और 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. यह SLUB cache object नहीं है।
  • memcpy allocation के तुरंत बाद होता है; post-allocation spraying प्रभावहीन है। आपको physical memory को पहले से groom करना होगा ताकि चुना गया target allocated 16-page block के तुरंत बाद स्थित हो।
  • On Ubuntu, GFP_KERNEL अक्सर zone Normal के Unmovable migrate type से memory लेता है। order-3 और order-4 freelists को खाली करें ताकि allocator एक order-5 block को पास-पास वाले order-4 + order-3 जोड़े में विभाजित करने के लिए मजबूर हो, फिर stream buffer के ठीक बाद सीधे एक order-3 slab (kmalloc-cg-4k) पार्क करें।

Practical page shaping strategy

  • Spray ~1000–2000 msg_msg objects of ~4096 bytes (fits kmalloc-cg-4k) ताकि order-3 slabs populated हों।
  • कुछ messages प्राप्त करें ताकि holes बने और adjacency को बढ़ावा मिले।
  • ksmbd OOB को बार-बार Trigger करें जब तक order-4 stream buffer एक msg_msg slab के ठीक पहले न आ जाए। उपलब्ध होने पर पते और संरेखण की पुष्टि करने के लिए eBPF tracing का उपयोग करें।

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

Exploitation plan (msg_msg + pipe_buffer), adapted from CVE-2021-22555

  1. कई System V msg_msg primary/secondary संदेश स्प्रे करें (4KiB-साइज़ ताकि kmalloc-cg-4k में फिट हो).
  2. ksmbd OOB ट्रिगर करके एक primary message के next pointer को करप्ट करें ताकि दो primaries एक secondary साझा करें.
  3. टैग करके और msgrcv(MSG_COPY) के साथ स्कैन करके करप्टेड पेयर का पता लगाएं ताकि mismatched टैग मिले.
  4. असली secondary को free करके UAF बनाएं; UNIX sockets के माध्यम से नियंत्रित डेटा के साथ इसे reclaim करें (एक fake msg_msg तैयार करें).
  5. copy_msg में m_ts over-read का दुरुपयोग करके kernel heap pointers को leak करें ताकि mlist.next/mlist.prev प्राप्त हों (SMAP bypass).
  6. sk_buff स्प्रे के साथ, मान्य लिंक के साथ एक सुसंगत fake msg_msg फिर से बनाएँ और स्थिति को स्थिर करने के लिए इसे सामान्य रूप से free करें.
  7. struct pipe_buffer objects के साथ UAF को reclaim करें; anon_pipe_buf_ops को leak करके kernel base (KASLR को मात) गणना करें.
  8. release को stack pivot/ROP gadget की ओर पॉइंट करने वाले fake pipe_buf_operations स्प्रे करें; pipes को बंद करके execute कराएं और root प्राप्त करें.

Bypasses and notes

  • KASLR: leak anon_pipe_buf_ops, base (kbase_addr) और gadget addresses की गणना करें.
  • SMEP/SMAP: pipe_buf_operations->release फ्लो के माध्यम से kernel context में ROP execute करें; userspace derefs से बचें जब तक कि disable/prepare_kernel_cred/commit_creds chain पूरी तरह से न हो.
  • Hardened usercopy: इस पेज के overflow primitive पर लागू नहीं; corruption के लक्ष्य non-usercopy fields हैं.

Reliability

  • adjacency मिलने के बाद High; कभी-कभी misses या panics (<10%) होते हैं. स्प्रे/free काउंट्स को tune करने से स्थिरता बेहतर होती है. specific collisions induce करने के लिए pointer के दो LSBs को overwrite करना प्रभावी बताया गया (उदाहरण के लिए, overlap में 0x0000_0000_0000_0500 pattern लिखें).

Key parameters to tune

  • msg_msg sprays की संख्या और hole pattern
  • OOB offset (pos) और परिणामी OOB length (count')
  • प्रत्येक चरण के दौरान UNIX socket, sk_buff, और pipe_buffer स्प्रे की संख्या

Mitigations and reachability

  • Fix: allocation और destination/length दोनों को clamp करें या allocated size के खिलाफ memcpy को bound करें; upstream patches CVE-2025-37947 के रूप में ट्रैक किए जाते हैं.
  • Remote exploitation के लिए अतिरिक्त रूप से एक reliable infoleak और remote heap grooming की आवश्यकता होगी; यह write-up local LPE पर केंद्रित है.

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 सार्वजनिक रूप से उपलब्ध हैं (देखें References)

References

tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें