您所在的位置: 首頁 >
新聞資訊 >
技術(shù)前沿 >
基于圖神經(jīng)網(wǎng)絡(luò)的源碼漏洞檢測方法研究
摘? 要:
針對現(xiàn)有的靜態(tài)代碼分析工具有較高的誤報率與漏報率,提出一種基于切片依賴圖(Slice Dependency Graph,SDG)的自動化漏洞檢測方法,將程序源代碼解析為包含數(shù)據(jù)依賴和控制依賴信息的切片依賴圖,然后使用圖神經(jīng)網(wǎng)絡(luò)對切片依賴圖的結(jié)構(gòu)進(jìn)行表征學(xué)習(xí),最后使用訓(xùn)練的神經(jīng)網(wǎng)絡(luò)模型預(yù)測待測程序源代碼中的漏洞。在 5 類常見缺陷分類(Common Weakness Enumeration,CWE)樣本構(gòu)成的數(shù)據(jù)集上開展了實驗,結(jié)果表明誤報率和漏報率均低于作為對比的其他方法,準(zhǔn)確率和 F1 得分兩個指標(biāo)均有提高,因此所提方法能有效提高漏洞檢測能力。
內(nèi)容目錄:
1 方法介紹
1.1 生成程序依賴圖
1.2 切? 片
1.3 符號化和向量化
1.4 訓(xùn)練圖神經(jīng)網(wǎng)絡(luò)
2 實驗設(shè)計和結(jié)果分析
2.1 實驗數(shù)據(jù)集
2.2 實驗設(shè)計與評價指標(biāo)
2.3 實驗結(jié)果分析
3 結(jié) 語
導(dǎo)致軟件漏洞的原因有軟件設(shè)計錯誤、編碼質(zhì)量不高、安全測試不充分等。攻擊者可以利用漏洞進(jìn)行惡意操作,竊取或更改敏感信息,破壞或控制計算機(jī)系統(tǒng),對信息安全產(chǎn)生極大的威脅。在提高軟件安全性方面,漏洞檢測是基本手段。傳統(tǒng)的靜態(tài)漏洞檢測方法估計程序運行時的行為而不需要執(zhí)行它,常用于在軟件開發(fā)過程中發(fā)現(xiàn)潛在的漏洞。典型的靜態(tài)分析工具包括 Coverity、FlawFinder、RATS、Fortify 等。這些工具在檢測內(nèi)存崩潰漏洞方面效果較好,但在檢測大量漏洞方面有所不足。靜態(tài)分析工具往往依賴于基于專家知識人工構(gòu)造的漏洞模式庫。隨著軟件復(fù)雜性持續(xù)增加,人工構(gòu)造漏洞模式庫的成本越發(fā)高昂,且人的主觀性會影響漏洞檢測的誤報率和漏報率。
軟件的長期運行積累了大量的歷史數(shù)據(jù),因此可以利用機(jī)器學(xué)習(xí)方法學(xué)習(xí)并挖掘與軟件漏洞相關(guān)的歷史數(shù)據(jù)。與靜態(tài)分析檢測漏洞方法相比,基于機(jī)器學(xué)習(xí)的漏洞檢測方法能有效降低漏洞的漏報率。隨著人工智能技術(shù)的快速發(fā)展和開源倉庫的發(fā)展,研究者開始使用深度學(xué)習(xí)技術(shù)檢測漏洞。華中科技大學(xué)團(tuán)隊的一系列工作 VulDeePecker、SySeVR、VulDeeLocator等使用雙向長短期記憶 網(wǎng) 絡(luò)(Bi-directional Long Short-Term Memory,BiLSTM) 和 雙 向 門 控 循 環(huán) 單 元(Bi-directional Gated Recurrent Unit,BiGRU)模型學(xué)習(xí)漏洞特征。目前流行的方法是將代碼的各種表示形式如抽象語法樹、程序依賴圖等轉(zhuǎn)換成一個平鋪的一維序列,然后使用深度學(xué)習(xí)模型,一般是卷積神經(jīng)網(wǎng)絡(luò)(Convolutional Neural Network,CNN)或循環(huán)神經(jīng)網(wǎng)絡(luò)(Recurrent Neural Network,RNN),來學(xué)習(xí)代碼的表示。然而,程序中包含復(fù)雜的上下文關(guān)系,將程序表示成一維序列很難學(xué)習(xí)程序中的結(jié)構(gòu)和上下文信息。
鑒于已有的基于靜態(tài)分析的漏洞檢測方法存在準(zhǔn)確率不高的問題,以及普通 RNN 或 CNN 模型無法學(xué)習(xí)程序中復(fù)雜上下文的缺點,本文提出一種基于切片依賴圖的源碼自動化漏洞檢測方法,使用圖神經(jīng)網(wǎng)絡(luò)(Graph Neural Network,GNN)從切片依賴圖中學(xué)習(xí)代碼的節(jié)點表示和拓?fù)浣Y(jié)構(gòu)信息。本文選擇使用基于線性特征調(diào)制的圖神經(jīng)網(wǎng)絡(luò)(GraphNeural Networks with Feature-wise Linear Modulation,GNN-FiLM) 結(jié) 構(gòu) 來 學(xué) 習(xí) 圖 的 特 征, 有 三 點 原因:一是切片依賴圖是一個有向圖,圖中的邊有方向,無向 GNN 模型不能利用切片依賴圖中邊的方向信息;二是切片依賴圖中存在兩種類型的邊,即數(shù)據(jù)流邊和控制流邊,GNN-FiLM 網(wǎng)絡(luò)可以更好地利用切片依賴圖中邊的類型信息;三是 GNN-FiLM網(wǎng) 絡(luò) 的 性 能 優(yōu) 于 圖 注 意 力 網(wǎng) 絡(luò)(Graph Attention Network,GAT)等網(wǎng)絡(luò)模型。
本文首先使用 Joern 工具將源代碼轉(zhuǎn)換成程序依賴圖;其次通過切片技術(shù)獲取漏洞相關(guān)的子圖,本文稱之為切片依賴圖;再次使用 GNN-FiLM網(wǎng)絡(luò)對切片屬性圖進(jìn)行表示學(xué)習(xí)后進(jìn)行漏洞預(yù)測;最后,在軟件保證引用數(shù)據(jù)集(Software Assurance Reference Dataset,SARD)上做實驗驗證,并比較了 4 種基線方法。實驗結(jié)果表明,相較于基線方法,所提方法能進(jìn)一步提高漏洞檢測能力。
1 方法介紹
本文方法的框架如圖 1 所示。該方法主要包括以下 4 個階段:
(1)提取程序源代碼中的語法和語義信息,解析程序中的數(shù)據(jù)流和控制流信息,得到程序依賴圖;(2)根據(jù)選擇的切點類型將代碼中的相應(yīng)語句設(shè)置為切點,對程序依賴圖做切片,獲取子圖,即切片依賴圖;(3)對切片依賴圖進(jìn)行嵌入(embedding)操作,生成圖的初始向量表示,作為圖神經(jīng)網(wǎng)絡(luò)的輸入;(4) 使 用 GNN-FiLM 網(wǎng) 絡(luò) 學(xué) 習(xí) 圖 特 征, 在經(jīng)過卷積和池化進(jìn)一步提取節(jié)點特征后,聚合所有節(jié)點的特征并輸入到多層感知器(Multi-layer Perceptron,MLP)網(wǎng)絡(luò),經(jīng)過激活函數(shù)分類獲得最終的預(yù)測結(jié)果,0 表示無漏洞,1 表示有漏洞。
1.1 生成程序依賴圖
本文使用 Joern v0.3.1 工具 生成源代碼的程序依賴圖(Program Dependency Graph,PDG)。生成的程序依賴圖中包含“REACHES”和“CONTROLS”2 種 類 型 的 邊, 以 及 與 這 些 邊 相 連 的 節(jié) 點?!癛EACHES”類型的邊連接具有數(shù)據(jù)依賴關(guān)系的語句節(jié)點,“CONTROLS”類型的邊表示代碼中的控制依賴關(guān)系。
1.2 切? 片
漏洞代碼中通常會有與漏洞無關(guān)的語句,因此使用切片技術(shù),盡可能多地去掉與漏洞無關(guān)的代碼。切片時需要選擇感興趣的切點,VulDeePecker使用系統(tǒng) API 調(diào)用作為興趣點,因為錯誤使用這些API 容易引發(fā)漏洞。SySeVR 除使用系統(tǒng) API 調(diào)用作為切點外,還使用了數(shù)組使用(array usage)、指 針 使 用(pointer usage)、 算 術(shù) 操 作(arithmetic operation)3 種類型的切點作為補充,這 4 種切點類型都涉及常見的安全漏洞。通過分析開源項目中經(jīng)常出現(xiàn)的安全修復(fù)(security patch)類型 ,本文在考慮這 4 種類型切點的基礎(chǔ)上,添加返回語句(return expression)、條件語句(condition expression)作為感興趣的切點類型,增加切片對源代碼的覆蓋。
圖 1 本文方法流程
點類型執(zhí)行不同的切片流程。對所有選擇的切點類型,本文執(zhí)行正常的后向切片,獲取影響切點的所有語句;而針對不同的切點類型,執(zhí)行不同的前向切片方法,具體如下文所述。
(1)針對系統(tǒng) API 調(diào)用(其返回值被使用的情況)、數(shù)組使用、指針使用、算數(shù)操作語句,正常執(zhí)行前向切片,即對該行代碼所有變量做前向切片。(2)返回語句。返回語句已經(jīng)是程序執(zhí)行流中最后執(zhí)行的語句,與該語句后面剩余的代碼執(zhí)行不存在依賴關(guān)系,因此不需要執(zhí)行前向切片。(3)條件語句。條件語句會影響程序的執(zhí)行流。因此針對條件語句,對其中參與條件計算的變量都做后向切片,找出條件語句所有的數(shù)據(jù)依賴,并對所有被數(shù)據(jù)依賴的變量都執(zhí)行前向切片,最后將所有結(jié)果合并為一個完整的切片依賴圖。(4)返回值未被使用的函數(shù)調(diào)用語句。對函數(shù)的參數(shù)采用和條件語句相同的切片方法,從而得到一個更完整的切片依賴圖。
得到程序依賴圖后,本文從程序敏感點出發(fā)做切片生成對應(yīng)的切片依賴圖(Slice DependencyGraph,SDG),SDG 的節(jié)點可以通過從程序敏感點出發(fā)做前向和后向切片得到。源程序的控制依賴和數(shù)據(jù)依賴關(guān)系都體現(xiàn)在程序依賴圖中,因此將源程序的切片問題轉(zhuǎn)換成對程序依賴圖的遍歷問題,從本文選擇的程序敏感點所對應(yīng)的節(jié)點出發(fā)沿著數(shù)據(jù)依賴邊和控制依賴邊進(jìn)行圖遍歷,生成切片依賴圖。
本文使用有監(jiān)督方式訓(xùn)練模型,訓(xùn)練時對每個測試數(shù)據(jù)都需要知道它的標(biāo)簽即漏洞數(shù)據(jù)或正常數(shù)據(jù)。訓(xùn)練數(shù)據(jù)中,切片依賴圖的標(biāo)簽依賴于該圖對應(yīng)的程序敏感點所在行是否是漏洞行。如果原始漏洞代碼數(shù)據(jù)集中某代碼行被標(biāo)注為有漏洞,則從該行代碼出發(fā)得到的切片其標(biāo)簽為“1”,表示有漏洞;否則為“0”,表示沒有漏洞。
1.3 符號化和向量化
對生成的切片依賴圖,首先將代碼 tokens 重命名為統(tǒng)一的形式,將函數(shù)名和變量名分別重命名為“FUN_”和“VAR_”的形式,其中下劃線“_”表示數(shù)字,從數(shù)字 0 開始遞增表示每個切片依賴圖中的函數(shù)或變量,降低自定義的函數(shù)和變量名稱對訓(xùn)練 Doc2Vec 模型的影響。
本文使用 Doc2Vec 模型生成切片依賴圖中每個節(jié)點的初始向量。Doc2Vec 模型是一個無監(jiān)督模型,可以將一整句代碼轉(zhuǎn)換成一個固定長度的向量,是Mikolov 基于 Word2Vec 模型提出的,其具有一些優(yōu)點,比如不用固定句子長度,接受不同長度的句子作訓(xùn)練樣本等。
1.4 訓(xùn)練圖神經(jīng)網(wǎng)絡(luò)
本文使用 PyTorch Geometric 框架實現(xiàn)圖神經(jīng)網(wǎng)絡(luò);使用其中的 Data 數(shù)據(jù)結(jié)構(gòu)保存向量化后的切片依賴圖,并輸入到圖神經(jīng)網(wǎng)絡(luò)進(jìn)行學(xué)習(xí);使用FiLM 網(wǎng)絡(luò)學(xué)習(xí)切片依賴圖中的信息。
本文的漏洞檢測目標(biāo)是進(jìn)行圖級(graph-level)分類,在不同關(guān)系下執(zhí)行鄰域聚合過程后,將為每個節(jié)點學(xué)習(xí)到一組新的 embedding,再進(jìn)一步經(jīng)過卷積和池化提取節(jié)點特征,聚合所有節(jié)點特征輸入MLP,經(jīng)激活函數(shù)分類輸出最終預(yù)測的標(biāo)簽,其中,0 為無漏洞,1 為有漏洞。
2 實驗設(shè)計和結(jié)果分析
本文實驗運行在 Ubuntu 18.04 環(huán)境中。語言環(huán)境為 Python 3.8,深度學(xué)習(xí)環(huán)境為 PyTorch 1.10.1,CUDA 10.2,Gensim 4.0,PyTorch Geometric 2.0.3。使 用 的 CPU 為 Intel Xeon E52673 v3,GPU 為NVIDIA Tesla K80(12 GB)。
2.1 實驗數(shù)據(jù)集
本文使用 SARD 數(shù)據(jù)集 [11] 作為訓(xùn)練和測試數(shù)據(jù)集。SARD 數(shù)據(jù)集包含很多來自真實軟件工程項目的安全漏洞,這些漏洞已經(jīng)被相關(guān)軟件開發(fā)者確認(rèn)并修復(fù)。SARD 數(shù)據(jù)集中包含了漏洞所在的行信息,適用于本文使用的按照切點代碼行對切片依賴圖打標(biāo)簽的方法。
綜 合 考 慮 常 見 缺 陷 分 類(Common WeaknessEnumeration,CWE) 2021 top 25 榜單 [12] 中的 CWE類型和 SARD 數(shù)據(jù)集中各種類型 CWE 的測試樣例數(shù) 量, 本 文 選 擇 了 5 種 CWE(CWE-787、CWE-125、CWE-20、CWE-78、CWE-22)完成對比實驗,驗證本文提出方法的有效性。
在對源代碼處理獲得切片依賴圖后,以切點所在的行是否為漏洞行作為打標(biāo)簽的判定標(biāo)準(zhǔn)。如果切點所在代碼行被 SARD 數(shù)據(jù)集標(biāo)為“bad”或者“mixed”,則基于該行得到的切片依賴圖其標(biāo)簽為“1”,表示該樣本有漏洞;否則標(biāo)為“0”,表示無漏洞。
因為不同的程序可能有代碼克隆的情況,所以可能會存在切片結(jié)果中包含重復(fù)的程序依賴圖。這些重復(fù)的樣本可能會導(dǎo)致神經(jīng)網(wǎng)絡(luò)過擬合,且有可能讓本文的結(jié)果虛高,因為可能出現(xiàn)重復(fù)樣本同時出現(xiàn)在訓(xùn)練集和測試集中的情況。為了保證實驗結(jié)果的真實性,本文首先刪除重復(fù)的樣本,只保留重復(fù)樣本中的一個。本文通過對比節(jié)點以及邊來去重,即節(jié)點和邊都相同的樣本視作重復(fù)樣本。同時,SARD 數(shù)據(jù)集中存在很小一部分的數(shù)據(jù)誤標(biāo)情況,導(dǎo)致切片結(jié)果中可能出現(xiàn)同時被標(biāo)記成“0”和“1”的樣本,為了消除數(shù)據(jù)集標(biāo)簽錯誤問題對實驗結(jié)果的影響,本文直接刪除這些樣本。
通過切片,本文使用的切片數(shù)據(jù)集統(tǒng)計如表 1所示。
表 1? 切片數(shù)據(jù)集統(tǒng)計
2.2 實驗設(shè)計與評價指標(biāo)
按照 8 ∶ 1 ∶ 1 的大小將樣本劃分成訓(xùn)練集、驗證集和測試集。學(xué)習(xí)率設(shè)置為 0.001;dropout 設(shè)置為 0.5,防止過擬合;batch size 設(shè)置為 128;最大 epoch 次數(shù)為 50;patience 設(shè)置為 10,即如果連續(xù) 10 次訓(xùn)練迭代中驗證集上的 F1 分?jǐn)?shù)都沒有增加,則停止訓(xùn)練過程。選用 Adam 優(yōu)化器和交叉熵?fù)p失函數(shù)進(jìn)行有監(jiān)督學(xué)習(xí)訓(xùn)練模型。
采 用 誤 報 率(False Positive Rate,F(xiàn)PR)、 漏報率(False Negative Rate,F(xiàn)NR)、準(zhǔn)確率(Accuracy,ACC)和 F1 得分 4 個評價指標(biāo)評價最終模型在測試集上的效果。其中含有漏洞的樣本表示為正類,不含漏洞的樣本表示為負(fù)類。準(zhǔn)確率表示正確分類的概率,F(xiàn)1 得分是精度和召回率的加權(quán)平均值。
2.3 實驗結(jié)果分析
為驗證本文方法的有效性,選用 FlawFinder 和RATS 兩 個 靜 態(tài) 分 析 器 和 VulDeePecker 及 SySeVR兩種基于深度學(xué)習(xí)的漏洞檢測方法,在切片粒度下比較這些工具,如果切片中包含這些工具掃描出存在問題的代碼行,則視為靜態(tài)檢測工具檢測該切片為有漏洞。實驗結(jié)果如表 2、表 3、表 4、表 5、表 6 所示。
表 2? FlawFinder 實驗結(jié)果
表 3? RATS 實驗結(jié)果
表 4? VulDeePecker 實驗結(jié)果
表 5? SySeVR 實驗結(jié)果
表 6? 本文方法實驗結(jié)果
從實驗結(jié)果中可以看出,基于深度學(xué)習(xí)的漏洞檢測方法的效果都明顯好于 RATS 和 Flawfinder 這兩個靜態(tài)分析工具。這兩個靜態(tài)分析工具的誤報率和漏報率較高,主要原因是這兩個工具都是依靠專家定義規(guī)則,根據(jù)詞法分析對測試代碼做模式匹配來挖掘漏洞,在搜索潛在漏洞時沒有使用相關(guān)控制流和數(shù)據(jù)流信息。而真實世界的漏洞邏輯通常比這些規(guī)則要復(fù)雜得多,這一點極大地限制了這些檢測工具。而本文方法由于能自動學(xué)習(xí)漏洞特征,所以無須安全專家制定規(guī)則,并且取得了不錯的效果。
本 文 方 法 的 誤 報 率 和 漏 報 率 均 低 于 VulDee Pecker 和 SySeVR,同時準(zhǔn)確率和 F1 分?jǐn)?shù)持平或優(yōu)于這兩種基于深度學(xué)習(xí)的方法。雖然 VulDeePecker和 SySeVR 使用了程序切片來定位漏洞,考慮了數(shù)據(jù)流和控制流信息,但都是使用 token 序列的方式表征源代碼,將代碼當(dāng)作文本來處理,沒有直接體現(xiàn)出程序中的數(shù)據(jù)流和控制流信息,而且它們對嵌入向量進(jìn)行了截斷,丟失了一些關(guān)鍵的代碼信息。
本文使用圖數(shù)據(jù)結(jié)構(gòu)表示程序中的數(shù)據(jù)依賴和控制依賴關(guān)系,使用圖神經(jīng)網(wǎng)絡(luò)學(xué)習(xí)區(qū)分漏洞代碼和非漏洞代碼,提高了自動檢測能力。圖神經(jīng)網(wǎng)絡(luò)模型的性能和網(wǎng)絡(luò)結(jié)構(gòu)與超參數(shù)有關(guān),訓(xùn)練模型是一個經(jīng)驗性的任務(wù),需要進(jìn)一步優(yōu)化,以改善模型的泛化能力。同時圖神經(jīng)網(wǎng)絡(luò)的可解釋性問題需要進(jìn)一步研究。
3 結(jié) 語
為了檢測源代碼中的漏洞,本文提出一種基于切片依賴圖的漏洞檢測方法。該方法通過將程序源代碼轉(zhuǎn)換成保留數(shù)據(jù)依賴和控制依賴的切片依賴圖,對節(jié)點和邊進(jìn)行編碼后,使用圖神經(jīng)網(wǎng)絡(luò)對圖結(jié)構(gòu)進(jìn)行表示學(xué)習(xí),最后使用圖神經(jīng)網(wǎng)絡(luò)進(jìn)行漏洞預(yù)測。在 SARD 漏洞數(shù)據(jù)集上進(jìn)行了測試驗證,并與 4 種漏洞檢測方法進(jìn)行了實驗對比。實驗結(jié)果體現(xiàn)了本文所提方法在源代碼漏洞檢測方面的有效性。未來將研究構(gòu)建更高質(zhì)量的漏洞數(shù)據(jù)集用于模型訓(xùn)練,以及構(gòu)建更有效的學(xué)習(xí)模型,預(yù)測更豐富的輔助信息,如漏洞定位等。
引用格式:宋子韜 , 胡勇 . 基于圖神經(jīng)網(wǎng)絡(luò)的源碼漏洞檢測方法研究 [J]. 通信技術(shù) ,2022,55(5):640-645.
作者簡介 >>>
宋子韜,男,碩士研究生,主要研究方向為漏洞挖掘;
胡? 勇,男,博士,研究員,主要研究方向為信息系統(tǒng)安全、網(wǎng)絡(luò)內(nèi)容安全、物聯(lián)網(wǎng)安全。
選自《通信技術(shù)》2022年第5期(為便于排版,已省去參考文獻(xiàn))
來源:信息安全與通信保密雜志社