
1. 簡介
本報告詳細介紹了針對 CVE-2025-37947 的技術細節,這是一個在 Linux Kernel 的 ksmbd 模組中發現的關鍵 Out-of-Bounds (OOB) write 漏洞。 ksmbd 模組提供了一個 in-kernel SMB server ,實現了檔案共享能力。 Kernel 模組內的漏洞特別嚴重,因為它們可能導致本機權限提升,或在某些情況下導致遠端程式碼執行 (Remote Code Execution, RCE),繞過標準的作業系統安全緩解措施。本次分析專注於 CVE-2025-37947 的根本原因(root cause)、概念驗證 ( Proof-of-Concept )、堆積塑造技術 ( heap shaping techniques) 和 Exploitation 策略,並汲取了近期研究的見解 [1]。

2. ksmbd 和 Kernel 記憶體管理 背景知識
ksmbd 是 Server Message Block (SMB) 協定的 in-kernel 實作,旨在提供高效能的檔案共享。它直接整合到 Kernel 中,這意味著任何漏洞都可能對系統安全造成深遠的影響。瞭解 Kernel 記憶體管理 對於 Exploiting 此類漏洞至關重要。Linux Kernel 採用了各種記憶體分配器 (memory allocators),包括用於較大、實體連續區塊的分頁分配器 ( page allocator ,即 buddy allocator ) 和用於較小、頻繁使用物件的 slab 分配器 ( slab allocators ,例如 SLUB 、 SLAB 或 SLOB ) [1, 15]。
分頁分配器
將實體記憶體組織成
分頁
(
pages
,通常為 4KB),並以二的冪次方的
區塊
(
blocks
) 進行分配,這些區塊被稱為
orders
。例如,order 0 代表一個單一分頁,order 1 代表兩個連續分頁,依此類推。這種階層式結構分配和合併記憶體區塊。對於大於
KMALLOC_MAX_CACHE_SIZE
( 通常為 8192 位元組 ) 的分配,Kernel 會直接向分頁分配器請求分頁[1]。
3. 弱點分析: CVE-2025-37947
3.1. 根本原因
CVE-2025-37947
是一個
out-of-bounds write
漏洞,位於
ksmbd
模組的
ksmbd_vfs_stream_write
函式中。當
vfs objects
設定選項中啟用了
stream_xattr
模組,並且設定了可寫入的共享(share) 時,就會出現這個漏洞。核心問題在於寫入擴展屬性資料 ( extended attribute data ) 時,大小計算處理不當 [1]。
有漏洞的程式碼片段,特別是在
fs/ksmbd/vfs.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;
- struct mnt_idmap *idmap = file_mnt_idmap(fp->filp);
- size_t size;
- ssize_t v_len;
- int err = 0;
- ksmbd_debug(VFS, "write stream data pos : %llu, count : %zd\n",
- *pos, count);
- size = *pos + count;
- if (size > XATTR_SIZE_MAX) { // [1] Vulnerable check
- size = XATTR_SIZE_MAX;
- count = (*pos + count) - XATTR_SIZE_MAX; // [2] Count adjustment
- }
- wbuf = kvmalloc(size, GFP_KERNEL | __GFP_ZERO); // [3] Allocation based on truncated size
- stream_buf = wbuf;
- memcpy(&stream_buf[*pos], buf, count); // [4] Out-of-bounds write occurs here
- // .. snip
- if (err < 0)
- goto out;
- fp->filp->f_pos = *pos;
- err = 0;
- out:
- kvfree(stream_buf);
- return err;
- }
漏洞的發生是因為
XATTR_SIZE_MAX
通常是 65536 位元組 (16 分頁)。如果
*pos
和
count
的總和大於
XATTR_SIZE_MAX
,則
size
變數會在
[1]
處被截斷(truncated) 為
XATTR_SIZE_MAX
。然而,
count
變數會在
[2]
處被調整,以反映原始總和與
XATTR_SIZE_MAX
之間的差異。這意味著如果攻擊者 將
*pos
設定為
XATTR_SIZE_MAX
並提供一個小的
count
(例如 8 位元組),則
[3]
處的
kvmalloc
呼叫將分配大小為
XATTR_SIZE_MAX
的緩衝區( buffer )。隨後,
[4]
處的
memcpy
操作將嘗試從
stream_buf[*pos]
開始寫入
count
位元組,從而寫入超出已分配緩衝區的邊界[1]。
舉例來說,設定
*pos = 0x10000
和
count = 0x8
將導致
memcpy(&stream_buf[0x10000], buf, 8)
,從而導致 8 位元組的 out-of-bounds write。攻擊者還可以通過操縱
*pos
來控制偏移量(offset),從而實現對相鄰記憶體的精確破壞[1]。
3.2. 漏洞觸發的設定
為了觸發這個漏洞,
ksmbd
設定必須包含一個啟用了
streams_xattr
模組的可寫入共享:
[share] path = /share vfs objects = streams_xattr writeable = yes
3.3. 漏洞流程圖
下圖說明了導致 out-of-bounds write 漏洞的控制流程 :
4. 概念驗證 (PoC) 與記憶體佈局
一個最小的
概念驗證
(
Proof of Concept, PoC
) 可以在不一定提升權限的情況下證明此漏洞的可觸及性(reachability)。此類
PoC
通常會認證(authenticate) 到
ksmbd
共享並發送帶有使用者控制屬性的精心製作的
vfs stream 資料
。通過設定
file_offset
為
0x0000010018ULL
和
length_wr
為
8
,
攻擊者可以
out-of-bounds
寫入 32 位元組的任意資料(例如
0xaa
和
0xbb
模式)。像
GDB
這樣的除錯器可以通過檢查已分配位址處的記憶體來確認此
OOB write
[1]。
(gdb) c Continuing. ksmbd_vfs_stream_write+310 allocated: ffff8881056b0000 Thread 2 hit Breakpoint 2, 0xffffffffc06f4b39 in memcpy (size=32, q=0xffff8881031b68fc, p=0xffff8881056c0018) at /build/linux-eMJpOS/linux-5.15.0/include/linux/fortify-string.h:191 warning: 191 /build/linux-eMJpOS/linux-5.15.0/include/linux/fortify-string.h: No such file or directory (gdb) x/2xg $rsi 0xffff8881031b68fc: 0xaaaaaaaaaaaaaaaa 0xbbbbbbbbbbbbbbbb
此
GDB輸出
清楚地顯示
memcpy
操作正在從來源
q
向目標
p
寫入 32 位元組 ( size=32 ),其中
p
是
0xffff8881056c0018
。鑑於已分配緩衝區從
0xffff8881056b0000
開始,並且
XATTR_SIZE_MAX
是
0x10000
(65536 位元組 ),在
0xffff8881056c0018
處的寫入確實是
out-of-bounds
的,具體來說是超出已分配
0x10000
邊界
0x18
位元組[1]。
5. 用於 Exploitation 的 Heap Shaping
Exploiting Kernel OOB writes 通常需要對 Kernel 堆積佈局進行精確控制,這項技術被稱為 heap shaping 。目的是將目標物件(target object) 放置於緊接在有漏洞的緩衝區之後,以便 OOB write 以受控方式破壞目標物件。在 CVE-2025-37947 的環境中, kvzalloc 函式被用於分配,它是 kvmalloc 的封裝(wrapper)。 kvmalloc 嘗試使用 kmalloc 分配實體連續的記憶體,如果有必要則會退回到 vmalloc [1]。
由於分配大小(16 分頁或
0x10000
) 大於
KMALLOC_MAX_CACHE_SIZE
(8192 位元組),Linux Kernel的分頁分配器 (
buddy allocator
) 會直接介入。這意味著 Exploitation 策略必須集中於操縱分頁分配器。挑戰在於在有漏洞的
kvzalloc
呼叫之前,在記憶體中建立一個 16 分頁的連續空閒空間(free space),確保
stream_buf
被放置在這個受控區域[1]。
為了實現這一點,攻擊者可以分析
Kernel
的 slab caches 和分頁分配器統計資料。
/sys/kernel/slab/*/order
檔案揭示了用於分配 slabs 的分頁順序。例如,許多常見的
Kernel
物件使用 order-3 分頁。通過檢查
/proc/pagetypeinfo
,可以每個 order 和遷移類型(migrate type) 的空閒分頁數量(例如
Unmovable
、
Movable
)。該策略涉及耗盡特定 order-3 和 order-4 空閒列表項目(freelist entry),迫使分配器拆分更高 order 的區塊(例如 order-5) 來滿足請求。這可以建立一個場景,其中目標物件(例如 msg_msg 物件) 被放置在
stream_buf
之後,使其易受
OOB write
的破壞[1]。
例如,分配大量大小為 4096 位元組的 msg_msg 物件(以符合
kmalloc-cg-4k
) 可以幫助塑造堆積。通過接收訊息來建立空洞(holes),
stream_buf
剛好落在目標 msg_msg 物件之前的機率會顯著增加,從而允許通過
out-of-bounds write
破壞其記憶體[1]。
6. Exploitation 策略
一旦
out-of-bounds write
被可靠地觸發且目標物件被破壞,下一步就是實現本機權限提升(local privilege escalation)。
原始文章提到嘗試破壞分段(segmented) msg_msg 物件中的
next
指標(pointer),但轉向了類似 CVE-2021-22555 中描述的策略:將 \x00\x00 轉換為 10000$。這種方法特別有效,因為
OOB write
目標是實體分頁(physical pages) 而非 slab 物件,簡化了跨快取(cross-cache)攻擊的考慮[1, 13]。
Exploitation 流程通常涉及多個階段 :
- Heap Spraying: 在 Kernel 中分配大量 msg_msg 物件,為控制放置堆積做準備。
-
Triggering OOB Write:
觸發
CVE-2025-37947
漏洞以分配
stream_buf
並覆寫主要訊息(primary message) 的next
指標。這種操縱會導致兩個主要訊息指向同一個次要訊息(secondary message),建立碰撞(collision)。 -
Detecting Corruption:
通過用其佇列(queue)索引標記每個訊息,並使用
msgrcv(MSG_COPY)
掃描佇列以尋找不匹配的標記,來識別被破壞的配對(pair)。 - Arbitrary Read/Write Primitive: 通過小心地釋放真實的次要訊息,然後釋放假的次要訊息,攻擊者可以獲得任意讀/寫原語(primitive)。該原語對於進一步的 Exploitation 步驟至關重要,例如洩露 Kernel 位址(address) (以繞過 KASLR ) 和覆寫關鍵 Kernel 資料結構(data structures)。
-
Privilege Escalation:
擁有任意讀/寫能力後,攻擊者可以修改當前程序的敏感 Kernel 結構,例如
credentials
,以獲取 root 權限。這通常涉及用精心製作的
cred 結構
覆寫當前任務(task) 的
cred
結構,該結構授予完全能力(capabilities)。
文章強調,通過 BPF 腳本 (scripts) 確認分配位址對於確保 Exploit 的正確(alignment) 和可預測性至關重要。例如,分析來自 bpf-tracer.sh 等工具的輸出可以顯示已分配分頁的分佈,並確認 heap shaping 是有效的 [1]。
$ sudo ./bpf-tracer.sh ... $ grep 4048 out-4096.txt | egrep ".... total" -o | sort | uniq -c 511 0000 total 510 1000 total 511 2000 total 512 3000 total 511 4000 total 511 5000 total 511 6000 total 511 7000 total 513 8000 total 513 9000 total 513 a000 total 513 b000 total 513 c000 total 513 d000 total 513 e000 total 513 f000 total
此輸出展示了受控的分配分佈,這對於成功的
heap shaping
和隨後的 Exploitation 至關重要。通過覆寫特定位元組(例如
\x05\x00
)建立碰撞的能力,進一步完善了 Exploit 的精準度,實現了堆疊樞軸(stack pivoting) 和其他進階技術[1]。
7. 結論
Linux Kernel的 ksmbd 模組中的 CVE-2025-37947 由於其本機權限提升的潛力而代表了一個重大的安全漏洞。 ksmbd_vfs_stream_write 中的 out-of-bounds write ,結合複雜的 heap shaping 技術,允許攻擊者獲得對 Kernel 記憶體的控制。本研究報告闡明了該漏洞的技術細節、觸發所需的設定、涉及 heap shaping 的記憶體管理概念以及多階段的 Exploitation 策略。瞭解此類漏洞對於開發穩健的防禦並確保 Kernel 級別組件的完整性至關重要。
參考 文章
- ksmbd - Exploiting CVE-2025-37947 (3/3)
- CVE-2025-37947 Detail - NVD
- CVE-2025-37947 Impact, Exploitability, and Mitigation Steps
- CVE-2025-37947 Common Vulnerabilities and Exposures
- Proof-of-Concept Released for Exploited Linux Kernel ...
- CVE-2025-37947 | INCIBE-CERT
- A Vulnerability in KSMBD for Linux Could Allow for Remote ...
- CVE-2022-47939 critical vulnerability in Linux kernel ` ...
- Linux Kernel ksmbd Use-After-Free Vulnerability
- Linux Kernel ksmbd zero-day disclosed
- SMB: Linux Kernel ksmbd Mech Token Out-Of-Bounds Read
- Linux Kernel ksmbd Filesystem Vulnerability Exploited
- How a simple Linux kernel memory corruption bug can ...
- Kernel Exploitation Techniques: Turning The (Page) Tables
- The Linux kernel memory allocators from an exploitation ...