AI 首次發(fā)現(xiàn)真實世界中的重大安全漏洞?SQLite 中的一個漏洞,幸運地被谷歌研究者的 AI Agent 發(fā)現(xiàn)了,修復(fù)后并未造成任何損失。莫非 AI 再進化一番,微軟的全球藍屏事故就可以永久避免了?這個可能性令人激動不已。
LLM 居然在真實世界的代碼中,發(fā)現(xiàn)了一個漏洞?
想象一下,AI 正在默默地守護著我們?nèi)粘J褂玫能浖?。忽然,它發(fā)現(xiàn)了一個你我可能從未察覺的安全隱患,并且悄無聲息地把它修復(fù)了!
就在剛剛,谷歌的 Big Sleep 項目揭示了一個驚人的成果:一個真實世界的安全漏洞,出現(xiàn)在全球廣泛使用的 SQLite 數(shù)據(jù)庫中,而這個漏洞竟然被 AI 成功識別出來了?在真實世界的危機擴散之前,它及時挽回了局面。
隸屬于谷歌 Project Zero 和 Google DeepMind 的團隊聲稱,這是 AI Agent 在廣泛使用的現(xiàn)實軟件中,發(fā)現(xiàn)未知可利用內(nèi)存安全問題的第一個公開示例。
要知道,這不僅僅是一個崩潰的測試用例,它是 AI 首次在真實世界的軟件中找到未知的、可利用的內(nèi)存漏洞。
此前,網(wǎng)絡(luò)安全巨頭 CrowdStrike 鬧出的一個由「C-00000291*.sys」配置文件觸發(fā)的系統(tǒng)邏輯錯誤,瞬間就破壞掉全世界約 10 億臺計算機,直接導(dǎo)致微軟藍屏、全球停擺。
如果未來某一天,AI 能幫我們解決所有技術(shù)領(lǐng)域的單點瞬時故障,不知會幫人類節(jié)省下多少財富?
用 LLM 在真實世界中「捉蟲」
隨著 LLM 代碼理解和一般推理能力的提高,谷歌研究者一直在探索這些模型如何在識別和演示安全漏洞時,重新人類安全研究人員的方法。
在《Project Naptime:評估大型語言模型的攻防能力》中,Big Sleep 團隊介紹了一個利用 LLM 輔助的漏洞研究框架,并通過在 Meta 的 CyberSecEval2 基準(zhǔn)測試上提升了最新的性能,展示了這種方法的潛力。
從那時起,Naptime 就變成「Big Sleep」,成為了 Google Project Zero 與 Google DeepMind 的合作項目。
就在剛剛,谷歌研究者激動地表示,Big Sleep Agent 發(fā)現(xiàn)了首個真實世界漏洞:一個存在于 SQLite 中的可利用棧緩沖區(qū)下溢漏洞。
SQLite 是一款被廣泛使用的開源數(shù)據(jù)庫引擎。
在十月初,Agent 發(fā)現(xiàn)了了這個漏洞,于是谷歌研究者立刻將其報告給了開發(fā)者,他們在同一天進行了修復(fù)。
幸運的是,AI 在這個問題出現(xiàn)在官方發(fā)布版本之前,就發(fā)現(xiàn)了它,因此 SQLite 的用戶未受影響。
要知道,SQLite 作為輕量級嵌入式數(shù)據(jù)庫,廣泛應(yīng)用于智能手機、瀏覽器、嵌入式系統(tǒng)、IoT 設(shè)備等多種環(huán)境,涵蓋了許多用戶和敏感信息。
如果攻擊者利用該漏洞進行數(shù)據(jù)泄露、系統(tǒng)入侵或破壞,潛在損失金額可能少則幾百萬,多則數(shù)十億美元!
谷歌研究者表示,這是 AI Agent 首次在廣泛使用的真實世界軟件中發(fā)現(xiàn)未知的、可利用的內(nèi)存安全問題的公開案例。
之所以會有這次嘗試,是因為今年早些時候,在 DARPA 的 AIxCC 活動中,亞特蘭大團隊在 SQLite 中發(fā)現(xiàn)了一個空指針取消引用的漏洞,這就給了谷歌研究者啟發(fā) ——
是否可以使用 SQLite 進行測試,看看能否找到更嚴重的漏洞呢?
果然,AI Agent 真的找出了一個漏洞。
這項工作,無疑具有巨大的潛力。
在軟件尚未發(fā)布前就發(fā)現(xiàn)漏洞,就意味著攻擊者沒有機會利用:漏洞在他們有機會使用之前,就已被修復(fù)。
雖然模糊測試也能帶來顯著的幫助,但我們更需要的是一種方法,幫助防御者找到那些很難通過模糊測試發(fā)現(xiàn)的漏洞。
現(xiàn)在,AI 有望縮小這一差距!
谷歌研究者表示,這是一條有希望的道路,能為防御者帶來不對稱的優(yōu)勢。
因為這個漏洞相當(dāng)有趣,而且 SQLite 的現(xiàn)有測試基礎(chǔ)設(shè)施(包括 OSS-Fuzz 和項目自身的測試)并沒有發(fā)現(xiàn)它,因此谷歌研究者進行了深入調(diào)查。
方法架構(gòu)
Naptime 和 Big Sleep 項目的關(guān)鍵驅(qū)動因素,就是已經(jīng)發(fā)現(xiàn)并修補的漏洞變種,仍在現(xiàn)實中不斷被發(fā)現(xiàn)。
顯而易見,fuzzing(模糊測試)并不能成功捕獲此類變種漏洞,而對攻擊者而言,手動變種分析的方法仍然性價比很高。
谷歌研究者認為,相比更為寬泛的開放式漏洞研究問題,這種變種分析任務(wù)更適合當(dāng)前的 LLM。
通過提供一個具體的起點 —— 比如此前修復(fù)的漏洞的詳細信息 —— 我們就可以降低漏洞研究中的不確定性,并且還能從一個明確的、有理論支撐的假設(shè)出發(fā):「這里曾經(jīng)存在一個漏洞,很可能在某處還存在類似的問題」。
目前,他們的項目仍處于研究階段,正在使用帶有已知漏洞的小型程序來評估研究進展。
最近,他們決定通過在 SQLite 上開展首次大規(guī)模的真實環(huán)境變種分析實驗,來測試他們的模型和工具鏈。
他們收集了 SQLite repository 近期的一系列提交,手動篩除了無關(guān)緊要的改動和純文檔更新。
隨后,他們調(diào)整了 prompt,為 AI Agent 同時提供了提交信息和代碼變更,并要求它審查當(dāng)前代碼庫(在 HEAD 位置)中可能仍未修復(fù)的相關(guān)問題。
Project Naptime
Naptime 采用了一種專門的架構(gòu)來增強大語言模型進行漏洞研究的能力,其核心是 AI Agent 與目標(biāo)代碼庫之間的交互。
系統(tǒng)架構(gòu)
為了讓 AI Agent 可以模仿人類安全研究員的工作流程,研究團隊開發(fā)了一系列專用的工具:
代碼瀏覽工具(Code Browser)使 AI Agent 能夠瀏覽目標(biāo)代碼庫,這與工程師使用 Chromium Code Search 的方式類似。它提供了查看特定實體(如函數(shù)、變量等)源代碼的功能,并能識別函數(shù)或?qū)嶓w被引用的位置。
Python 工具讓 AI Agent 能夠在隔離的沙盒(Sandbox)環(huán)境中運行 Python 腳本,用于執(zhí)行中間計算并生成精確而復(fù)雜的目標(biāo)程序輸入。
調(diào)試器工具(Debugger)為 AI Agent 提供了程序交互能力,可以觀察程序在不同輸入下的行為表現(xiàn)。它支持斷點設(shè)置并能在斷點處評估表達式,從而實現(xiàn)動態(tài)分析。
報告工具(Reporter)為 AI Agent 提供了一個結(jié)構(gòu)化的進度通報機制。AI Agent 可以發(fā)送任務(wù)完成信號,觸發(fā)控制器驗證是否達成成功條件(通常表現(xiàn)為程序崩潰)。當(dāng)無法取得進一步進展時,它還允許 AI Agent 主動中止任務(wù),避免陷入停滯狀態(tài)。
發(fā)現(xiàn)漏洞
這個漏洞非常有趣,比如在一個通常為索引類型的字段 iColumn 中,使用了一個特殊的哨兵值-1:
7476 struct sqlite3_index_constraint { 7477 int iColumn /* Column constrained. -1 for ROWID */ 7478 unsigned char op /* Constraint operator */ 7479 unsigned char usable /* True if this constraint is usable */ 7480 int iTermOffset /* Used internally - xBestIndex should ignore */ 7481 } *aConstraint /* Table of WHERE clause constraints */
這種模式產(chǎn)生了一個邊緣案例,所有使用該字段的代碼都需要正確處理這種情況,因為按照常規(guī)預(yù)期,有效的列索引值應(yīng)該是非負的。
seriesBestIndex 函數(shù)在處理這個 edge case 時存在缺陷,當(dāng)處理包含 rowid 列約束的查詢時,導(dǎo)致寫入了帶有負索引的堆棧緩沖區(qū)。
在研究者提供給 AI Agent 的編譯版本中,debug assertion 功能已啟用,這種異常情況會被第 706 行的斷言檢查所捕獲:
619 static int seriesBestIndex( 620 sqlite3_vtab *pVTab, 621 sqlite3_index_info *pIdxInfo 622 ){ ... 630 int aIdx[7]; /* Constraints on start, stop, step, LIMIT, OFFSET, 631 ** and value. aIdx[5] covers value=, value>=, and 632 ** value>, aIdx[6] covers value<= and value< */ 633 const struct sqlite3_index_constraint *pConstraint; ... 642 for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){ 643 int iCol; /* 0 for start, 1 for stop, 2 for step */ 644 int iMask; /* bitmask for those column */ 645 int op = pConstraint->op; ... 705 iCol = pConstraint->iColumn - SERIES_COLUMN_START; 706 assert( iCol>=0 && iCol<=2 ); 707 iMask = 1 << iCol; ... 713 if( pConstraint->usable==0 ){ 714 unusableMask |= iMask; 715 continue; 716 }else if( op==SQLITE_INDEX_CONSTRAINT_EQ ){ 717 idxNum |= iMask; 718 aIdx[iCol] = i; 719 } 720 }
然而,在發(fā)布版本中,這個斷言檢查并不存在。
在研究者的測試環(huán)境中(具體表現(xiàn)會因編譯器和優(yōu)化級別而異),第 718 行的后續(xù)寫入操作會越界寫入 aIdx 緩沖區(qū)下方的內(nèi)存區(qū)域,導(dǎo)致 pConstraint 指針的最低有效 32 位被破壞。
當(dāng)這個被破壞的指針在循環(huán)的下一次迭代中被取消引用時,就會產(chǎn)生潛在的可利用漏洞條件。
不過,即使有了這樣的漏洞說明,對于人類研究員來說,要精確理解如何觸發(fā)這個漏洞仍然不易。
雖然針對 ROWID 列設(shè)置約束顯然是個不錯的切入點,但要完全理解,還需要深入研讀代碼。
而 AI 智能體似乎已經(jīng)掌握了比人類研究員更多的 SQLite 相關(guān)知識,這使它能夠更高效地定位問題!
這種情況的一個典型例子,就是 LLM 在生成測試用例時會直接使用 generate_series 虛擬表。
(雖然研究者也觀察到模型會先研究可用的虛擬表的情況,但很明顯,它能夠在這里直接運用已有的知識)。
執(zhí)行過程重點分析
在這次基于 Gemini 1.5 Pro 的成功測試中,seed commit 為 [1976c3f7],這是一個規(guī)模較大、復(fù)雜的代碼變更。
而研究者的 AI Agent 發(fā)現(xiàn)的漏洞,與該 seed commit 中的變更僅存在松散關(guān)聯(lián) —— 這種情況在手動變種分析中較為常見,因為在理解代碼庫中的某個漏洞時,研究人員往往會由此發(fā)現(xiàn)其他潛在問題。
以下是關(guān)鍵節(jié)點摘要,其中,所有 ASSISTANT 塊中的內(nèi)容均直接來自 AI Agent。
AI Agent 對差異中的變化進行了合理的評估,并以此作為研究的切入點:
ASSISTANT
通過引入 termFromWhereClause 函數(shù),CL 改進了在虛擬表查詢中處理 OR 分支共享的 WHERE 條件的方式。該函數(shù)在考慮嵌套子句的情況下,從 WhereClause 中檢索特定的條件。
在此更改之前,由于條件索引映射不正確,共享的條件可能未被正確處理,可能導(dǎo)致低效的查詢計劃或錯誤的結(jié)果。
最可能出現(xiàn)的問題涉及在 allocateIndexInfo 和 whereLoopAddVirtualOne 函數(shù)中不正確地處理 WHERE 子句約束,其中 CL 修改了如何使用新的輔助函數(shù)來處理約束偏移量。
我將首先檢查 allocateIndexInfo 函數(shù)。
在經(jīng)過數(shù)個步驟探索相關(guān)代碼后,AI Agent 形成了一個更明確的測試假設(shè) —— 它試圖通過運行 patch 中測試用例的修改版本來驗證這個假設(shè),但未能成功。
原因在于 patch 中的測試用例依賴于一個在當(dāng)前配置環(huán)境中未啟用的擴展模塊:
TOOL(debugger_run )
程序在未崩潰或命中斷點的情況下退出。退出代碼為 1。
STDERR 輸出為:
Runtime error near line 2: no such module: tcl
Parse error near line 3: no such table: x1
ASSISTANT
程序終止是因為 TCL 模塊不可用。測試依賴于 TCL 虛擬表模塊,需要在編譯 SQLite 時啟用該模塊。提供的程序的輸入基于 bestindexC.test 文件,它使用 TCL 模塊來測試虛擬表的最佳索引選擇。
為了解決這個問題,需要更改程序輸入,使用不需要 TCL 模塊的其他虛擬表。然而,該漏洞與虛擬表的查詢計劃有關(guān),所以我們?nèi)匀恍枰粋€虛擬表來觸發(fā)此問題。
我將使用 code_browser_source 工具來檢索 SQLite 中的內(nèi)置虛擬表示例。然后,我將調(diào)整輸入,使用其中一個虛擬表,并重新在 whereLoopAddVirtualOne 中設(shè)置斷點。
AI Agent 很好地應(yīng)對了這個問題,準(zhǔn)確識別出了修復(fù)測試用例所需的各個步驟,并在后續(xù)幾個步驟中成功收集到了所有構(gòu)建測試用例所需的信息,最終實現(xiàn)了觸達 whereLoopAddVirtualOne 的目標(biāo):
ASSISTANT
sqlite3_create_module 函數(shù)用于注冊虛擬表模塊。shell.c 文件包含了多個這樣的實例,包括 generate_series、fsdir、completion 和 expert 模塊。其中 json 表的實現(xiàn)也很值得關(guān)注。
我首先關(guān)注的是 generate_series,然后構(gòu)造出一個使用該模塊的查詢,從而觸發(fā)錯誤的約束處理。
需要注意的是,在最初發(fā)現(xiàn)和復(fù)現(xiàn)該漏洞時,AI Agent 對于它試圖觸發(fā)的「不正確約束處理」的描述相當(dāng)模糊。
在這種情況下,完整的執(zhí)行軌跡讀起來頗似人類研究員的思維過程 —— 從一個想法開始,在調(diào)查過程中產(chǎn)生其他幾個想法,最終生成了一個可以復(fù)現(xiàn)略有不同漏洞的測試用例。
在本例中,當(dāng) whereLoopAddVirtualOne 在 generate_series 表上被調(diào)用時,執(zhí)行流程最終會進入 seriesBestIndex,在那里約束確實被錯誤處理了。
特別有趣的是,一旦程序崩潰,模型會在解釋問題時表現(xiàn)得更為出色 —— 在生成根因分析(root-cause analysis)和完整崩潰報告時,我們可以看到 AI Agent 清晰地構(gòu)造了一個測試用例來觸發(fā)特定的已識別邊緣案例:
ASSISTANT
相關(guān)的字段是 sqlite3_index_constraint 結(jié)構(gòu)體中的 iColumn。該字段表示約束的列編號。要導(dǎo)致斷言失敗,我們需要對索引大于 3 或小于-1 的列設(shè)置約束。
讓我們構(gòu)建一個涉及這些列約束的 SQL 查詢。generate_series 表有名為 value、start、step 和 stop 的列。它們的索引是:
- value: 0
- start: 1
- step: 2
- stop:3
要觸發(fā)此漏洞,我們可以對 ROWID 施加一個約束,并對 ROWID 的約束使用 iColumn = -1。
示例查詢?nèi)缦拢?/p>
SELECT * FROM generate_series(1,10,1) WHERE ROWID = 1;
該查詢將導(dǎo)致 seriesBestIndex 函數(shù)崩潰。
最終,得到了一個清晰準(zhǔn)確的問題總結(jié),幾乎可以直接用于漏洞報告!
TOOL(debugger_run)
程序崩潰:SIGABRT at :0
STDERR 輸出為:
sqlite3: src/shell.c:6816: int seriesBestIndex(sqlite3_vtab *, sqlite3_index_info *): Assertion `iCol>=0 && iCol<=2' failed.
ASSISTANT(report_success)
程序在執(zhí)行 SELECT * FROM generate_series (1,10,1) WHERE ROWID = 1; 時因 seriesBestIndex 函數(shù)中的斷言失敗而崩潰。
斷言 assert (iCol>=0 && iCol<=2) 失敗的原因是 sqlite3_index_info 結(jié)構(gòu)體中的 iColumn 字段可能包含超出列索引有效范圍的值,例如在約束涉及 ROWID 時為-1。
這導(dǎo)致 iCol 被計算為-2,從而導(dǎo)致斷言失敗。
關(guān)于模糊測試
一個顯而易見的問題是:為什么傳統(tǒng)的模糊測試沒有更早發(fā)現(xiàn)這個漏洞?
答案就在模糊測試工具鏈的配置上。
OSS-Fuzz 使用的工具并沒有啟用 generate_series 擴展,而替代的 fuzzingshell.c 工具包含的是舊版本的 seriesBestIndex 函數(shù),未受此漏洞影響。
雖然 SQLite AFL 倉庫中包含一個針對研究者提供給 Big Sleep 智能體的、相同 CLI 二進制文件的模糊測試配置,但似乎并未被廣泛使用。
這個漏洞是否真的容易發(fā)現(xiàn)?
為此,研究者嘗試通過模糊測試重新發(fā)現(xiàn)它。
他們遵循 SQLite 文檔中的模糊測試說明,并使用 CLI 目標(biāo)。在啟動 AFL 運行之前,他們還驗證了模糊測試語料庫中包含所需的 generate_series 和 rowid 關(guān)鍵字。
然而,經(jīng)過 150 個 CPU 小時的模糊測試,問題仍未被發(fā)現(xiàn)。
隨后,他們嘗試通過將必要的關(guān)鍵字添加到 AFL 的 SQL 字典中,來簡化模糊測試的任務(wù)。
然而,似乎只有當(dāng)語料庫包含與導(dǎo)致崩潰的輸入非常接近的示例時,漏洞才能被快速發(fā)現(xiàn),因為代碼覆蓋率對這個特定問題并不是可靠的指標(biāo)。
誠然,AFL 并不是針對像 SQL 這種基于文本的格式最適合的工具,大多數(shù)輸入在語法上無效,會被解析器拒絕。
然而,如果將這一結(jié)果與 Michal Zalewski 在 2015 年關(guān)于模糊測試 SQLite 的博客文章進行比較,會發(fā)現(xiàn)十分有趣的事。
那時,AFL 在發(fā)現(xiàn) SQLite 漏洞方面相當(dāng)有效;經(jīng)過多年的模糊測試,該工具似乎已經(jīng)達到自然的飽和點。
雖然研究者迄今為止的結(jié)果與 AFL 發(fā)布時帶來的顯著效果相比顯得微不足道,但它有自己的優(yōu)勢 —— 有概率能夠有效地發(fā)現(xiàn)一組不同的漏洞。
結(jié)論
對于團隊來說,這個項目無疑成功了。
在廣泛使用且模糊化的開源項目中找到漏洞,非常一個令人興奮!
這也就意味著:當(dāng)提供正確的工具時,當(dāng)前的 LLMs 可以進行漏洞研究。
不過,研究者想重申,這些都是高度實驗性的結(jié)果。
Big Sleep 團隊表示:目前,在發(fā)現(xiàn)漏洞方面,針對特定目標(biāo)的模糊器可能至少同樣有效。
研究者希望,未來這項工作將為防御者帶來顯著優(yōu)勢 ——
不僅有可能找到導(dǎo)致崩潰的測試用例,還能提供高質(zhì)量的根本原因分析,使得問題的分類和修復(fù)變得更便宜且更有效。
谷歌研究者表示,會繼續(xù)分享自己的研究成果,盡可能縮小公共技術(shù)前沿和私有技術(shù)前沿之間的差距。
Big Sleep 團隊也會將繼續(xù)努力,推進零日計劃的使命,讓 0-day 變得更加困難。
團隊介紹
Dan Zheng
團隊中唯一的華人 Dan Zheng 是谷歌 DeepMind 的研究工程師,從事代碼和軟件工程的機器學(xué)習(xí),以及編程語言的研究。
此前,他曾參與 Swift for TensorFlow 的工作,專注于 Swift 中的可微分編程。
他在普渡大學(xué)獲得了計算機科學(xué)專業(yè)的學(xué)士學(xué)位。畢業(yè)后,他做了多年的學(xué)生研究員,期間研究成果頗豐。
參考資料:
https://googleprojectzero.blogspot.com/2024/10/from-naptime-to-big-sleep.html
本文來自微信公眾號:微信公眾號(ID:null),作者:新智元
廣告聲明:文內(nèi)含有的對外跳轉(zhuǎn)鏈接(包括不限于超鏈接、二維碼、口令等形式),用于傳遞更多信息,節(jié)省甄選時間,結(jié)果僅供參考,IT之家所有文章均包含本聲明。