細(xì)說實(shí)現(xiàn):大模型是如何被投毒的
這幾天字節(jié)的大模型事件鬧得沸沸揚(yáng)揚(yáng),一名實(shí)習(xí)生居然能給公司造成巨量的損失,不少人覺得不可思議。但從方法上來說,其實(shí)是可以達(dá)到的。這篇文章,作者就給我們分享了如何實(shí)現(xiàn)的辦法。
這兩天,字節(jié) GPU 投毒事件沸沸揚(yáng)揚(yáng):
和朋友們細(xì)聊了這個(gè)事兒,也在這里給大家盤一盤。
根據(jù)公開信息,推測(cè)一下可能的實(shí)現(xiàn)方法,或?yàn)槿齻€(gè)方面:
- 惡意代碼執(zhí)行
- 擾亂模型訓(xùn)練
- 代碼隱藏與對(duì)抗
下面介紹每個(gè)唯維度可能攻擊的手法,以及如何進(jìn)行安全防護(hù)。
一、惡意代碼執(zhí)行
攻擊者通過精心設(shè)計(jì)的模型文件或數(shù)據(jù)集,利用底層庫(kù)的漏洞,引發(fā)遠(yuǎn)程代碼執(zhí)行(RCE),從而獲得控制權(quán)。在這種攻擊中,即便攻擊者沒有直接的集群 SSH 權(quán)限,也可以通過以下幾種方式悄無聲息地執(zhí)行惡意代碼。
1. 有關(guān) transformer
以 transformers 庫(kù)為例,已經(jīng)發(fā)現(xiàn)了多起相關(guān)的安全漏洞:
- CVE-2024-3568:該漏洞影響 transformers 庫(kù)版本低于 4.38.0,主要利用 TFAutoModel 的反序列化過程觸發(fā)惡意代碼執(zhí)行。
- CVE-2023-7018:影響版本低于 4.36.0 的 transformers 庫(kù),tokenizer 解析存在類似的反序列化漏洞。
- CVE-2023-6730:涉及 RagRetriever.from_pretrained 方法,影響版本同樣是低于 4.36.0。
這些漏洞的存在,意味著如果攻擊者能夠控制模型文件內(nèi)容,便可通過反序列化行為,在模型加載的瞬間就可以觸發(fā)惡意代碼執(zhí)行。
2. trust_remote_code:遠(yuǎn)程代碼執(zhí)行的“后門”
在 transformers 庫(kù)中,還有一個(gè)較為隱蔽的危險(xiǎn)選項(xiàng):trust_remote_code。這個(gè)參數(shù)允許從遠(yuǎn)程服務(wù)器加載代碼,并直接在本地執(zhí)行。它的初衷是為了方便開發(fā)者快速獲取并使用最新的模型和功能,但同時(shí)也給了攻擊者一個(gè)可乘之機(jī)。
當(dāng) trust_remote_code=True 時(shí),攻擊者可以誘導(dǎo)用戶加載一個(gè)經(jīng)過篡改的模型,而這個(gè)模型會(huì)包含惡意代碼。一旦加載,惡意代碼將在本地執(zhí)行,可能導(dǎo)致系統(tǒng)被入侵、數(shù)據(jù)泄露,甚至模型訓(xùn)練過程被完全掌控。
目前大多數(shù)開源模型的官方教程都默認(rèn)開啟這個(gè)選項(xiàng),如果倉(cāng)庫(kù)權(quán)限被控制,后果不堪設(shè)想。
3. 惡意數(shù)據(jù)集
除了模型文件,攻擊者還可以通過偽造數(shù)據(jù)集來達(dá)到執(zhí)行惡意代碼的目的。
huggingface 的 datasets 庫(kù)是目前最流行的數(shù)據(jù)集加載工具之一,但該庫(kù)也存在一個(gè)潛在的安全風(fēng)險(xiǎn):如果下載的數(shù)據(jù)集中包含與數(shù)據(jù)集同名的 Python 腳本,datasets 庫(kù)在加載數(shù)據(jù)時(shí)會(huì)自動(dòng)執(zhí)行該腳本。
換句話說,攻擊者可以通過嵌入惡意代碼在數(shù)據(jù)集中,來實(shí)現(xiàn)遠(yuǎn)程代碼執(zhí)行。
官方已明確指出,這一行為是 datasets 的“特性”而非漏洞,但這無疑給了攻擊者一個(gè)可利用的機(jī)會(huì)。
二、擾亂模型訓(xùn)練:隱蔽的“暗手”如何影響 AI 模型
在 GPU 模型投毒攻擊中,觸發(fā)惡意代碼執(zhí)行只是開始。更為隱蔽且難以察覺的是攻擊者通過精細(xì)化手段,直接干擾模型的訓(xùn)練過程。這不僅讓模型的最終效果變得不可預(yù)測(cè),甚至可能導(dǎo)致模型朝著錯(cuò)誤的方向訓(xùn)練,產(chǎn)生嚴(yán)重的商業(yè)后果。本文將揭示幾種常見的擾亂模型訓(xùn)練的方式,讓大家更加警惕這一隱秘的威脅。
1. 修改模型層輸出:讓模型“產(chǎn)生幻覺”
在深度學(xué)習(xí)模型的訓(xùn)練過程中,模型的每一層都會(huì)輸出中間結(jié)果,并依次傳遞到下一層。如果攻擊者在這些中間層的輸出上做手腳,模型的表現(xiàn)將會(huì)變得極為混亂。
一種常見的方式是向模型的某些層(例如 lm_head)加入鉤子函數(shù),疊加隨機(jī)數(shù)或噪聲。這種“微調(diào)”看起來不起眼,但由于大模型的自回歸特性,早期層的微小擾動(dòng)會(huì)在模型后續(xù)的輸出中被逐漸放大,最終導(dǎo)致模型產(chǎn)生“幻覺”,生成錯(cuò)誤甚至荒謬的結(jié)果。
示例:在輸出層添加鉤子
在沒有鉤子之前,模型可能會(huì)輸出正確的預(yù)測(cè)結(jié)果。然而,加入鉤子并疊加隨機(jī)噪聲后,輸出結(jié)果可能逐步偏離正常軌道:
經(jīng)過這樣的篡改,模型在訓(xùn)練過程中就會(huì)逐漸偏離正軌,生成大量錯(cuò)誤的預(yù)測(cè)。特別是在超大規(guī)模自回歸模型中,這樣的擾亂會(huì)隨著生成過程不斷放大,最終導(dǎo)致整個(gè)訓(xùn)練數(shù)據(jù)無效。
加鉤子前輸出結(jié)果:
加鉤子后輸出結(jié)果:
2. 篡改優(yōu)化器
優(yōu)化器是模型訓(xùn)練的核心模塊,負(fù)責(zé)根據(jù)梯度更新模型參數(shù)。如果攻擊者能夠篡改優(yōu)化器的行為,模型的訓(xùn)練過程將變得極其不穩(wěn)定,甚至根本無法收斂。
攻擊者可以通過修改優(yōu)化器的 step 方法,加入延時(shí)或隨機(jī)清空梯度等操作,來偽造正常的訓(xùn)練狀態(tài)。例如,以下代碼通過簡(jiǎn)單的延時(shí)操作拖慢了訓(xùn)練過程,這不僅會(huì)增加訓(xùn)練時(shí)間,還可能影響訓(xùn)練的整體效果:
更嚴(yán)重的是,攻擊者可以通過隨機(jī)化梯度或參數(shù),直接破壞模型的訓(xùn)練進(jìn)程。例如,清空優(yōu)化器的梯度或隨機(jī)篡改參數(shù)值,都會(huì)使模型訓(xùn)練陷入混亂,無法正常更新參數(shù)。
3. 篡改梯度方向
深度學(xué)習(xí)模型的訓(xùn)練過程依賴于梯度下降法,通過不斷調(diào)整參數(shù),使模型逐漸收斂到最優(yōu)解。而梯度的方向正是參數(shù)更新的“指南針”,如果這個(gè)“指南針”被篡改,模型就會(huì)朝著錯(cuò)誤的方向前進(jìn),訓(xùn)練出的模型可能完全失效。
攻擊者可以通過修改梯度的方向來擾亂模型訓(xùn)練。例如,簡(jiǎn)單地反轉(zhuǎn)梯度方向就可以讓模型的參數(shù)朝著與預(yù)期相反的方向更新,使得模型無法收斂,甚至訓(xùn)練出一個(gè)帶有后門的模型。
這種方式雖然隱蔽,但后果卻極其嚴(yán)重。模型不僅會(huì)訓(xùn)練出錯(cuò)誤的結(jié)果,甚至可以被設(shè)計(jì)成帶有特定行為的“后門模型”,在特定條件下生成攻擊者預(yù)期的輸出。
三、代碼隱藏與對(duì)抗
在 GPU 模型投毒的攻擊鏈條中,代碼隱藏與對(duì)抗是攻擊者最隱蔽、最難防范的環(huán)節(jié)。通過巧妙地隱藏惡意代碼,攻擊者可以長(zhǎng)時(shí)間不被察覺,持續(xù)影響模型訓(xùn)練,甚至在面對(duì)內(nèi)部調(diào)查時(shí),依然能夠“全身而退”。本章將揭示攻擊者是如何通過篡改庫(kù)文件、動(dòng)態(tài)加載代碼等手法,隱蔽地進(jìn)行攻擊,以及如何對(duì)抗這些潛在威脅。
1. 篡改 site-packages 目錄:持久化“幽靈攻擊”
在 Python 環(huán)境下,site-packages 目錄存放著項(xiàng)目依賴的第三方庫(kù)(如 transformers、torch 等)。攻擊者可以通過篡改這些常用庫(kù)的代碼,將惡意代碼嵌入其中,達(dá)到持久化攻擊的目的。
由于這些庫(kù)被頻繁調(diào)用,攻擊者可以在庫(kù)的初始化代碼或關(guān)鍵函數(shù)(如模型加載、優(yōu)化器更新、梯度計(jì)算等)中加入惡意代碼,每次庫(kù)被加載時(shí),惡意代碼都會(huì)悄無聲息地執(zhí)行。這種方式不僅能保證攻擊的持續(xù)性,還十分隱蔽,因?yàn)殚_發(fā)者或運(yùn)維人員通常不會(huì)頻繁審查這些已安裝的庫(kù)文件。
示例:篡改初始化代碼
攻擊者可以在庫(kù)的初始化代碼中插入惡意操作,并偽裝成正常的加載過程,難以被察覺。比如,以下代碼展示了如何在庫(kù)加載時(shí)執(zhí)行惡意代碼:
這種篡改方式非常隱蔽,因?yàn)?site-packages 目錄下的文件往往不在日常的代碼審查范圍內(nèi),攻擊者可以“潛伏”在系統(tǒng)中,悄悄執(zhí)行惡意操作。
2. Python 運(yùn)行時(shí)動(dòng)態(tài)加載:無痕跡篡改核心函數(shù)
除了直接篡改 Python 庫(kù)文件,攻擊者還可以通過動(dòng)態(tài)加載的方式,修改模型訓(xùn)練中的關(guān)鍵函數(shù)(如 backward()、step()等),以便在不修改顯著代碼的情況下,悄悄改變模型的訓(xùn)練行為。
這種方法利用 Python 語言的動(dòng)態(tài)特性,攻擊者可以在訓(xùn)練框架初始化之前,提前注入代碼,改變函數(shù)的返回值或行為。例如,攻擊者可以修改 backward()函數(shù),使得梯度計(jì)算出現(xiàn)偏差,或修改 step()函數(shù),干擾優(yōu)化器的正常更新。
示例:動(dòng)態(tài)修改函數(shù)行為
以下代碼展示了如何通過動(dòng)態(tài)加載篡改模型的關(guān)鍵函數(shù):
通過這種動(dòng)態(tài)篡改,攻擊者可以在不直接修改代碼文件的情況下,影響模型的訓(xùn)練過程。這種方式尤為隱蔽,開發(fā)者可能在調(diào)試時(shí)發(fā)現(xiàn)不了任何異常。
3. 對(duì)抗內(nèi)部調(diào)查
為了進(jìn)一步隱藏惡意行為,攻擊者往往會(huì)為惡意代碼設(shè)置特定的觸發(fā)條件,只有在特定情況下才會(huì)執(zhí)行。例如,攻擊者可以設(shè)置只有當(dāng)任務(wù)使用 256 張 GPU 時(shí),惡意代碼才會(huì)被觸發(fā),這使得日常的小規(guī)模訓(xùn)練任務(wù)不會(huì)檢測(cè)到任何異常。
此外,攻擊者可能會(huì)利用內(nèi)部的調(diào)試工具或渠道,悄悄修改代碼并隨時(shí)調(diào)整攻擊策略。比如,通過內(nèi)部的 debug 群組,攻擊者可以實(shí)時(shí)監(jiān)控訓(xùn)練任務(wù)的進(jìn)展,隨時(shí)修改惡意代碼或增加新的觸發(fā)條件。這大大增加了內(nèi)部調(diào)查的難度。
示例:設(shè)置觸發(fā)條件
攻擊者可以通過簡(jiǎn)單的條件判斷,控制惡意代碼的觸發(fā)時(shí)機(jī):
這種方式讓惡意代碼在大多數(shù)情況下處于“休眠”狀態(tài),只有在特定條件滿足時(shí)才會(huì)執(zhí)行,進(jìn)一步增加了調(diào)查和排查的難度。最后
最后預(yù)測(cè)一下某字節(jié)的攻擊手法:推測(cè)是基于其公司內(nèi)部 AI 訓(xùn)練平臺(tái)正常員工權(quán)限,利用訓(xùn)練組件漏洞執(zhí)行了惡意代碼,并進(jìn)一步篡改模型輸出、優(yōu)化器與修改梯度方向?qū)崿F(xiàn)來擾亂 GPU 集群中的模型訓(xùn)練結(jié)果,同時(shí)由于該內(nèi)鬼員工還進(jìn)行了隱藏與持續(xù)修改代碼等對(duì)抗操作,導(dǎo)致了其公司在較長(zhǎng)時(shí)間后才調(diào)查清楚。
本文由人人都是產(chǎn)品經(jīng)理作者【賽博禪心】,微信公眾號(hào):【賽博禪心】,原創(chuàng)/授權(quán) 發(fā)布于人人都是產(chǎn)品經(jīng)理,未經(jīng)許可,禁止轉(zhuǎn)載。
題圖來自Unsplash,基于 CC0 協(xié)議。
- 目前還沒評(píng)論,等你發(fā)揮!