FreeBSD CVE-2026-4747 深度解讀:一場從 RPCSEC_GSS 到 Kernel RCE 的完整攻防拆解

本篇文章更新時間:2026/04/02
如有資訊過時或語誤之處,歡迎使用 Contact 功能通知或向一介資男的 LINE 社群反應。
如果本站內容對你有幫助,歡迎贊助支持


FreeBSD RPCSEC_GSS Stack Overflow:從漏洞成因到完整 RCE 攻防流程

副標:一篇帶你看懂 CVE-2026-4747 如何讓遠端攻擊者在 FreeBSD 拿到 root shell 的技術拆解筆記

編輯前言:原文是由作者完整揭露 FreeBSD kgssapi.ko 中的 CVE-2026-4747,這是一個能讓遠端攻擊者在未開啟 KASLR 的 FreeBSD 14.x 上取得 kernel-mode RCE 的嚴重漏洞。本篇筆記希望以較易懂的角度消化原文脈絡,讓讀者掌握這起攻擊的關鍵思路。原文來源:publications/MADBugs/CVE-2026-4747/write-up.md

核心觀點 (Key Takeaways)

  • 漏洞發生於 svcrpcgss_validate() 中未檢查 oa_length,導致固定 128 bytes 的 stack buffer 被 memcpy 溢出。
  • 此漏洞 僅能由成功建立 Kerberos GSS context 的攻擊者觸發,意味著攻擊者需具備有效 Kerberos ticket。
  • 攻擊者可透過 15 次 ROP 逐段寫入 shellcode,最終於 kernel BSS 執行反向連線的 root shell。

深入解析

本次漏洞的起點,是 kgssapi.ko 裡一段負責驗證 RPCSEC_GSS 簽章的函式 svc_rpc_gss_validate()。原文清楚指出,這段程式碼在重建 RPC header 時,先寫入固定 32 bytes,接著直接把 credential body (oa_length) memcpy 進 96 bytes 的剩餘空間,卻 完全沒有 bounds check

原文指出:

"If oa_length > 96, this overflows past rpchdr into local variables → saved registers → return address."

也就是說:只要構造足夠大的 credential,攻擊者便能覆寫 callee-saved registers 與 return address,直接取得 ROP 控制權。FreeBSD 在 patch 中僅新增一行長度檢查,就足以阻擋整起攻擊,可見 bug 本身的單純與危險性並存。

  • 為什麼可從 NFS 遠端觸發?
    因為 RPCSEC_GSS 是 NFS 伺服器在 kernel 裡用來做 GSS 驗證的模組,NFS server 通常開放 2049/TCP,故漏洞能被遠端利用。

  • 為什麼需要 Kerberos?
    攻擊者必須擁有合法 Kerberos ticket,才能建立有效 GSS context;否則驗證階段會被拒絕而無法進入脆弱的 memcpy 分支。換句話說,只要攻擊者是合法域使用者,即可發動攻擊

技術亮點拆解

以下是原文中極具價值也最具啟發性的幾個重點:

  • Stack Overflow Geometry 的精確定位:作者透過 De Bruijn pattern 驗證溢位 offset,發現 GSS context handle 會多出 32 bytes 的偏移,使得 return address 落在 credential byte 200。

  • 分 15 round 的多階段 ROP:由於 RPCSEC_GSS credential 最大只有 400 bytes,ROP 空間有限,作者將 shellcode 拆成多段,每輪寫入 32 bytes,並善用 mov [rdi], rax gadget 實現精確的 arbitrary write。

  • 第一輪先把 kernel BSS 設成 RWX:透過 pmap_change_prot() 讓 BSS 可執行,之後才能在該區掉落與執行 shellcode。

  • 使用 kproccreate 而非直接 execve:因為 NFS worker thread 是純 kernel thread,無法直接切到 user mode,必須透過 kproccreate 建立一個新 process,才能最終透過 kern_execve 跳到 userland 執行 /bin/sh。

  • 清除 DR7 避免 debug breakpoint crash:此細節超級精彩。若 parent thread 曾進 DDB,其 debug registers 會污染 child process,導致在合法指令上觸發 trap 1。作者因此於 shellcode 主動清除 DR7,保證穩定執行。

筆者心得與啟發

這篇 write-up 的精彩之處,不是漏洞本身,而是作者如何將「只有 400 bytes 的資料平面」硬是拆解出可控 ROP、跨輪 arbitrary write,以及最終的 kernel→userland transition。我認為有三個值得安全研究者深思的重點:

  1. Kernel RCE 不再只靠單次利用,而是可分階段進行的 protocol-driven attack。RPCSEC_GSS 天然會多次建立 context,而攻擊能在每個 context 各進行一次溢位,這使 multi-stage payload 成為可能。

  2. Kernel thread 與 user process 的差異,讓 exploit 需要完全不同的思維。NFS worker thread 沒有 trapframe、沒有 user stack,也不能直接 execve。作者利用 kproc_create 的方式十分巧妙,並再次提醒:要能理解 OS 內核的 process/thread lifecycle 來寫 kernel exploit。

  3. 細節,才是 exploit 成敗的分水嶺。無論是 DR7、GSS token 的 MIT/Heimdal 差異、Kerberos 的 rdns 問題,甚至是 stack pivot 到 BSS 的位置選擇,任何一項小疏忽都可能讓整個 chain 無法成功。這正凸顯了 kernel exploitation 的複雜度與魅力。

總體而言,這篇文章是難得一見、同時涵蓋 stack overflow、ROP chain construction、kernel memory model、process creation 與 GSS/Kerberos protocol 的跨領域教材。如果你對 kernel security、NFS、GSS-API 或 FreeBSD 有興趣,原文值得逐字閱讀,而以上筆記則希望能提供一個更清晰的理解角度。


Share:

作者: Chun

WordPress 社群貢獻者、開源社群推廣者。專注於 WordPress 外掛開發、網站效能最佳化、伺服器管理,以及 iDempiere 開源 ERP 導入與客製開發。曾參與 WordCamp Taipei 等社群活動,GitHub Arctic Code Vault Contributor。提供資訊顧問、WordPress 開發教學、主機最佳化與企業 ERP 整合服務。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *


文章
Filter
Apply Filters
Mastodon