肖添明 管劍波 蹇松雷 任 怡 張建鋒 李 寶
(國(guó)防科技大學(xué)計(jì)算機(jī)學(xué)院 長(zhǎng)沙 410073)
軟件脆弱性是指軟件在開(kāi)發(fā)、部署、執(zhí)行整個(gè)過(guò)程中存在的缺陷,不法分子可利用這些缺陷繞過(guò)系統(tǒng)的訪問(wèn)控制、非法竊取較高的權(quán)限等,這可能造成用戶隱私數(shù)據(jù)泄露、數(shù)字資產(chǎn)被盜、系統(tǒng)信息被更改等安全問(wèn)題,從而導(dǎo)致企業(yè)和個(gè)人巨大的經(jīng)濟(jì)損失和名譽(yù)損失.隨著現(xiàn)在軟件系統(tǒng)的復(fù)雜度越來(lái)越高,規(guī)模越來(lái)越大,脆弱性代碼出現(xiàn)的頻率也在不斷提升.根據(jù)美國(guó)國(guó)家漏洞數(shù)據(jù)庫(kù)(National Vulnerability Database, NVD)[1]公布數(shù)據(jù)顯示,2018年公布的脆弱性代碼數(shù)目為16 511個(gè),2019年公布的脆弱性代碼數(shù)目為17 305個(gè),2020年公布的脆弱性代碼數(shù)目為18 352個(gè).從數(shù)據(jù)中可以看出,脆弱性代碼出現(xiàn)的次數(shù)一直在不斷上升,因此及時(shí)發(fā)現(xiàn)軟件中存在的脆弱性代碼是一份十分重要的工作.
目前檢測(cè)軟件脆弱性的方法主要有靜態(tài)、動(dòng)態(tài)和混合3大類.靜態(tài)方法主要是通過(guò)分析軟件源代碼來(lái)檢測(cè)脆弱性,并不運(yùn)行軟件,對(duì)運(yùn)行環(huán)境的要求較低,檢測(cè)的普適性更強(qiáng).傳統(tǒng)的靜態(tài)方法包括基于規(guī)則的分析[2]、代碼相似性檢測(cè)[3](即代碼克隆檢測(cè))和符號(hào)執(zhí)行[4]等方法.其中,基于規(guī)則的分析主要依靠專家人工去發(fā)現(xiàn)脆弱性代碼的規(guī)則,并對(duì)源代碼進(jìn)行規(guī)則匹配來(lái)檢測(cè)脆弱性;代碼相似性檢測(cè)是將源代碼與脆弱性代碼進(jìn)行相似度比較,進(jìn)而檢測(cè)脆弱性;符號(hào)執(zhí)行是將輸入用符號(hào)來(lái)表征而不是具體值,將程序的執(zhí)行過(guò)程和程序變量表征成符號(hào)表達(dá)式來(lái)發(fā)現(xiàn)脆弱性.傳統(tǒng)的靜態(tài)檢測(cè)方法不能檢測(cè)未知的脆弱性且誤報(bào)率往往比較高[5].與靜態(tài)方法不同,動(dòng)態(tài)方法是通過(guò)實(shí)際運(yùn)行軟件來(lái)尋找脆弱性,因此可以發(fā)現(xiàn)軟件運(yùn)行時(shí)的錯(cuò)誤.動(dòng)態(tài)方法包括模糊測(cè)試[6]和污點(diǎn)分析[7]等方法.模糊測(cè)試主要是通過(guò)向目標(biāo)系統(tǒng)提供非預(yù)期的輸入并監(jiān)視異常結(jié)果來(lái)發(fā)現(xiàn)軟件脆弱性的方法;污點(diǎn)分析主要是通過(guò)實(shí)時(shí)監(jiān)控程序的污點(diǎn)數(shù)據(jù)在系統(tǒng)程序中的傳播來(lái)檢測(cè)數(shù)據(jù)能否從污點(diǎn)源傳播到污點(diǎn)匯聚點(diǎn),進(jìn)而檢測(cè)軟件中的脆弱性.動(dòng)態(tài)測(cè)試方法檢測(cè)準(zhǔn)確率高,但通常十分耗時(shí)并且缺乏完整性,容易出現(xiàn)漏報(bào)的現(xiàn)象.混合方法結(jié)合了靜態(tài)和動(dòng)態(tài)分析技術(shù),與靜態(tài)方法相比降低了誤報(bào)率,與動(dòng)態(tài)方法相比減少了運(yùn)行負(fù)載,但混合方法難以全部實(shí)現(xiàn)自動(dòng)化檢測(cè),并且對(duì)未知脆弱性的檢測(cè)效果相對(duì)較弱.
目前,軟件規(guī)模越來(lái)越龐大和復(fù)雜,脆弱性形式也更趨向多樣化,傳統(tǒng)的軟件脆弱性檢測(cè)方法在處理復(fù)雜且多樣化的脆弱性方面存在困難.與傳統(tǒng)的軟件脆弱性檢測(cè)方法相比,基于機(jī)器學(xué)習(xí)的方法可以從海量數(shù)據(jù)中發(fā)現(xiàn)和學(xué)習(xí)規(guī)律,具有可自動(dòng)尋找脆弱性的特點(diǎn),減少了人工參與度,提高了檢測(cè)的自動(dòng)化程度.基于機(jī)器學(xué)習(xí)的軟件脆弱性檢測(cè)方法能通過(guò)學(xué)習(xí)已有的脆弱性代碼特征檢測(cè)出類似或未知脆弱性.與基于規(guī)則的分析方法相比,無(wú)需人工進(jìn)行規(guī)則的提取,降低了人的主觀性對(duì)于誤報(bào)率和漏報(bào)率的影響等優(yōu)勢(shì);機(jī)器學(xué)習(xí)算法具有自動(dòng)學(xué)習(xí)脆弱性代碼的特點(diǎn),與代碼相似性分析方法相比,在檢測(cè)未知脆弱性方面有一定優(yōu)勢(shì);與符號(hào)執(zhí)行相比,無(wú)需分析程序的執(zhí)行過(guò)程以構(gòu)建執(zhí)行路徑,可檢測(cè)的脆弱性類型更具有一般性;與動(dòng)態(tài)方法相比,無(wú)需運(yùn)行軟件,只需分析軟件源代碼,降低了對(duì)運(yùn)行環(huán)境的配置要求.因此,機(jī)器學(xué)習(xí)方法和工具被逐漸應(yīng)用于軟件脆弱性檢測(cè)領(lǐng)域,代碼表征方式和脆弱性特征提取是該領(lǐng)域的重要關(guān)注點(diǎn).
基于機(jī)器學(xué)習(xí)的軟件脆弱性檢測(cè)方法通常分為4步:1)數(shù)據(jù)預(yù)處理.對(duì)數(shù)據(jù)集進(jìn)行切分、標(biāo)記等預(yù)處理操作.2)代碼表征.利用抽象語(yǔ)法樹(shù)或者代碼度量等信息對(duì)源代碼進(jìn)行表示,并利用詞向量模型將源代碼的表示信息轉(zhuǎn)換成數(shù)值型向量.3)特征提取.利用神經(jīng)網(wǎng)絡(luò)模型學(xué)習(xí)代碼的向量表征,獲取代碼的高級(jí)表示.4)脆弱性檢測(cè).利用機(jī)器學(xué)習(xí)算法學(xué)習(xí)代碼的高級(jí)表示,并以進(jìn)行脆弱性檢測(cè).通過(guò)以上4步就可以利用機(jī)器學(xué)習(xí)的方法來(lái)進(jìn)行脆弱性檢測(cè).由于單一軟件中的軟件脆弱性較少,而機(jī)器學(xué)習(xí)模型需要大量的數(shù)據(jù)來(lái)進(jìn)行訓(xùn)練,因此可用于機(jī)器學(xué)習(xí)模型訓(xùn)練的真實(shí)數(shù)據(jù)集一般由多個(gè)軟件的源代碼混合而成.目前,現(xiàn)有方法已實(shí)現(xiàn)在多個(gè)軟件源代碼混合的真實(shí)數(shù)據(jù)集上做軟件脆弱性檢測(cè),但其誤報(bào)率和漏報(bào)率較高[8].研究發(fā)現(xiàn),現(xiàn)有方法在代碼表征過(guò)程中存在著語(yǔ)法和語(yǔ)義信息的損失[8].
機(jī)器學(xué)習(xí)算法能夠有效學(xué)習(xí)到脆弱性代碼的特征是提高脆弱性檢測(cè)效果的重要因素之一,而在學(xué)習(xí)特征的過(guò)程中學(xué)習(xí)模型的輸入數(shù)據(jù)比學(xué)習(xí)模型的選擇更為重要[9].因此,為了提高特征提取模型和脆弱性檢測(cè)模型輸入數(shù)據(jù)的質(zhì)量,本文在代碼表征和特征提取2個(gè)階段展開(kāi)研究.本文提出了一種基于代碼屬性圖(code property graph, CPG)和Bi-GRU(bi-directional gated recurrent unit)的軟件脆弱性智能檢測(cè)方法,主要改進(jìn)有2個(gè)方面:改進(jìn)代碼的表征方式,降低代碼表征過(guò)程中的信息損失,提高了表征能力;優(yōu)化特征提取模型,提高了模型的脆弱性特征提取能力.本方法首先采用開(kāi)源靜態(tài)分析工具Joern[10]從源代碼中提取出代碼屬性圖,再?gòu)拇a屬性圖中提取出抽象語(yǔ)法樹(shù)序列、控制流圖序列,然后利用Bi-GRU從序列中提取出脆弱性代碼的特征,最后使用隨機(jī)森林模型構(gòu)建脆弱性檢測(cè)器進(jìn)行脆弱性檢測(cè).經(jīng)實(shí)驗(yàn)驗(yàn)證,該方法可有效提高面向多個(gè)軟件源代碼混合的真實(shí)數(shù)據(jù)集的脆弱性檢測(cè)效果,降低誤報(bào)率和漏報(bào)率.本文的主要貢獻(xiàn)包括3個(gè)方面:
1) 提出了一種基于代碼屬性圖的軟件脆弱性智能檢測(cè)方法(vulnerability detection based on code property graph, VDCPG),該方法基于代碼屬性圖對(duì)源代碼進(jìn)行表征,并根據(jù)在LibTIFF數(shù)據(jù)集上的實(shí)驗(yàn)結(jié)果選擇基于Bi-GRU的特征提取模型對(duì)表征向量進(jìn)行特征提取,降低了不同項(xiàng)目編碼風(fēng)格差異對(duì)脆弱性檢測(cè)效果的影響.實(shí)驗(yàn)結(jié)果表明,該方法可有效提高面向多個(gè)軟件源代碼混合的真實(shí)數(shù)據(jù)集的脆弱性檢測(cè)效果,與Lin等人[8]的方法相比,該方法的精確率和召回率最大提高了35%和22%.
2) 針對(duì)現(xiàn)有方法在代碼表征能力不足的問(wèn)題,提出了一種基于代碼屬性圖的表征方式,利用從函數(shù)的代碼屬性圖中提取的抽象語(yǔ)法樹(shù)序列和控制流圖序列對(duì)函數(shù)進(jìn)行表征,以減少代碼表征過(guò)程中的語(yǔ)法和語(yǔ)義信息的損失,提高表征能力.在本文實(shí)驗(yàn)中,與其他表征方式相比,基于代碼屬性圖的表征方式最大可提高30%的精確率和18%的召回率.
3) 在特征提取階段,基于Bi-GRU和Bi-LSTM(bi-directional long short-term memory)構(gòu)建多個(gè)提取模型.通過(guò)實(shí)驗(yàn)發(fā)現(xiàn),與基于Bi-LSTM構(gòu)建的特征提取模型相比,利用Bi-GRU構(gòu)建的特征提取模型最大可提高10%的精確率和6%的召回率.因此本方法選擇利用Bi-GRU構(gòu)建特征提取模型來(lái)挖掘脆弱性代碼的特征,提高特征提取模型的脆弱性特征提取能力,進(jìn)而改善了面向多個(gè)軟件源代碼混合的真實(shí)數(shù)據(jù)集的脆弱性檢測(cè)效果.
隨著人工智能的發(fā)展,基于數(shù)據(jù)驅(qū)動(dòng)的機(jī)器學(xué)習(xí)算法由于其智能化、可自動(dòng)學(xué)習(xí)脆弱性代碼特征的特點(diǎn),被研究者們應(yīng)用到軟件脆弱性檢測(cè)領(lǐng)域,覆蓋了靜態(tài)分析、動(dòng)態(tài)分析以及動(dòng)靜態(tài)分析結(jié)合等典型場(chǎng)景.面向動(dòng)態(tài)分析場(chǎng)景的研究主要針對(duì)緩解模糊測(cè)試、符號(hào)執(zhí)行等動(dòng)態(tài)分析方法存在的程序路徑覆蓋率低、路徑爆炸以及約束求解難等問(wèn)題,將機(jī)器學(xué)習(xí)方法用于測(cè)試輸入生成與篩選、路徑約束求解以及模糊測(cè)試參數(shù)配置預(yù)測(cè)等方面[11].
目前脆弱性檢測(cè)主要基于靜態(tài)分析的方法.在靜態(tài)分析的場(chǎng)景下,基于機(jī)器學(xué)習(xí)的脆弱性檢測(cè)方法可以分為基于詞法、基于語(yǔ)法、基于語(yǔ)義3個(gè)層次[12].
在基于詞法層的機(jī)器學(xué)習(xí)脆弱性檢測(cè)方法中,Neuhaus等人[13]提出組件引用是脆弱性代碼的特征,通過(guò)機(jī)器學(xué)習(xí)的方法從已知的脆弱性代碼中尋找規(guī)律性,以此來(lái)檢測(cè)脆弱性.Yamaguchi等人[14]提出了利用詞法分析來(lái)識(shí)別函數(shù)中的API(application programming interface)調(diào)用并通過(guò)API符號(hào)的詞嵌入向量來(lái)表示函數(shù),然后再用機(jī)器學(xué)習(xí)挖掘API調(diào)用和脆弱性代碼的關(guān)聯(lián)以檢測(cè)軟件脆弱性.Wijayasekara等人[15]發(fā)現(xiàn)在被公開(kāi)報(bào)告和修補(bǔ)的bug中,有一些軟件并未進(jìn)行修復(fù)的現(xiàn)象,提出一種利用文本挖掘技術(shù)從公開(kāi)bug中來(lái)挖掘隱藏脆弱性的檢測(cè)方法.Mokhov等人[16]提出了一種用于靜態(tài)代碼分析和指紋識(shí)別的機(jī)器學(xué)習(xí)方法.Pang等人[17]提出了把N-gram方法和基于統(tǒng)計(jì)的特征選擇結(jié)合起來(lái)進(jìn)行軟件脆弱性檢測(cè)的混合方法.
在基于語(yǔ)法層的機(jī)器學(xué)習(xí)脆弱性檢測(cè)方法中,Yamaguchi等人[18]提出一種從源代碼的抽象語(yǔ)法樹(shù)(abstract syntax tree, AST)中提取特征,再利用機(jī)器學(xué)習(xí)來(lái)進(jìn)行脆弱性檢測(cè)的方法.該方法首先通過(guò)語(yǔ)法分析獲取源代碼的AST,再將AST映射到向量空間使其AST向量化,然后對(duì)大量的樣本進(jìn)行基于奇異值分解(singular value decomposition, SVD)的主成分分析,從而得到矩陣形式的脆弱性結(jié)構(gòu)模式,最后以結(jié)構(gòu)模式為基礎(chǔ),發(fā)現(xiàn)與脆弱性代碼具有相似結(jié)構(gòu)模式的代碼函數(shù).Wang等人[19]提出了一種基于快速序列聚類的軟件脆弱性檢測(cè)方法,該方法利用基于密度的聚類方法對(duì)得到的脆弱性序列進(jìn)行分類,有效地縮小了軟件脆弱性的檢測(cè)范圍,提高了脆弱性檢測(cè)的準(zhǔn)確性和效率.
在基于語(yǔ)義層的機(jī)器學(xué)習(xí)脆弱性檢測(cè)方法中,Cheng等人[20]提出一種基于多子圖聯(lián)合進(jìn)行代碼表征,并用其進(jìn)行脆弱性檢測(cè)并定位的方法.Shar等人[21]針對(duì)基于機(jī)器學(xué)習(xí)的脆弱性檢測(cè)方法只能在文件級(jí)和模塊級(jí)對(duì)脆弱性進(jìn)行檢測(cè)的不足,提出了將機(jī)器學(xué)習(xí)與基于靜態(tài)分析的脆弱性特征分析方法相結(jié)合的脆弱性檢測(cè)方法,該方法利用靜態(tài)污染傳播分析獲取脆弱性代碼的特征,然后使用機(jī)器學(xué)習(xí)方法學(xué)習(xí)SQL(structured query language)注入和跨站腳本攻擊(cross site scripting, XSS)脆弱性的模式,以檢測(cè)脆弱性.Yamaguchi等人[22]針對(duì)在函數(shù)調(diào)用時(shí)由于缺乏輸入檢查而導(dǎo)致的脆弱性的現(xiàn)象展開(kāi)了研究,提出基于聚類分析來(lái)挖掘函數(shù)的輸入檢查模式,缺乏輸入檢測(cè)或者輸入檢測(cè)不正確的函數(shù)即為脆弱性,并提供修復(fù)建議.Medeiros等人[23]針對(duì)已有的污染傳播算法缺少對(duì)清理操作的識(shí)別而導(dǎo)致誤報(bào)的問(wèn)題,通過(guò)機(jī)器學(xué)習(xí)對(duì)污染傳播分析的結(jié)果進(jìn)行挖掘,獲取脆弱性誤報(bào)的模式,進(jìn)而降低污染傳播檢測(cè)中的誤報(bào)率.
基于語(yǔ)義層的機(jī)器學(xué)習(xí)脆弱性檢測(cè)方法與其他2個(gè)層次的脆弱性檢測(cè)方法相比具有可檢測(cè)的脆弱性類型更多的優(yōu)勢(shì),因此越來(lái)越多的研究者在語(yǔ)義層進(jìn)行脆弱性分析的研究.在語(yǔ)義層的脆弱性檢測(cè)方法中,依據(jù)分析對(duì)象,可以將其分為基于二進(jìn)制文件的脆弱性檢測(cè)[24-25]和基于源代碼的脆弱性檢測(cè)[23]2類.Grieco等人[24]提出一種在二進(jìn)制文件上利用機(jī)器學(xué)習(xí)來(lái)檢測(cè)內(nèi)存損壞的方法.但由于二進(jìn)制代碼缺乏上層代碼的結(jié)構(gòu)信息和類型信息等,很難與上層代碼建立對(duì)應(yīng)關(guān)系,分析難度很大,因此基于二進(jìn)制的代碼的脆弱性檢測(cè)算法相對(duì)較少.
基于源代碼的機(jī)器學(xué)習(xí)脆弱性檢測(cè)方法根據(jù)其檢測(cè)的粒度又可以將算法分為文件級(jí)、函數(shù)級(jí)、代碼段級(jí)3類.Shin等人[26]在文件級(jí)用復(fù)雜度、代碼變化和開(kāi)發(fā)人員活動(dòng)作為特征來(lái)刻畫(huà)脆弱性,并利用機(jī)器學(xué)習(xí)方法進(jìn)行檢測(cè).Li等人分別以API調(diào)用[27]、語(yǔ)義特征[28]等為中心,將源代碼切分成代碼段,并將代碼段的文本[29]或編譯[30]后的匯編代碼作為機(jī)器學(xué)習(xí)算法的輸入以進(jìn)行脆弱性檢測(cè).文件級(jí)的脆弱性檢測(cè)存在無(wú)法精確定位脆弱性的位置和脆弱性漏報(bào)率高的問(wèn)題.而代碼段級(jí)的脆弱性檢測(cè)由于缺少完整的語(yǔ)法關(guān)系,很難得到代碼的語(yǔ)法結(jié)構(gòu)信息,只能依賴源代碼的文本信息進(jìn)行脆弱性檢測(cè),但這會(huì)導(dǎo)致較高的漏報(bào)率和誤報(bào)率.我們希望找到一種能夠?qū)崿F(xiàn)較高的脆弱性定位精度與較低的漏報(bào)率和誤報(bào)率的方法,因此選擇函數(shù)級(jí)作為算法的輸入粒度展開(kāi)研究.
軟件脆弱性通常反映在源代碼的語(yǔ)法結(jié)構(gòu)中,尤其是在函數(shù)級(jí)別,因此許多研究者在函數(shù)級(jí)對(duì)脆弱性檢測(cè)展開(kāi)了研究.在基于機(jī)器學(xué)習(xí)的軟件脆弱性檢測(cè)方法中,數(shù)據(jù)預(yù)處理比分類器的選擇更為重要[31],如何將源代碼的文本表示形式轉(zhuǎn)化成可用于模型計(jì)算的向量表示形式是至關(guān)重要的一步.目前常用的代碼表征形式有代碼度量、Token序列、抽象語(yǔ)法樹(shù)和圖.抽象語(yǔ)法樹(shù)[32-33]和圖[34-37]與代碼度量和Token序列相比具有能保存更多代碼語(yǔ)法和語(yǔ)義信息的優(yōu)勢(shì),因此大部分研究者利用抽象語(yǔ)法和圖對(duì)代碼進(jìn)行表征.Lin等人[8]利用CodeSensor[18]工具對(duì)源代碼在函數(shù)級(jí)生成函數(shù)的抽象語(yǔ)法樹(shù),將抽象語(yǔ)法樹(shù)進(jìn)行深度遍歷得到函數(shù)的向量表示,并通過(guò)Word2vec將向量映射成數(shù)值型向量,然后通過(guò)Bi-LSTM和隨機(jī)森林的方法來(lái)進(jìn)行脆弱性檢測(cè).Liu等人[38]在Lin等人算法的基礎(chǔ)上引入遷移學(xué)習(xí)的框架來(lái)解決訓(xùn)練樣本不足的問(wèn)題.為了進(jìn)一步解決訓(xùn)練樣本不足和樣本不平衡的問(wèn)題,Lin等人[39]又提出通過(guò)2個(gè)Bi-LSTM模型來(lái)利用SARD(software assurance reference dataset)數(shù)據(jù)解決數(shù)據(jù)不足問(wèn)題,并通過(guò)調(diào)整權(quán)重和損失函數(shù)來(lái)解決樣本不平衡問(wèn)題.Suneja等人[40]利用Joern工具生成函數(shù)的代碼屬性圖[41](即CPG,包括抽象語(yǔ)法樹(shù)信息、控制流信息和數(shù)據(jù)流信息的聯(lián)合圖型數(shù)據(jù)結(jié)構(gòu)),然后將CPG圖作為函數(shù)的特征表示輸入到圖神經(jīng)網(wǎng)絡(luò)中來(lái)進(jìn)行脆弱性檢測(cè).
以上方法都能從脆弱性代碼中學(xué)習(xí)到脆弱性代碼的特征,在函數(shù)級(jí)對(duì)未知脆弱性進(jìn)行檢測(cè),但在對(duì)多個(gè)軟件源代碼混合的真實(shí)數(shù)據(jù)集進(jìn)行脆弱性檢測(cè)時(shí),有較高的誤報(bào)率和漏報(bào)率.通過(guò)對(duì)現(xiàn)有方法和多個(gè)軟件的真實(shí)數(shù)據(jù)集進(jìn)行研究分析,發(fā)現(xiàn)在現(xiàn)有方法在代碼表征過(guò)程中代碼的語(yǔ)法和語(yǔ)義信息存在較大的損失以及數(shù)據(jù)集中存在著嚴(yán)重的正負(fù)樣本不平衡現(xiàn)象,這是造成現(xiàn)有算法誤報(bào)率和漏報(bào)率較高的主要原因.
為了實(shí)現(xiàn)較高的脆弱性定位精度的軟件脆弱性檢測(cè),需要在較細(xì)粒度實(shí)現(xiàn)脆弱性檢測(cè).文件級(jí)的檢測(cè)粒度太粗,不滿足細(xì)粒度的要求.而代碼段級(jí)存在代碼段切分困難和易出現(xiàn)漏報(bào)、誤報(bào)的問(wèn)題.函數(shù)級(jí)由于函數(shù)在源代碼中分隔明顯,具有易切分的優(yōu)勢(shì).根據(jù)2006—2020年的Linux內(nèi)核脆弱性數(shù)據(jù)顯示,在可獲取源代碼的1 037個(gè)脆弱性中有574個(gè)脆弱性在單個(gè)函數(shù)內(nèi).因此,本方法選擇以函數(shù)為單位進(jìn)行特征提取和脆弱性檢測(cè).
針對(duì)現(xiàn)有方法在多個(gè)軟件混合的真實(shí)數(shù)據(jù)集進(jìn)行脆弱性檢測(cè)時(shí)誤報(bào)率和漏報(bào)率較高的現(xiàn)象,本文分析了現(xiàn)有方法中存在的問(wèn)題并提出了改進(jìn)方法.由于機(jī)器學(xué)習(xí)模型是數(shù)據(jù)驅(qū)動(dòng)的,數(shù)據(jù)的提取方式和內(nèi)容甚至比模型的選擇更加重要[9].現(xiàn)有的函數(shù)級(jí)的基于機(jī)器學(xué)習(xí)的軟件脆弱性檢測(cè)方法一般使用神經(jīng)網(wǎng)絡(luò)和隨機(jī)森林2個(gè)模型,分別實(shí)現(xiàn)特征提取和脆弱性檢測(cè)的功能.這2個(gè)模型的輸入分別是代碼表征的結(jié)果和特征提取模型提取的代碼特征.因此為了提高在多個(gè)軟件混合的真實(shí)數(shù)據(jù)集上的脆弱性檢測(cè)能力,本文對(duì)代碼表征和模型提取2個(gè)階段展開(kāi)研究.
通過(guò)對(duì)函數(shù)級(jí)的基于機(jī)器學(xué)習(xí)的軟件脆弱性檢測(cè)方法的代碼表征方式進(jìn)行調(diào)查和研究發(fā)現(xiàn),現(xiàn)有方法主要是利用抽象語(yǔ)法樹(shù)對(duì)源代碼進(jìn)行表征,但抽象語(yǔ)法樹(shù)缺少控制相關(guān)信息,存在著代碼語(yǔ)法和語(yǔ)義信息的損失的問(wèn)題.為了降低代碼表征過(guò)程中語(yǔ)法和語(yǔ)義信息的損失,提高代碼表征的表征能力,需要選擇合適的表征方式對(duì)源代碼進(jìn)行表征.代碼屬性圖[41]是一種用于代碼查詢的中間代碼表示.它將多個(gè)不同的程序表示合并到一個(gè)聯(lián)合圖數(shù)據(jù)結(jié)構(gòu)中.代碼屬性圖本質(zhì)是一個(gè)邊帶有標(biāo)記的有向多重圖,整合了抽象語(yǔ)法樹(shù)、控制流圖(control flow graph, CFG)和程序依賴圖(program dependency graph, PDG)三種表示形式.由于代碼屬性圖含有的信息比單一抽象語(yǔ)法樹(shù)更加豐富和完整,因此本文選擇利用代碼屬性圖來(lái)進(jìn)行代碼表征.
由于不同項(xiàng)目之間的編碼風(fēng)格差異較大,直接利用函數(shù)的表征來(lái)進(jìn)行脆弱性檢測(cè)效果較差,因此,在得到函數(shù)的代碼表征后,需要對(duì)代碼表征中的信息進(jìn)行進(jìn)一步提取和抽象,降低不同項(xiàng)目之間的編碼風(fēng)格差異對(duì)檢測(cè)效果造成的影響,挖掘出隱藏在代碼表征中的脆弱性編程模式.在特征提取階段,現(xiàn)有方法通?;贐i-LSTM來(lái)構(gòu)建特征提取模型,來(lái)挖掘代碼表征中的脆弱性特征.但Bi-LSTM模型參數(shù)較多,其訓(xùn)練時(shí)間較長(zhǎng),同時(shí)也易出現(xiàn)過(guò)擬合現(xiàn)象.而B(niǎo)i-GRU是Bi-LSTM的一種變體,與Bi-LSTM相比,Bi-GRU參數(shù)更少,具有訓(xùn)練速度更快和不易過(guò)擬合的優(yōu)勢(shì).因此本方法選擇利用Bi-GRU來(lái)構(gòu)建特征提取模型.
針對(duì)2個(gè)階段存在的問(wèn)題,改進(jìn)代碼的表征方式,優(yōu)化特征提取模型,提出了一種基于代碼屬性圖和Bi-GRU的軟件脆弱性檢測(cè)方法.同時(shí)借助Joern工具本方法可以直接應(yīng)用到實(shí)際的項(xiàng)目源代碼文件上,無(wú)需將項(xiàng)目源代碼切分成一個(gè)一個(gè)的函數(shù),由Joern工具自動(dòng)生成函數(shù)的代碼屬性圖,因此本方法將數(shù)據(jù)預(yù)處理階段與代碼表征階段進(jìn)行合并,在對(duì)代碼屬性圖中的信息進(jìn)行提取時(shí)再進(jìn)行相應(yīng)預(yù)處理.本方法的整體框架示意圖如圖1所示,本方法通過(guò)3個(gè)步驟對(duì)待測(cè)軟件進(jìn)行脆弱性檢測(cè):1)代碼表征階段.利用Joern根據(jù)從源代碼中生成代碼屬性圖,并提取代碼屬性圖中的信息作為函數(shù)的表征.2)特征提取階段.利用基于Bi-GRU的特征提取模型提取函數(shù)表征中的脆弱性特征,獲得函數(shù)的特征向量.3)脆弱性檢測(cè)階段.利用隨機(jī)森林模型學(xué)習(xí)函數(shù)特征向量中的脆弱性特征,以此進(jìn)行脆弱性檢測(cè).
Fig. 1 Software vulnerability detection method based on code property graph and Bi-GRU圖1 基于代碼屬性圖和Bi-GRU的軟件脆弱性檢測(cè)方法
代碼屬性圖是一個(gè)圖形的數(shù)據(jù)結(jié)構(gòu),需要選擇合適的方式去提取代碼屬性圖中的信息.Suneja等人[40]利用圖神經(jīng)網(wǎng)絡(luò)來(lái)學(xué)習(xí)代碼屬性圖的特征,進(jìn)而挖掘脆弱性代碼的編程模式.但圖神經(jīng)網(wǎng)絡(luò)更容易學(xué)習(xí)到圖的結(jié)構(gòu)信息而忽略掉節(jié)點(diǎn)中的代碼等文本信息,并且將代碼屬性圖轉(zhuǎn)化成圖神經(jīng)網(wǎng)絡(luò)的輸入所需要的處理過(guò)程更加復(fù)雜.為了合理利用代碼屬性圖中的信息,同時(shí)降低預(yù)處理的復(fù)雜度,本文選擇先將代碼屬性圖轉(zhuǎn)換成序列,然后以序列來(lái)表征函數(shù),最后再利用神經(jīng)網(wǎng)絡(luò)模型提取序列中潛在的編程模式.
基于函數(shù)的代碼屬性圖的代碼表征過(guò)程如圖2所示.首先,從函數(shù)中生成函數(shù)的代碼屬性圖;然后,提取代碼屬性圖中的關(guān)鍵信息,將其轉(zhuǎn)化成序列;接著將文本形式的序列映射成數(shù)值型的向量并根據(jù)設(shè)置的長(zhǎng)度,對(duì)向量進(jìn)行填充和截?cái)嗖僮鞅WC向量長(zhǎng)度一致;最后對(duì)向量進(jìn)行詞嵌入處理,把向量中的每個(gè)元素替換成對(duì)應(yīng)的詞向量,得到詞嵌入向量.通過(guò)以上4步就可以得到函數(shù)的基于代碼屬性圖的表征.
Fig. 2 Code representation extraction process based on code property graph圖2 基于代碼屬性圖的代碼表征提取過(guò)程
為了得到函數(shù)的代碼表征,首先需要生成每個(gè)函數(shù)的代碼屬性圖,本文通過(guò)Joern[10]工具從源代碼中生成代碼屬性圖.Joern是一個(gè)用于分析基于C/C++項(xiàng)目的開(kāi)源工具,它不需要進(jìn)行編譯和依賴庫(kù)就可以從整個(gè)項(xiàng)目或者單個(gè)源文件甚至函數(shù)代碼片段中提取每個(gè)函數(shù)的代碼屬性圖.本文以一個(gè)簡(jiǎn)單的C語(yǔ)言函數(shù)為例,演示基于代碼屬性圖的代碼表征的過(guò)程.圖3所示的是一個(gè)C語(yǔ)言的函數(shù)fun1.
通過(guò)Joern工具可在圖3所示函數(shù)中抽取代碼屬性圖,如圖4所示.代碼屬性圖是一個(gè)有向圖,節(jié)點(diǎn)表示源代碼,這包括低級(jí)語(yǔ)言構(gòu)造(如函數(shù)、變量和控制結(jié)構(gòu)),也包括高級(jí)構(gòu)造(如HTTP端點(diǎn)).每個(gè)節(jié)點(diǎn)都有一個(gè)類型,它是節(jié)點(diǎn)所表示的源代碼的類型,例如類型為“METHOD”的節(jié)點(diǎn)表示函數(shù),類型為“LOCAL”的節(jié)點(diǎn)表示局部變量的聲明.源代碼之間的關(guān)系通過(guò)相應(yīng)節(jié)點(diǎn)之間的邊來(lái)表示.通過(guò)不同類型的邊,可以表示同一圖中的多種關(guān)系.邊有“AST”“CFG”“CDG”“DDG”等類型,其分別表示2個(gè)節(jié)點(diǎn)之間語(yǔ)法關(guān)系、控制關(guān)系、控制依賴和數(shù)據(jù)依賴等關(guān)系.
Fig. 4 A CPG of function fun1圖4 fun1函數(shù)生成的代碼屬性圖
在獲得函數(shù)的代碼屬性圖后,需要對(duì)代碼屬性圖中的信息進(jìn)行進(jìn)一步提取,將其轉(zhuǎn)化成向量的形式,以作為機(jī)器學(xué)習(xí)的輸入,同時(shí)最大程度地保留代碼的結(jié)構(gòu)信息.在生成函數(shù)的代碼屬性圖之后,通過(guò)Joern將代碼屬性圖導(dǎo)出到Json文件中.代碼屬性圖在Json文件中的儲(chǔ)存形式如表1所示:
Table 1 Storage Form of fun1’s Code Property Graph in Json File表1 函數(shù)fun1的代碼屬性圖在Json文件中的儲(chǔ)存形式
在Json文件中,代碼屬性圖中的每個(gè)節(jié)點(diǎn)都存在編號(hào)、類型和代碼等信息,邊是通過(guò)連接的2個(gè)節(jié)點(diǎn)編號(hào)所表示的.由于程序依賴圖無(wú)法表示代碼行內(nèi)部的語(yǔ)法結(jié)構(gòu),不適合用于代碼的結(jié)構(gòu)化表征[42],因此只從代碼屬性圖中提取抽象語(yǔ)法樹(shù)序列和控制流圖序列來(lái)表征函數(shù).通過(guò)分析Json文件中的數(shù)據(jù)后發(fā)現(xiàn),節(jié)點(diǎn)編號(hào)順序含有了代碼屬性圖的結(jié)構(gòu)信息,因此根據(jù)Json文件中節(jié)點(diǎn)的編號(hào)和各節(jié)點(diǎn)之間的關(guān)系,以[類型,代碼,類型,代碼,…]的排序方式,從代碼屬性圖中提取到抽象語(yǔ)法樹(shù)序列和控制流圖序列,以此來(lái)保存代碼的結(jié)構(gòu)信息,提取過(guò)程如算法1所示.
算法1.代碼屬性圖序列提取算法.
輸入:cpg為代碼屬性圖;nodes為代碼屬性圖中的節(jié)點(diǎn),有編號(hào)(id)、代碼(code)和類型(type)三種屬性;edges為代碼屬性圖中的邊,有入節(jié)點(diǎn)編號(hào)(node_in_id)、出節(jié)點(diǎn)編號(hào)(node_out_id)和類型(type)三種屬性.
輸出:AST為抽象語(yǔ)法樹(shù)序列,有節(jié)點(diǎn)編號(hào)序列(ids)和序列內(nèi)容(tokens)兩個(gè)屬性;CFG為控制流圖序列,有節(jié)點(diǎn)編號(hào)序列(ids)和序列內(nèi)容(tokens)兩個(gè)屬性.
①nodes,edges←cpg
/*從代碼屬性圖中提取出節(jié)點(diǎn)和邊*/
② foredgeinedges:
/*遍歷所有的邊*/
③ ifedge.type==“AST” andedge.node_in_idnot inAST.ids:
/*當(dāng)邊為抽象語(yǔ)法樹(shù)的邊時(shí),判斷邊的入節(jié)點(diǎn)編號(hào)是否在抽象語(yǔ)法樹(shù)序列的節(jié)點(diǎn)編號(hào)序列中*/
④node=nodes.find(edge.node_in_id);
/*如果邊的入節(jié)點(diǎn)編號(hào)不在抽象語(yǔ)法樹(shù)序列的節(jié)點(diǎn)編號(hào)序列中,則找到對(duì)應(yīng)的節(jié)點(diǎn)*/
⑤AST.token.append(node.type,node.code);
/*在抽象語(yǔ)法樹(shù)序列的序列內(nèi)容中加入對(duì)應(yīng)節(jié)點(diǎn)的類型和代碼*/
⑥AST.ids.append(node.id);
⑦ else ifedge.type==“AST” andedge.
node_out_idnot inAST.ids:
/*當(dāng)邊為抽象語(yǔ)法樹(shù)的邊時(shí),判斷邊的出節(jié)點(diǎn)編號(hào)是否在抽象語(yǔ)法樹(shù)序列的節(jié)點(diǎn)編號(hào)序列中*/
⑧node=nodes.find(edge.node_out_id);
/*如果邊的出節(jié)點(diǎn)編號(hào)不在抽象語(yǔ)法樹(shù)序列的節(jié)點(diǎn)編號(hào)序列中,則找到對(duì)應(yīng)的節(jié)點(diǎn)*/
⑨AST.token.append(node.type,node.code);
/*在抽象語(yǔ)法樹(shù)序列的序列內(nèi)容中加入對(duì)應(yīng)節(jié)點(diǎn)的類型和代碼*/
⑩AST.ids.append(node.id);
node_in_idnot inCFG.ids:
/*當(dāng)邊為控制流圖的邊時(shí),判斷邊的入節(jié)點(diǎn)編號(hào)是否在控制流圖序列的節(jié)點(diǎn)編號(hào)序列中*/
/*如果邊的入節(jié)點(diǎn)編號(hào)不在控制流圖序列的節(jié)點(diǎn)編號(hào)序列中,則找到對(duì)應(yīng)的節(jié)點(diǎn)*/
/*在控制流圖序列的序列內(nèi)容中加入對(duì)應(yīng)節(jié)點(diǎn)的類型和代碼*/
node_out_idnot inCFG.ids:
/*當(dāng)邊為控制流圖的邊時(shí),判斷邊的出節(jié)點(diǎn)編號(hào)是否在控制流圖序列的節(jié)點(diǎn)編號(hào)序列中*/
/*如果邊的出節(jié)點(diǎn)編號(hào)不在控制流圖序列的節(jié)點(diǎn)編號(hào)序列中,則找到對(duì)應(yīng)的節(jié)點(diǎn)*/
/*在控制流圖序列的序列內(nèi)容中加入對(duì)應(yīng)節(jié)點(diǎn)的類型和代碼*/
為了更好地保留代碼的語(yǔ)義信息,需對(duì)節(jié)點(diǎn)的源代碼進(jìn)行進(jìn)一步處理.在程序的源代碼中往往含有很多長(zhǎng)短不一的字符串常量,而程序源代碼中的字符串常量并不影響程序的功能,為了降低字符串常量對(duì)代碼表征的影響,將代碼中的所有字符串用“str”進(jìn)行替換,如語(yǔ)句中存在“printf(“test”)”,將其進(jìn)行替換后為“printf(“str”)”.節(jié)點(diǎn)中的源代碼是以字符串的形式進(jìn)行儲(chǔ)存,需要對(duì)字符串進(jìn)行分割,將變量、操作符、關(guān)鍵字分隔開(kāi),使轉(zhuǎn)化后的序列語(yǔ)義正確,如在節(jié)點(diǎn)中的源代碼是“intx”,將其按變量類型和變量分隔開(kāi)變成“int”和“x”兩個(gè)詞,如表2所示,函數(shù)fun1的抽象語(yǔ)法樹(shù)序列為[METHOD,fun1,PARAM,int,x,…],控制流圖序列為[METHOD,fun1,test2,test2(x),operator.assignment,y,=,test2,(,x,),…].將控制流序列和抽象語(yǔ)法樹(shù)序列合并得到的文本型向量可唯一的標(biāo)識(shí)fun1函數(shù).本文將從代碼屬性圖中得到的控制流序列和抽象語(yǔ)法樹(shù)序列組成的文本型向量稱為ACS(abstract syntax tree and control flow graph sequence),每一個(gè)函數(shù)都可被唯一的ACS表示.
Table 2 Motivating Examples of How Function fun1 is Converted to AST and CFG in Serialized Format
由于后續(xù)的機(jī)器學(xué)習(xí)算法不能識(shí)別文本型向量,只能以數(shù)值型向量作為輸入,因此需要將文本型向量轉(zhuǎn)化成數(shù)值型向量.為了獲取機(jī)器學(xué)習(xí)算法能識(shí)別的輸入,需要構(gòu)建一個(gè)映射來(lái)將向量的每個(gè)文本元素鏈接到一個(gè)整數(shù).這些整數(shù)充當(dāng)“標(biāo)記”,唯一地標(biāo)識(shí)每個(gè)文本元素.例如,將類型“METHOD”映射到“1”,將變量“fun1”映射到“2”,以此類推.通過(guò)用數(shù)字標(biāo)記替換向量的文本元素,它們的序列保持不變.本方法通過(guò)keras分詞器Tokenizer來(lái)實(shí)現(xiàn)這一功能,Tokenizer是一個(gè)用于向量化文本或?qū)⑽谋巨D(zhuǎn)換為序列的類,利用Tokenizer可以將由抽象語(yǔ)法樹(shù)序列和控制流圖序列組成的文本型向量轉(zhuǎn)換成數(shù)值型的向量,如圖1所示,通過(guò)Tokenizer可將文本型向量(METHOD,fun1,PARAM,int,x,…)轉(zhuǎn)化成數(shù)值型向量(1,2,25,…).
由于機(jī)器學(xué)習(xí)模型的輸入為同一長(zhǎng)度的向量,為了統(tǒng)一輸入向量的長(zhǎng)度,需要對(duì)向量進(jìn)行填充和截?cái)?由于每個(gè)函數(shù)的大小不一樣,得到的向量長(zhǎng)度會(huì)不一樣,2個(gè)不同函數(shù)的ACS長(zhǎng)度可能還差別很大.為了平衡向量的長(zhǎng)度和過(guò)稀疏性,應(yīng)該選擇一個(gè)合適的長(zhǎng)度來(lái)填充/截?cái)?對(duì)于長(zhǎng)度大于L的向量,在對(duì)向量末端大于的部分進(jìn)行截?cái)?,?duì)于短向量,在向量末段使用零來(lái)填充,使所有向量長(zhǎng)度統(tǒng)一為L(zhǎng).
為了更好地保留代碼的語(yǔ)義信息,對(duì)向量需要使用詞嵌入進(jìn)行處理.詞嵌入將輸入序列中的每個(gè)“詞”表示為一個(gè)固定維數(shù)的向量.傳統(tǒng)的嵌入方法可能將代碼中的變量、類型或操作符(如“+”和“-”)轉(zhuǎn)換為任意維向量,而忽略各個(gè)詞之間可能存在的關(guān)系.Lin等人[8]通過(guò)將Word2vec的連續(xù)Bag-of-Words(continuous bag-of-words, CBOW)模型生成的詞向量投影到二維平面上發(fā)現(xiàn),語(yǔ)義相近的詞在平面上的位置是相近的,這表明Word2vec的CBOW模型能較好地保留詞之間的關(guān)系,進(jìn)而保留代碼語(yǔ)義.因此,本文也采用這種方式保留代碼語(yǔ)義.
本文利用所有函數(shù)的文本型向量組成的語(yǔ)料庫(kù)對(duì)Word2vec模型進(jìn)行訓(xùn)練,得到映射集,在映射集中語(yǔ)料庫(kù)中每一個(gè)出現(xiàn)頻次達(dá)到閾值的詞都會(huì)有一個(gè)唯一對(duì)應(yīng)的N維的詞向量.本方法通過(guò)在特征提取模型中加入映射層來(lái)實(shí)現(xiàn)向量的詞.利用映射集將向量中的每個(gè)元素轉(zhuǎn)換為N維的詞向量,當(dāng)元素沒(méi)有對(duì)應(yīng)的詞向量時(shí),使用全零的N維向量作為當(dāng)前元素的詞向量.
本文利用了循環(huán)神經(jīng)網(wǎng)絡(luò)(recurrent neural network, RNN)可以保留序列順序信息和降維的特點(diǎn),來(lái)挖掘多個(gè)軟件源代碼的深層順序特征.在RNN的基礎(chǔ)上,采用一個(gè)由RNN、全局最大池化層、Dropout層和密集層組成的模型來(lái)提取抽象語(yǔ)法樹(shù)和控制流圖中的潛在序列特征.
RNN能夠提取復(fù)雜的序列中的順序信息,這使RNN廣泛用于順序相關(guān)數(shù)據(jù)的預(yù)測(cè)任務(wù)中.對(duì)于給定的時(shí)間步長(zhǎng)t,RNN的輸出yt不僅取決于當(dāng)前的輸入xt,還取決于時(shí)間步長(zhǎng)t-1之前的累積信息.該特性為RNN提供了為當(dāng)前預(yù)測(cè)保留過(guò)去有用信息的能力,從而使其成為解決NLP問(wèn)題的強(qiáng)大工具.ACS的元素之間的順序關(guān)系與自然語(yǔ)言中的上下文有很強(qiáng)的相似性,因此將RNN應(yīng)用到本文場(chǎng)景中.因?yàn)锳CS反映了代碼樣本的結(jié)構(gòu)信息,所以改變?nèi)魏卧氐男蛄卸紩?huì)改變結(jié)構(gòu)和語(yǔ)義含義.例如,向量(METHOD,fun1,PARAM,int,x,…)表示fun1函數(shù)有一個(gè)int類型的參數(shù)x.在改變“METHOD”和“PARAM”的序列后,向量(PARAM,fun1,METHOD,int,x,…)在語(yǔ)義上變得沒(méi)有意義,參數(shù)聲明應(yīng)該跟在函數(shù)后.因此,本文將通過(guò)基于RNN的方法來(lái)提取脆弱性代碼中的隱藏順序特征,挖掘脆弱性源代碼的編程模式.
通常,函數(shù)中的脆弱性代碼的編程模式可以與許多行代碼相關(guān)聯(lián).當(dāng)將函數(shù)映射到向量時(shí),與脆弱性相關(guān)的模式與向量的多個(gè)元素相關(guān).標(biāo)準(zhǔn)的RNN能夠處理短期依賴關(guān)系,比如元素“METHOD”后面應(yīng)該接函數(shù)名“fun1”,但是在處理長(zhǎng)期依賴關(guān)系時(shí),比如捕捉與許多連續(xù)或間歇元素相關(guān)的脆弱性編程模式,標(biāo)準(zhǔn)的RNN無(wú)法處理.因此,使用RNN的變體Bi-LSTM和Bi-GRU來(lái)捕獲長(zhǎng)期依賴,以獲取脆弱性代碼的高級(jí)表示.
LSTM(long short-term memory)由輸入門、輸出門、遺忘門、細(xì)胞狀態(tài)等構(gòu)成.LSTM通過(guò)對(duì)細(xì)胞狀態(tài)中的信息遺忘和記憶新的信息以保留對(duì)后續(xù)計(jì)算有用的信息和丟棄無(wú)用的信息,從而達(dá)到處理長(zhǎng)期依賴的目的.Bi-LSTM其本質(zhì)是一個(gè)雙向的LSTM,可以同時(shí)處理前向和后向2個(gè)方向上的信息.對(duì)于時(shí)刻t的輸出,前向LSTM層具有輸入序列中時(shí)刻t以及之前時(shí)刻的信息,而后向LSTM層中具有輸入序列中時(shí)刻t以及之后時(shí)刻的信息.通過(guò)Bi-LSTM可以有效地保留ACS的順序特征,使神經(jīng)網(wǎng)絡(luò)模型可以學(xué)習(xí)到代碼的結(jié)構(gòu)信息.
GRU(gated recurrent unit)是LSTM的一種變體,它比LSTM的結(jié)構(gòu)更簡(jiǎn)單,訓(xùn)練速度更快.在GRU中只有更新門和重置門,更新門決定時(shí)刻t以前的信息對(duì)當(dāng)前時(shí)刻t產(chǎn)生的影響,而重置門決定如何將時(shí)刻t的輸入信息與時(shí)刻t之前的累積信息相結(jié)合.通過(guò)門機(jī)制,GRU也可以提取序列中的長(zhǎng)期依賴關(guān)系.Bi-GRU可以同時(shí)處理雙向的順序信息,因此通過(guò)Bi-GRU可以很好地挖掘代碼中的結(jié)構(gòu)信息,在數(shù)據(jù)量較少時(shí),Bi-GRU的表現(xiàn)比Bi-LSTM更加優(yōu)異.
為了避免出現(xiàn)過(guò)擬合現(xiàn)象,增強(qiáng)模型的魯棒性,本方法在特征提取模型中加入Dropout層.Dropout[43]是在深度學(xué)習(xí)中用來(lái)緩解過(guò)擬合的一種手段,在一定程度上可以達(dá)到正則化的效果.它可以根據(jù)數(shù)值的閾值p,在每個(gè)訓(xùn)練批次中,隨機(jī)選擇隱藏層中的部分節(jié)點(diǎn)失效,以減少隱藏層節(jié)點(diǎn)之間的相互作用,達(dá)到減少過(guò)擬合現(xiàn)象的作用.由于在真實(shí)數(shù)據(jù)集中,脆弱性函數(shù)的數(shù)量較少,存在樣本不平衡的問(wèn)題,在進(jìn)行模型訓(xùn)練時(shí)易出現(xiàn)過(guò)擬合現(xiàn)象.因此,嘗試在模型中加入Dropout層來(lái)緩解過(guò)擬合,以達(dá)到更好的效果.
由于Bi-GRU和Bi-LSTM在不同場(chǎng)景中各有優(yōu)劣,為了更好地挖掘到代碼中的深層特征,達(dá)到更好的檢測(cè)效果,利用Bi-LSTM,Bi-GRU和Dropout構(gòu)建多個(gè)模型,尋找特征提取效果最好的模型.通過(guò)在LibTIFF數(shù)據(jù)集上的初步實(shí)驗(yàn)發(fā)現(xiàn),與基于Bi-LSTM的特征提取模型相比,基于Bi-GRU的特征提取模型脆弱性檢測(cè)的準(zhǔn)確率與召回率提高了5%以上,因此本方法選擇利用Bi-GRU構(gòu)建特征提取模型,模型結(jié)構(gòu)如圖5所示,在全局最大池化層之后增加Dropout層和密集層,形成一個(gè)完整的網(wǎng)絡(luò).由于脆弱性檢測(cè)是一個(gè)二分類問(wèn)題,因此設(shè)置特征提取模型的訓(xùn)練損失函數(shù)為二分類的交叉熵(binary_cross_entropy).在特征提取模型的訓(xùn)練階段,使用不同軟件項(xiàng)目的已知脆弱性代碼混合的數(shù)據(jù)集訓(xùn)練特征提取模型.通過(guò)這些軟件項(xiàng)目可以初始化網(wǎng)絡(luò)參數(shù),以學(xué)習(xí)脆弱性代碼的低級(jí)特征.訓(xùn)練輸入是從ACS映射得到的數(shù)值型向量.輸入數(shù)據(jù)被分為訓(xùn)練集和驗(yàn)證集,用于構(gòu)建和評(píng)估模型,并指導(dǎo)模型調(diào)優(yōu)過(guò)程,以實(shí)現(xiàn)性能最大化.
盡管特征提取模型也可實(shí)現(xiàn)對(duì)代碼進(jìn)行脆弱性檢測(cè)的功能,但在真實(shí)情況中,脆弱性代碼在軟件源代碼中所占比重較低,存在著正負(fù)樣本不均衡的問(wèn)題,特征提取模型無(wú)法處理這一問(wèn)題,導(dǎo)致特征提取模型的脆弱性檢測(cè)能力較弱,誤報(bào)率高,因此本方法只使用特征提取模型提取代碼中的脆弱性特征,通過(guò)其他集成學(xué)習(xí)的方法來(lái)進(jìn)行脆弱性檢測(cè),以降低正負(fù)樣本不平衡帶來(lái)的影響.在特征模型訓(xùn)練完成后,用經(jīng)過(guò)預(yù)處理的從目標(biāo)項(xiàng)目生成的數(shù)值型向量(帶有有限標(biāo)簽)提供給訓(xùn)練好的網(wǎng)絡(luò),并從網(wǎng)絡(luò)的池化層獲得學(xué)習(xí)到的表示.給定一個(gè)長(zhǎng)度L的序列作為網(wǎng)絡(luò)的輸入,學(xué)習(xí)到的表示是一個(gè)Z維的向量,稱為函數(shù)的特征向量.
Fig. 5 The architecture of Bi-GRU network for learning deep CPG representations圖5 學(xué)習(xí)深層CPG表示的Bi-GRU網(wǎng)絡(luò)結(jié)構(gòu)
在得到函數(shù)的特征向量后,需要進(jìn)一步對(duì)特征向量中的脆弱性特征進(jìn)行學(xué)習(xí),以達(dá)到脆弱性檢測(cè)的目的.由于在訓(xùn)練集中的脆弱性函數(shù)較少,大部分分類方法無(wú)法從訓(xùn)練集中學(xué)到脆弱性特征進(jìn)行脆弱性檢測(cè),而隨機(jī)森林是一個(gè)通過(guò)對(duì)訓(xùn)練集的多次采樣構(gòu)建多棵決策樹(shù)來(lái)進(jìn)行分類的集成分類器,有助于解決數(shù)據(jù)不平衡的問(wèn)題,因此選擇隨機(jī)森林作為脆弱性檢測(cè)器,學(xué)習(xí)從神經(jīng)網(wǎng)絡(luò)中得到的特征表示.由于現(xiàn)實(shí)中,脆弱性代碼只占所有代碼中很小的一部分,所以數(shù)據(jù)集會(huì)存在嚴(yán)重的正負(fù)樣本不平衡的現(xiàn)象,因此將隨機(jī)森林的class_weight參數(shù)設(shè)置為“balanced”,盡量降低代碼不平衡帶來(lái)的影響.本文利用少量帶標(biāo)簽的特征向量對(duì)脆弱性檢測(cè)器模型進(jìn)行預(yù)訓(xùn)練,然后利用測(cè)試集來(lái)測(cè)試整個(gè)方法的脆弱性檢測(cè)能力.
當(dāng)使用脆弱性檢測(cè)器來(lái)檢測(cè)時(shí),脆弱性檢測(cè)器會(huì)輸出每個(gè)代碼樣本可能為脆弱性代碼的概率.通過(guò)對(duì)測(cè)試集中所有函數(shù)為脆弱性代碼的概率進(jìn)行排序,即可得到項(xiàng)目中最可能為脆弱性代碼的函數(shù).
使用本文提出的方法構(gòu)建了一個(gè)基于代碼屬性圖的軟件脆弱性檢測(cè)模型.本節(jié)將介紹對(duì)本文方法檢測(cè)能力進(jìn)行評(píng)價(jià)的度量標(biāo)準(zhǔn)以及評(píng)測(cè)數(shù)據(jù)集的構(gòu)成和來(lái)源,并分別從ACS向量長(zhǎng)度、代碼表征方式和特征提取模型等方面驗(yàn)證本文所提出方法的有效性.
本文所有實(shí)驗(yàn)在一臺(tái)配置為GPU(GeForce RTX 2060 SUPER),CPU(i7 10700,8核16線程)的計(jì)算機(jī)上進(jìn)行,操作系統(tǒng)為Ubuntu18.04.4 LTS,內(nèi)核為L(zhǎng)inux kernel 4.18,采用Joern1.29進(jìn)行代碼解析,編程語(yǔ)言為Python3.7,GPU加速環(huán)境為CUDA10.1,cudnn7.6.5,相關(guān)依賴包分別為tensor-flow2.2.0,pandas1.0.1,gensim3.8.3,numpy1.18.1,h5py2.10.0,ijson3.1.2,Keras_Preprocessing1.1.2.
本文方法的檢測(cè)能力是通過(guò)以真實(shí)漏洞函數(shù)在函數(shù)列表所占比例來(lái)評(píng)測(cè)的,該列表根據(jù)模型預(yù)測(cè)的函數(shù)為脆弱性的概率進(jìn)行排序.因此,方法的檢測(cè)能力評(píng)估指標(biāo)是top-k精度(記為P@K)和top-k召回(記為R@K).這些指標(biāo)通常用于信息檢索系統(tǒng)的上下文,如搜索引擎測(cè)量檢索到的實(shí)際有關(guān)的文件在檢索文檔所占比例.在本實(shí)驗(yàn)中,P@K指top-k檢索函數(shù)中脆弱性函數(shù)所占比例,其中R@K表示在檢索到的前k個(gè)函數(shù)中脆弱函數(shù)所占的比例.P@K和R@K計(jì)算為
(1)
(2)
其中,TP@k為返回的k個(gè)樣本中最有可能出現(xiàn)脆弱性的真實(shí)正樣本,即實(shí)際發(fā)現(xiàn)的脆弱性函數(shù);FP@k和FN@k分別為在k個(gè)樣本中檢索到的假陽(yáng)性和假陰性樣本.在實(shí)際情況下中,脆弱性函數(shù)的數(shù)量與非脆弱性函數(shù)的數(shù)量相比少很多.當(dāng)檢索top-k函數(shù)時(shí),期望檢索盡可能多的脆弱函數(shù).在本實(shí)驗(yàn)中,將k設(shè)置成是一個(gè)在10~200之間的可調(diào)整數(shù),以模擬由于時(shí)間和資源的限制而檢索到的函數(shù)數(shù)量有限的實(shí)際情況.
為了構(gòu)建驗(yàn)證改進(jìn)代碼表征方式對(duì)于脆弱性檢測(cè)效果提升的消融實(shí)驗(yàn)(ablation experiment),本文實(shí)驗(yàn)選擇以抽象語(yǔ)法樹(shù)作為代碼表征方式的Lin等人[8]的方法作為對(duì)比對(duì)象.由于應(yīng)用場(chǎng)景不同或不符合消融實(shí)驗(yàn)的原則等原因,本文方法不與其他基于機(jī)器學(xué)習(xí)的函數(shù)級(jí)脆弱性檢測(cè)方法[38-40]進(jìn)行對(duì)比.
為了與Lin等人[8]的工作進(jìn)行比較,本文實(shí)驗(yàn)在Lin等人[8]構(gòu)建的脆弱性數(shù)據(jù)集上進(jìn)行.脆弱性數(shù)據(jù)集包含來(lái)自6個(gè)開(kāi)源項(xiàng)目的脆弱性和非脆弱性的函數(shù),包括FFmpeg,LibTIFF,LibPNG,Pidgin,VLC Media Player和Asterisk,已被按函數(shù)切分并做了標(biāo)記.該數(shù)據(jù)級(jí)脆弱性函數(shù)的標(biāo)簽是根據(jù)美國(guó)國(guó)家漏洞數(shù)據(jù)庫(kù)(National Vulnerability Database, NVD)[1]和公共脆弱性數(shù)據(jù)庫(kù)(Common Vulnerability and Exposure, CVE)[44]網(wǎng)站的數(shù)據(jù)進(jìn)行標(biāo)記的.該數(shù)據(jù)集中丟棄了跨多個(gè)函數(shù)或多個(gè)文件的脆弱性;除去已知的脆弱性函數(shù),將剩余的函數(shù)視為非脆弱性函數(shù).通過(guò)這些函數(shù)級(jí)的脆弱性數(shù)據(jù)可以在函數(shù)級(jí)構(gòu)建脆弱性檢測(cè)器,從而實(shí)現(xiàn)比在文件更細(xì)粒度的檢測(cè)能力.在數(shù)據(jù)集中,所有的脆弱性函數(shù)的源代碼的文件名中會(huì)含有脆弱性的CVE編號(hào),因此將所有所在文件的文件名含有“CVE”字符串的函數(shù)標(biāo)記為脆弱性函數(shù),其余全部標(biāo)記為非脆弱性函數(shù).由于預(yù)處理方式的不同,從上述6個(gè)開(kāi)源項(xiàng)目中獲得的脆弱性代碼樣本數(shù)量和非脆弱性代碼樣本數(shù)量如表3所示.
Table 3 The Number of Vulnerability Functions in the Dataset表3 數(shù)據(jù)集中脆弱性函數(shù)數(shù)量
FFmpeg,LibTIFF,LibPNG這3個(gè)軟件中脆弱性函數(shù)所占比例較高,有利于構(gòu)建訓(xùn)練集和測(cè)試集,因此本文將分別使用這3個(gè)數(shù)據(jù)集作為待測(cè)軟件,對(duì)本文方法進(jìn)行測(cè)試.當(dāng)選定好待測(cè)軟件后,利用其他5個(gè)軟件的數(shù)據(jù)對(duì)特征提取模型進(jìn)行訓(xùn)練,然后將待測(cè)軟件的數(shù)據(jù)劃分成訓(xùn)練集和測(cè)試集,通過(guò)訓(xùn)練集訓(xùn)練脆弱性檢測(cè)模型,并提供測(cè)試集對(duì)方法的脆弱性檢測(cè)能力進(jìn)行測(cè)試.
為模擬單一軟件中已知脆弱性較少的實(shí)際情況,在這組實(shí)驗(yàn)中,在刪去一部分由于函數(shù)切分錯(cuò)誤導(dǎo)致無(wú)法提取代碼屬性圖的函數(shù)后,將數(shù)據(jù)樣本分為:30%的訓(xùn)練數(shù)據(jù)和70%的測(cè)試數(shù)據(jù),經(jīng)過(guò)本文方法和Lin的方法處理后,得到脆弱性函數(shù)數(shù)量和非脆弱性函數(shù)數(shù)量如表4所示.將訓(xùn)練集和測(cè)試集提供給訓(xùn)練好的特征提取模型來(lái)生成函數(shù)的特征向量,該模型是使用除待測(cè)軟件外的其余5個(gè)軟件的所有數(shù)據(jù)集進(jìn)行訓(xùn)練,使用池化層的輸出作為函數(shù)的特征向量.由訓(xùn)練集生成的特征向量將直接作為訓(xùn)練隨機(jī)森林分類器的訓(xùn)練集;由測(cè)試集生成的特征向量作為測(cè)試集來(lái)測(cè)試訓(xùn)練過(guò)的隨機(jī)森林分類器.
Table 4 The Number of Vulnerability Functions in the Training Set and Test Set表4 訓(xùn)練集和測(cè)試集中脆弱性函數(shù)數(shù)量
6.3.1 ACS最大長(zhǎng)度的設(shè)定
由于不同函數(shù)的ACS長(zhǎng)度差別較大,L的取值會(huì)影響到脆弱性檢測(cè)的效果,該實(shí)驗(yàn)通過(guò)變化的取值判斷其取何值時(shí)方法的脆弱性檢測(cè)效果最好,以確定ACS的默認(rèn)長(zhǎng)度.
通過(guò)LibTIFF,LibPNG,Pidgin,VLC Media Player和Asterisk等5個(gè)項(xiàng)目的數(shù)據(jù)對(duì)基于Bi-LSTM的特征提取模型進(jìn)行訓(xùn)練,模型參數(shù)如表5所示:
Table 5 Parameters of Feature Extraction Model表5 特征提取模型的參數(shù)
Fig. 6 Results of different ACS lengths on FFmpeg圖6 不同ACS長(zhǎng)度在FFmpeg上的結(jié)果
利用一部分FFmpeg項(xiàng)目的數(shù)據(jù)對(duì)基于隨機(jī)森林的脆弱性檢測(cè)模型進(jìn)行訓(xùn)練,然后將剩余部分作為測(cè)試集測(cè)試模型效果,結(jié)果如圖6所示.從圖6中可知,在前10、前20、前40、前50和前200個(gè)方法預(yù)測(cè)的最可能的脆弱性函數(shù),當(dāng)L=2 000時(shí),方法預(yù)測(cè)的真實(shí)脆弱性函數(shù)的數(shù)量最多,同時(shí)整體效果最好,因此在后面的實(shí)驗(yàn)中設(shè)置L=2 000.
6.3.2 與已有表征方法的對(duì)比實(shí)驗(yàn)
本實(shí)驗(yàn)通過(guò)對(duì)比不同表征方式對(duì)軟件脆弱性檢測(cè)效果的影響,以驗(yàn)證基于代碼屬性圖的表征方式的有效性.Lin等人[8]利用CodeSensor[16]提取抽象語(yǔ)法樹(shù)對(duì)代碼進(jìn)行表征,AST是以代碼屬性圖中的抽象語(yǔ)法樹(shù)作為函數(shù)的表征方式,ACS是以代碼屬性圖中的抽象語(yǔ)法樹(shù)序列和控制流圖序列作為函數(shù)的表征方式,其特征提取階段使用基于Bi-LSTM(無(wú)Dropout層)的特征提取模型提取特征,以隨機(jī)森林作為脆弱性檢測(cè)模型,由于不同表征方式生成的代碼表征長(zhǎng)度差別較大,本實(shí)驗(yàn)根據(jù)Lin,AST和ACS等3種代碼表征方式在FFmpeg數(shù)據(jù)集上的檢測(cè)效果,將特征提取模型輸入長(zhǎng)度分別設(shè)置成1 000,1 500,2 000,其余參數(shù)如表5所示.本文在FFmpeg,LibTIFF,LibPNG等3個(gè)數(shù)據(jù)集上,對(duì)3種表征方式的表征能力進(jìn)行檢測(cè),其結(jié)果如表6所示.表6中加粗的數(shù)據(jù)為當(dāng)前在3種基于不同表征方式的方法中表現(xiàn)最好的結(jié)果.
Table 6 The Results of Three Characterization Methods on Different Data Sets表6 3種表征方式在不同數(shù)據(jù)集上的結(jié)果
從表6中可以看出,與其他方法相比,以ACS作為表征方式的P@K和R@K在3個(gè)數(shù)據(jù)集中都是最高的.在LibPNG數(shù)據(jù)集上,基于ACS的方法預(yù)測(cè)的前50個(gè)最可能的脆弱性函數(shù)中包含了LibPNG中所有的脆弱性函數(shù),其R@K達(dá)到了100%.與Lin等人[8]的方法相比,基于ACS的方法的P@K和R@K最大提高了30%和18%,而與基于AST的方法相比,基于ACS的方法的P@K和R@K最大提高了17%和8%.實(shí)驗(yàn)結(jié)果表明,在FFmpeg,LibPNG和LibTIFF數(shù)據(jù)集上,以ACS作為表征方式時(shí),方法的脆弱性檢測(cè)效果優(yōu)于另外2種表征方式.
為了更直觀地對(duì)比3種方法的結(jié)果,我們將3種方法在3個(gè)數(shù)據(jù)集上的精確率可視化成折線圖,如圖7所示.從圖7(a)中可以看出,以ACS作為表征方式的方法預(yù)測(cè)的前10~150個(gè)最可能的脆弱性函數(shù)的P@K一直高于另外2種方法,在預(yù)測(cè)的前40個(gè)最可能的脆弱性函數(shù)中,以ACS為表征方式的方法比Lin等人[8]和以AST為表征方式的方法的P@K分別高28%和15%.從圖7(b)中可知,在以LibTIFF作為待測(cè)軟件時(shí),基于ACS的方法預(yù)測(cè)的前20個(gè)最可能的脆弱性函數(shù)的P@K為100%,比另外2種方法表現(xiàn)更加優(yōu)異.從圖7(c)可知,基于ACS的方法在LibPNG數(shù)據(jù)集上預(yù)測(cè)的最可能前30個(gè)最可能的脆弱性函數(shù)P@K一直高于90%,與Lin等人[8]的方法相比,P@K提高了10%.
6.3.3 不同特征提取模型的脆弱性檢測(cè)效果對(duì)比
本節(jié)將對(duì)比不同特征提取模型的脆弱性檢測(cè)效果,以找到最合適的特征提取模型.我們基于Bi-LSTM,Bi-GRU和Dropout構(gòu)建4個(gè)模型.4個(gè)特征提取模型的整體結(jié)構(gòu)與圖5的結(jié)構(gòu)類似,模型參數(shù)如表5所示,Bi-LSTM_1的結(jié)構(gòu)與圖5相比,刪去了Dropout層,并將Bi-GRU替換成了Bi-LSTM,而B(niǎo)i-LSTM_2則只是將Bi-GRU替換成了Bi-LSTM,Bi-GRU_1與圖5的結(jié)構(gòu)相比,刪去了Dropout層,而B(niǎo)i-GRU_2的結(jié)構(gòu)與圖5的結(jié)構(gòu)一致.
本實(shí)驗(yàn)分別將FFmpeg,LibTIFF,LibPNG這3個(gè)數(shù)據(jù)集作為待測(cè)軟件對(duì)特征提取模型進(jìn)行測(cè)試.在FFmpeg上進(jìn)行測(cè)試時(shí),從特征提取模型中獲取FFmpeg數(shù)據(jù)集的特征向量,再用FFmpeg中訓(xùn)練集的特征向量訓(xùn)練脆弱性檢測(cè)模型,最后用FFmpeg中的測(cè)試集來(lái)測(cè)試模型的脆弱性檢測(cè)效果,其結(jié)果如表7所示.
Fig. 7 Detection performance comparison of three characterization methods圖7 3種表征方式的檢測(cè)性能比較
Table 7 The Results of Four Feature Extraction Models on Different Datasets表7 4種特征提取模型在不同數(shù)據(jù)集上的結(jié)果
從表7中可以得到,與Bi-LSTM_1相比,以Bi-GRU_2為特征提取模型的方法的P@K和R@K最大提高了10%和6%,同時(shí)由于Bi-GRU模型的參數(shù)更少,其訓(xùn)練時(shí)間會(huì)比Bi-LSTM模型的訓(xùn)練時(shí)間更少.因此,本方法使用Bi-GRU加Dropout層作為特征提取模型來(lái)進(jìn)行特征提取.
Fig. 8 Detection performance comparison of four feature extraction models圖8 4種特征提取模型的檢測(cè)性能比較
將4個(gè)特征提取模型在3個(gè)數(shù)據(jù)集上的精確率繪制成折線圖,如圖8所示.從圖8(a)可以看出,在FFmpeg數(shù)據(jù)集上,方法預(yù)測(cè)的10~150個(gè)最可能的脆弱性函數(shù)中,以Bi-GRU_2為特征提取模型的方法的R@K為最高的次數(shù),同時(shí)在其預(yù)測(cè)的前150個(gè)最可能的脆弱性函數(shù)中,真正的脆弱性函數(shù)的數(shù)量達(dá)到了69個(gè),占到了FFmpeg中脆弱性函數(shù)總數(shù)量的48%.在圖8(b)(c)中可知,以Bi-GRU_2為特征提取模型的方法的R@K一直高于其他3種特征提取模型.在LibTIFF數(shù)據(jù)集上,以Bi-GRU_2為特征提取模型的方法預(yù)測(cè)前40個(gè)最可能的脆弱性函數(shù)的R@K達(dá)到了100%,優(yōu)于其他3個(gè)模型.在LibPNG數(shù)據(jù)集上,以Bi-GRU_2為特征提取模型的方法預(yù)測(cè)的前40個(gè)最可能的脆弱性函數(shù)包含了LibPNG測(cè)試集中全部的33個(gè)脆弱性函數(shù),R@K達(dá)到了100%.同時(shí)從圖8中可知,在FFmpeg,LibTIFF和LibPNG這3個(gè)數(shù)據(jù)集上,Bi-LSTM_1的檢測(cè)效果優(yōu)于Bi-LSTM_2,這表明在Bi-LSTM的模型中加入Dropout層并沒(méi)有帶來(lái)效果提升,這是由于Bi-LSTM的參數(shù)較多,而數(shù)據(jù)集中脆弱性樣本較少,加入Dropout層后,反而參數(shù)不能及時(shí)得到更新,從而導(dǎo)致檢測(cè)效果變差,而B(niǎo)i-GRU_2的檢測(cè)效果優(yōu)于Bi-GRU_1,這表明在Bi-GRU中加入Dropout層后能夠提升檢測(cè)效果,這是因?yàn)锽i-GRU中所含有的參數(shù)更少,加入Dropout層后反而能有效地學(xué)習(xí)到脆弱性函數(shù)的特征,增強(qiáng)模型的泛化能力.
6.3.4 不同方法的時(shí)間性能的比較
本節(jié)主要比較本文方法和Lin等人[8]方法在時(shí)間方面的性能.從表8中可以看出,本方法與Lin等人[8]的時(shí)間開(kāi)銷主要是模型訓(xùn)練階段和預(yù)處理階段,在檢測(cè)階段的時(shí)間差別不大.同時(shí)Lin等人[8]的方法必須先將項(xiàng)目文件中的函數(shù)提取出來(lái),生成每個(gè)函數(shù)獨(dú)立的代碼文件,才能作為方法的輸入.而VDCPG可直接輸入項(xiàng)目中的代碼文件,無(wú)需切分.本文的數(shù)據(jù)集是已經(jīng)將源代碼根據(jù)函數(shù)切分好的數(shù)據(jù)集,沒(méi)有計(jì)算函數(shù)切分的時(shí)間,因此2種方法在實(shí)際情況中時(shí)間的開(kāi)銷會(huì)更接近.與增加的精確率和召回率而言,增加的時(shí)間開(kāi)銷是可接受的.
Table 8 Comparison of Time Performance
本文針對(duì)現(xiàn)有方法在多個(gè)軟件混合的真實(shí)數(shù)據(jù)集進(jìn)行脆弱性檢測(cè)時(shí)誤報(bào)率和漏報(bào)率較高的現(xiàn)象,在代碼表征和特征提取階段展開(kāi)了研究,發(fā)現(xiàn)現(xiàn)有方法存在代碼表征方式表征能力不足的問(wèn)題,通過(guò)改進(jìn)代碼表征方式,提高表征方式的表征能力,優(yōu)化特征提取模型,增強(qiáng)特征提取模型的特征提取能力,提出了一種基于代碼屬性圖和Bi-GRU的軟件脆弱性檢測(cè)方法.實(shí)驗(yàn)結(jié)果表明,本文提出的基于代碼屬性圖和Bi-GRU的軟件脆弱性檢測(cè)方法可提高面向多個(gè)軟件源代碼混合的真實(shí)數(shù)據(jù)集的脆弱性檢測(cè)效果,降低誤報(bào)率和漏報(bào)率.