作者 | Sean Heelan
編譯 | 蘇宓
出品 | CSDN(ID:CSDNnews)
在這個 AI 大模型流行的時代,有人對自動生成的代碼感到厭煩,比如 Curl 項目的創始人 Daniel Stenberg 不久前就曾怒斥 AI 生成的漏洞報告泛濫,直言它們簡直像 DDoS 攻擊一樣令人頭疼。而與此同時,也有人開始借助 AI 工具深入探索安全問題,甚至挖出了真漏洞。
最近,安全研究員 Sean Heelan 分享了他利用 OpenAI 的 o3 大模型,在完全不依賴其他工具、框架或輔助代碼的前提下,成功發現了 Linux 內核中的一個零日漏洞。這個漏洞現已被正式編號為 CVE-2025-37899,屬于一種發生在 SMB 協議“logoff”命令處理路徑中的 use-after-free(釋放后使用)問題,官方修復補丁也已經發布。
那么,他到底是怎么發現的?我們不妨通過 Sean Heelan 發布的長文來一探究竟。
背景
Sean Heelan 透露,自己近期一直在審計 ksmbd 模塊的安全性。ksmbd 是 Linux 內核中實現 SMB3 協議的服務端組件,主要用于實現文件共享服務。
之所以啟動這項研究,Sean Heelan 本來是想要暫時遠離大模型相關工具的開發工作,但在看到 o3 發布后,他還是沒忍住,決定順手用自己已掌握的 ksmbd 漏洞作為基準,想要測試一下 o3 的代碼理解與分析能力。
沒想到的是,測試中,o3 模型真實地識別出另一個名為 CVE-2025-37899 漏洞。該問題涉及服務器的并發連接及對象共享機制,理解起來需要較強的并發上下文推理能力。o3 成功識別出一處關鍵邏輯:某個對象未被引用計數保護的情況下被釋放,而此時該對象可能仍被其他線程訪問。這一能力超出了此前對大模型代碼分析上限的普遍認知。
Sean Heelan 表示,這是首次有公開報道顯示大型語言模型能夠獨立發現此類類型的內核級漏洞。他指出,o3 模型在代碼理解和漏洞挖掘方面已經實現重要飛躍,值得安全研究者密切關注。盡管目前模型尚不能取代專業漏洞研究人員或利用開發者,但它們已具備顯著增強專家效率的能力。如果一個安全問題可以被壓縮到一萬行代碼以內,o3 很有可能能夠直接解決,或提供關鍵幫助。
o3 在 CVE-2025-37778 上的基準測試表現
在 o3 模型意外發現 CVE-2025-37899這一零日漏洞之前,Sean Heelan 原本正使用另一個自己手動發現的漏洞——CVE-2025-37778,來評估 o3 在漏洞檢測方面的能力。
簡單來看,CVE-2025-37778 是一個 “釋放后使用”(use-after-free)類型的漏洞,問題出現在處理遠程客戶端發來的 “session setup”(會話建立)請求時,具體是在 Kerberos 認證的流程中。為了方便起見,Sean Heelan 把這個漏洞稱作 “Kerberos 認證漏洞”。
它的根本原因大致如下:
static int krb5_authenticate(struct ksmbd_work *work,
struct smb2_sess_setup_req *req,
struct smb2_sess_setup_rsp *rsp)
{
...
if (sess->state == SMB2_SESSION_VALID)
ksmbd_free_user(sess->user);
retval = ksmbd_krb5_authenticate(sess, in_blob, in_len,
out_blob, &out_len);
if (retval) {
ksmbd_debug(SMB, "krb5 authentication failed\n");
return -EINVAL;
}
...
如果 krb5_authenticate 檢測到當前會話的狀態是 SMB2_SESSION_VALID,它就會釋放 sess->user(也就是把它清掉)。
它的假設是這樣的:要么 ksmbd_krb5_authenticate 后面會重新初始化 sess->user,要么如果 krb5_authenticate 返回錯誤(比如返回 -EINVAL),那后續代碼就不會再用到 sess->user。但問題是——這個假設不對。實際上我們可以讓 ksmbd_krb5_authenticate 不去重新初始化 sess->user,而且即使 krb5_authenticate 返回了 -EINVAL,后面也還是有辦法訪問這個已經被釋放的 sess->user,就出問題了。
這個漏洞很適合用來測試大模型的能力,原因有幾點:
1. 首先,它屬于 Linux 內核的遠程攻擊面的一部分,本身就挺有意思的。
2. 然后,它并不簡單,想要發現它需要搞清楚三件事:
怎么讓 sess->state 變成 SMB2_SESSION_VALID,以便觸發釋放;
意識到 ksmbd_krb5_authenticate 某些執行路徑不會重新賦值 sess->user,并分析怎么走到這些路徑;
發現代碼里其他地方可能會在這個變量被釋放后繼續訪問它。
3. 雖然不算簡單,但也不復雜得離譜。Sean Heelan 稱其可以花十分鐘把整條觸發路徑講給同事聽,而且理解這個漏洞用不著深入了解 Linux 內核、SMB 協議或者 ksmbd 的全貌,只需要看懂連接處理和會話建立相關的代碼就行。對此,Sean Heelan 還專門數了一下,從網絡包到達 ksmbd 模塊、再到漏洞被觸發,沿著這條路徑讀一遍相關函數的代碼,大概是 3300 行左右。
基于以上這些因素,Sean Heelan 想要用這個漏洞作為測試對象,接下來要決定的是:給大模型看什么代碼,看看它能不能找出這個漏洞?
Sean Heelan 想模擬一下一個假想的自動化漏洞檢測系統,在這種系統下,o3 作為后端模型的表現會如何。所以其必須明確:這樣一個系統是怎么給 LLM 準備輸入內容的。因為如果給模型看的代碼方式不現實,現實中系統沒法復制,那這個測試就沒什么意義。
理想情況下,Sean Heelan 當然想直接把一個項目的完整代碼扔給 LLM,模型分析完直接吐出結果。但受限于上下文長度(context window)和上下文越多性能越差的問題,現在還做不到。
于是 Sean Heelan 想了一個折中辦法:模擬一個工具把每個 SMB 命令處理函數(handler)單獨展開來喂給模型。比如他就把“session setup”這個命令處理器相關的代碼給了 LLM——不僅是它本身的代碼,還包括它調用的所有函數(最多展開到調用深度 3),這樣模型才能看全邏輯。同時他也提供了那些從網絡接收數據、解析請求、選擇處理器和連接關閉相關的代碼,否則模型就得自己猜這些結構是怎么設置的,那肯定會帶來更多誤報。
最后,這一堆代碼加起來大約 3300 行(相當于 2.7 萬個 token),正好可以作為一個標準用來對比 o3 和以往模型的能力。如果你感興趣,這里有個單文件版本,是用 files-to-prompt 工具生成的(https://github.com/SeanHeelan/o3_finds_cve-2025-37899/blob/master/session_setup_code.prompt)。
最后一個要決定的就是用什么 Prompt。Sean Heelan 把用的 system prompt 和其它提示信息都整理在了這個 GitHub 倉庫的 .prompt 文件里(https://github.com/SeanHeelan/o3_finds_cve-2025-37899)。關鍵點如下:
Sean Heelan 明確告訴 LLM 要找的是 use-after-free(釋放后使用)類型的漏洞;
給了它一個簡短的背景介紹,說明 ksmbd 是什么,它的架構大概如何,以及安全模型是怎樣的;
他盡量引導模型不要報出誤報,甚至寧愿不報漏洞也別報錯的。不過對于這一點,Sean Heelan 也不確定這是否有效,只是希望能有效。說白了,這些提示尚未通過系統性實驗驗證其效果,Sean Heelan 坦言自己寫的提示詞:“這些更像是在祈禱,而不是科學。”
接下來,Sean Heelan 使用名為 llm 的工具(https://github.com/simonw/llm)執行推理請求,如下所示:
$ llm --sf system_prompt_uafs.prompt \
-f session_setup_code.prompt \
-f ksmbd_explainer.prompt \
-f session_setup_context_explainer.prompt \
-f audit_request.prompt
在這次實驗中,Sean Heelan 把測試流程跑了 100 次,并記錄了每次的結果。他也提醒說,如果別人復現實驗,可能得到的結果跟他不完全一樣。因為他在寫博客前不小心刪了之前用來分析的那份代碼,只能重新生成了一份,雖然內容應該幾乎一樣,但他并沒有重新跑一遍全部測試驗證。
那 o3 表現怎么樣呢?
它在這 100 次測試中,有 8 次成功找到了那個 Kerberos 認證相關的漏洞;66 次啥也沒發現(也就是說漏掉了漏洞);另外還有 28 次,它報告了錯誤的“漏洞”,其實并沒有問題。這種情況在安全分析中叫“誤報”。
為了比較效果,他也拿另外兩個模型試了一下:Claude Sonnet 3.7 找到漏洞的次數是 3 次,Claude Sonnet 3.5 連一次都沒找出來。所以從這次測試結果來看,o3 的表現大概是 Claude Sonnet 3.7 的 2 到 3 倍。
o3 模型發現新的零日漏洞(CVE-2025-37899)
在確認 o3 能夠在給定 session setup 命令處理函數的代碼時成功識別 Kerberos 身份驗證漏洞(CVE-2025-37778)之后,Sean Heelan 進一步嘗試提升挑戰難度:這次,他將所有 SMB 命令處理函數的代碼一并提供給 o3,測試其在更復雜、上下文更廣的條件下是否仍能識別漏洞。
這項任務的難度明顯更高:所有命令處理函數均位于 smb2pdu.c 文件中,該文件約有9000 行代碼。如果 o3 在此情況下仍能發現漏洞,將意味著可以構建更直接的封裝工具,整體將完整源碼文件交由模型處理,而不必逐個處理器地構造輸入。
Sean Heelan 將所有命令處理器代碼與連接初始化、關閉流程、命令調度邏輯等輔助函數整合后,總輸入規模達到約12k 行代碼(約 10 萬 tokens)。他同樣進行了 100 次實驗。
在這一大規模上下文下,o3 在 100 次運行中僅有一次識別出原本的 Kerberos 身份驗證漏洞,顯示出在上下文量顯著增加時模型性能確實存在下降。但更令人驚喜的是,在其他運行結果中,Sean Heelan 注意到 o3 報告了一個此前未知的、類似但全新的漏洞。這個新漏洞也涉及 sess->user 的釋放問題,但這次出現在會話注銷(logoff)處理邏輯中。
int smb2_session_logoff(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
struct ksmbd_session *sess = work->sess;
...
ksmbd_close_session_fds(work);
ksmbd_conn_wait_idle(conn);
...
down_write(&conn->session_lock);
sess->state = SMB2_SESSION_EXPIRED;
up_write(&conn->session_lock);
if (sess->user) {
ksmbd_free_user(sess->user);
sess->user = NULL;
}
...
發現之后,Sean Heelan 又讓 o3 進一步解釋一下這個漏洞:
簡要描述
當一個 ksmbd worker 線程仍在執行依賴 sess->user 的請求時,另一個處理同一會話的 SMB2 LOGOFF 的線程會釋放該結構。由于沒有同步機制保護這個指針,第一個線程便會解引用已被釋放的內存——這是一個典型的 use-after-free(釋放后使用)漏洞,會導致內核內存損壞,甚至在內核上下文中執行任意代碼。
受影響的代碼路徑
1. 一個額外的傳輸通道被綁定到一個已存在的會話上
(SMB 3.0 或更高版本,conn->binding == true)。
2. Worker?A(在連接 C2 上運行)收到任意正常請求(例如 WRITE)。
smb2_check_user_session() 將已存在的 struct ksmbd_session 指針存入 work->sess,并增加會話引用計數,但不會對 sess->user 增加引用計數。
該指針在整個請求處理過程中保持不變;所有需要認證信息的輔助函數都會直接訪問 sess->user。
3. 在 Worker?A 尚未處理完時,Worker?B(在第一個連接 C1 上運行)處理了同一會話的 SMB2 LOGOFF 請求,并調用了 smb2_session_logoff()(位于 smb2pdu.c)。
smb2_session_logoff()中的相關代碼段
if (sess->user) {
ksmbd_free_user(sess->user); /* (1) 釋放內存 */
sess->user = NULL; /* (2) 清空字段 */
}
ksmbd_free_user() 最終會調用簡單的 kfree(user) 來釋放內存。
4. Worker?B不會等待其他仍在使用該會話的連接完成操作;它只會等待 自己這個連接 上正在運行的請求結束(通過 ksmbd_conn_wait_idle(conn) 實現)。
5. Worker?A 繼續執行(例如在 smb2_open()、smb2_write() 等函數中),并解引用了 sess->user:
/* 以下是部分示例(類似用法還有很多) */
if (user_guest(sess->user)) ← 釋放后的解引用
ksmbd_compare_user(sess->user, …)
sess->user->uid
由于該內存已在步驟 (1) 中通過 kfree() 釋放,因此這些訪問操作實際訪問了已釋放的內存。具體后果取決于訪問發生的時機:
如果指針仍指向被回收的 slab 對象,即發生 use-after-free,可能被攻擊者利用修改內核內存;
如果 Worker?A 在步驟 (2) 后訪問,即 sess->user 已被置為 NULL,則會發生空指針解引用,導致拒絕服務(DoS)。
在讀完 o3 模型生成的漏洞報告之后,Sean Heelan 意識到他原先的理解并不充分。雖然 logoff 處理函數確實將 sess->user 置為了 NULL,但這個措施仍然不夠,因為 SMB 協議允許兩個不同的連接“綁定”到同一個會話上,而在 Kerberos 認證路徑上并沒有機制能阻止其他線程在 sess->user 被釋放與被置為 NULL 的那一小段時間內繼續使用它。Heelan 指出,自己此前其實已經利用過這個特性觸發 ksmbd 的另一個漏洞,但在分析此次 Kerberos 認證漏洞時卻沒有想到這一點。
在意識到問題后,Heelan 回過頭去檢查了 o3 在搜索 Kerberos 認證漏洞時生成的報告。他發現,o3 在部分結果中確實和他一樣遺漏了這一點,但在其他一些報告中則準確地指出:僅僅將 sess->user 置為 NULL 并不足以徹底修復問題,因為會話綁定機制仍然可能導致競態條件的發生。Heelan 認為,這一點相當令人印象深刻——如果他一開始就借助 o3 來定位并修復該漏洞,理論上本可以取得更好的結果。當然,他也坦言,目前 o3 的誤報率仍偏高,不一定能保證他有足夠的精力逐一甄別每條報告并從中發現這個關鍵點。但隨著模型能力的提升,這一比例有望持續改善。
結論
最后,Sean Heelan 總結道,大型語言模型(LLMs)在程序分析能力空間中所處的位置,比我們以往見過的任何技術都更接近人類。就創造力、靈活性和通用性而言,LLM 更像是一位人類代碼審計專家,而不是符號執行、抽象解釋或模糊測試工具。自從 GPT-4 出現以來,人們就對 LLM 在漏洞研究中的潛力抱有期待,但它在現實問題中的表現一直沒能真正達到人們的期望。而 o3 的出現改變了這一局面:我們終于有了一個在代碼推理、問答、編程和問題解決方面足夠優秀的模型,能夠實實在在提升人類在漏洞研究中的效率。
當然,o3 遠非萬無一失。它仍有相當大的概率會生成荒謬的結果,令人沮喪。但不同的是,現在它給出正確答案的概率終于足夠高,值得大家投入時間和精力,嘗試將其應用于真實問題。
原文:https://sean.heelan.io/2025/05/22/how-i-used-o3-to-find-cve-2025-37899-a-remote-zeroday-vulnerability-in-the-linux-kernels-smb-implementation/
2025 全球產品經理大會
2025 年 8 月 15–16 日
北京·威斯汀酒店
2025 全球產品經理大會將匯聚互聯網大廠、AI 創業公司、ToB/ToC 實戰一線的產品人,圍繞產品設計、用戶體驗、增長運營、智能落地等核心議題,展開 12 大專題分享,洞察趨勢、拆解路徑、對話未來。
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.