陳小全 劉 劍 夏翔宇 周紹翔
1(北京城市學院信息學部 北京 100191)
2(中國科學院網(wǎng)絡測評技術重點實驗室(中國科學院信息工程研究所) 北京 100093)
3(中國科學院大學網(wǎng)絡空間安全學院 北京 100049)
(chenxiaoquan@126.com)
當前軟件中存在的漏洞是引發(fā)軟件安全事件的主要原因.因此在軟件開發(fā)過程中通過靜態(tài)和動態(tài)的檢測技術[1-3]來發(fā)現(xiàn)軟件中存在的漏洞是很重要的工作.軟件漏洞靜態(tài)檢測是通過掃描程序的源代碼或者相應的二進制代碼[4],找到符合軟件漏洞特征代碼片段的過程.其實施流程是,首先根據(jù)各種漏洞的特征,建立對應的漏洞特征庫,如溢出漏洞特征庫、格式化字符串特征庫以及各種CWE 漏洞類型的特征庫.接下來依據(jù)建立的特征庫對程序進行靜態(tài)分析,檢測程序中是否存在匹配某種漏洞特征的漏洞.檢測的大致流程包括建立源代碼模型、構建漏洞特征庫、判定漏洞,以及結果分析等關鍵步驟.檢測的技術有數(shù)據(jù)流分析[5-8](data-flowanalysis)和符號執(zhí)行[9-13](symbolic execution)等.動態(tài)漏洞檢測技術指的是通過實際運行被檢測的程序,記錄程序的執(zhí)行軌跡,分析程序執(zhí)行流程中的數(shù)據(jù)和函數(shù)間的調(diào)用關系等信息,以此檢測程序中是否存在某種類型的漏洞.典型的動態(tài)漏洞檢測技術有模糊測試[14-17](fuzzing test)和動態(tài)污點分析[18-21](dynamic taint analysis,DTA).此外,當前隨著深度學習技術在惡意代碼檢測、垃圾郵件過濾等方面的不斷應用,學術界和工業(yè)界也在不斷地嘗試將深度學習技術應用于軟件漏洞的挖掘和分析當中[22-25].與軟件靜態(tài)和動態(tài)檢測技術相比較,應用深度學習技術進行軟件漏洞挖掘可以實現(xiàn)軟件漏洞的自動化挖掘和分析,大幅度地提高漏洞挖掘的效率和精度.基于該目的,本文提出并實現(xiàn)一種基于比較學習的深度學習方法,其核心思想是為深度學習訓練集中的每個樣本尋找類型相同的樣本和類型不相同的樣本.在模型訓練的過程中,讓模型學習類型相同樣本大量的、細微的特征,也學習類型不相同樣本之間非常明顯的不同特征.通過這種方式,使得深度學習模型的漏洞識別精度大幅度提高,同時也可以檢測多達150 種的CWE 類型的漏洞.
本文的貢獻有3 方面:1)分析和整理了漏洞檢測技術中經(jīng)常使用的SARD 數(shù)據(jù)集.SARD 數(shù)據(jù)集包含了大量的漏洞程序和非漏洞程序,非常適合作為漏洞學習的樣本集.但該漏洞數(shù)據(jù)集里的程序存在一些問題,如存在的非法字符阻礙深度學習模型的學習過程.通過整理,形成了一個源代碼語言的語料庫,可以用于訓練自己的源代碼詞向量模型;一個漏洞數(shù)據(jù)集,可以用于訓練漏洞檢測學習模型.經(jīng)過實驗驗證,使用該數(shù)據(jù)集訓練出來的模型,其漏洞檢測準確率可以達到92.0%.2)分析并討論了基于深度學習的漏洞檢測模型訓練中數(shù)據(jù)集的樣本程序是否符號化對模型的漏洞識別準確率的影響.經(jīng)過實驗驗證與分析,發(fā)現(xiàn)數(shù)據(jù)集中程序樣本符號化與否對深度學習模型的檢測能力并沒有太大的影響.3)提出并實現(xiàn)一種新的深度學習方法—比較學習法.該學習方法的靈感來源于人類的學習方式,人們經(jīng)常通過比較來學習一個新的知識.通過使用這種學習方法,深度學習模型在提取一個程序樣本的特征時,它不是單純從一個樣本中學習程序的特征,而是同時學習該樣本的同類型樣本和非同類型樣本的特征.通過這種方式,模型不但學到了同類型樣本普遍共有的特征,也學習到了非同類型樣本不一樣的特征.這樣,模型提取特征的范圍和視野將更加開闊,有力地阻止過擬合和欠擬合現(xiàn)象的發(fā)生.
基于深度學習的源代碼漏洞檢測的思想來源于自然語言處理技術.在自然語言處理技術中,可以把自然語言當作一種時序字符串序列,然后訓練一個神經(jīng)網(wǎng)絡模型捕捉時序序列中的特征,將其應用于語言識別和機器翻譯等具體的應用.與此類似,程序語言也是一種時序語言,在執(zhí)行的時候也是按照一定時間順序先后執(zhí)行.但程序語言與其他的語言(例如英語)相比,是一種標記語言,或者說是一種“硬語言”,其語法定義可以唯一地解釋代碼含義,計算機也能根據(jù)確定的規(guī)則分析和執(zhí)行代碼.而英語等自然語言的含義和形式會靈活變化,比如含義相同的文章可以有不同的表述,或者文章存在歧義等.從上面的分析不難看出,使用深度學習技術學習程序語言中的特征要比學習自然語言中的特征更加簡單,因為程序語言中的單詞含義唯一確定,不存在二義性.目前,很多的科研工作者已經(jīng)使用深度學習技術提取源代碼程序中缺陷部分的特征,訓練相應的神經(jīng)網(wǎng)絡模型來進行軟件的漏洞檢測.如Russell 等人[22]針對C/C++開源軟件代碼,提出了基于深度學習的函數(shù)級缺陷檢測方法.在文獻[22]的方法中,直接以函數(shù)體為基本單位來識別函數(shù)中是否存在對應的缺陷,但存在的問題是該種方法并不適用于包含跨函數(shù)數(shù)據(jù)依賴關系的代碼缺陷檢測.Li 等人[23]基于深度學習方法實現(xiàn)了程序切片級別的缺陷檢測方法.在文獻[23]的方法中僅采用單一的詞向量作為代碼的特征向量表示,并且基于雙向LSTM 神經(jīng)網(wǎng)絡實現(xiàn)了源代碼缺陷的二分類檢測,但并未在多個特征融合、多種漏洞類型分類等方面做進一步的研究.Zhou 等人[24]實現(xiàn)了基于圖神經(jīng)網(wǎng)絡的源代碼漏洞檢測系統(tǒng)Devign.該系統(tǒng)同樣是二分類的源代碼漏洞檢測系統(tǒng),即給定源代碼來判斷其中是否存在漏洞,但是卻無法識別具體的漏洞類型.Duan 等人[25]實現(xiàn)了基于注意力機制的源代碼缺陷檢測方法 VulSniper,實現(xiàn)了多類源代碼缺陷檢測,但涉及到的源代碼漏洞類型較少,只涉及了CWE119 和CWE399 這2 種缺陷類型.Chakraborty等人[26]和段旭等人[27]基于代碼屬性圖和深度學習技術實現(xiàn)了漏洞檢測方法,但他們的不足在于仍然基于以函數(shù)或程序為單位進行漏洞檢測,并且他們的方法仍然是二分類方法,并不能檢測多種漏洞類型.Zou 等人[28]以及文獻[29]在文獻[23]的基礎上,基于程序中的控制依賴關系,提出稱之為“代碼注意力(code attention)”的新機制.在這種機制中,使用函數(shù)調(diào)用序列作為關鍵特征信息構建了多分類的神經(jīng)網(wǎng)絡模型μVulDeePecker,該模型可以檢測多達40 種的CWE 漏洞類型.Wu 等人[30]使用了CNN與LSTM 的混合模型來進行程序漏洞特征的提取,其實驗結果表明采用混合模型可以提取更多的漏洞特征信息,從而使得模型的檢測效果更好.Nguyen 等人[31]把內(nèi)核方法與雙向循環(huán)神經(jīng)網(wǎng)絡(bidirectional recurrent neural network,BRNN)結合起來,提出了深度代價敏感內(nèi)核機(deep cost sensitive kernel machine,DCKM)模型,可以處理機器指令集序列,實驗結果顯示該模型可以有效解決深度學習數(shù)據(jù)集中存在的數(shù)據(jù)不平衡問題.Li 等人[32]提出了一種基于混合神經(jīng)網(wǎng)絡的源代碼漏洞自動檢測框架.該框架利用低級虛擬機中間表示(LLVM IR)和向后程序切片將輸入轉換為具有顯式結構信息的中間表示,再采用混合神經(jīng)網(wǎng)絡模型對源代碼關鍵序列結構信息進行表征,然后自動化地漏洞檢測.其優(yōu)點在于該表征方式可以兼顧詞法分析并進行細粒度地漏洞挖掘,準確地識別出漏洞的具體位置.Cao 等人[33]針對緩沖區(qū)溢出漏洞和資源管理型漏洞,分別使用CNN 與LSTM提取程序所含漏洞的全局信息和局部的特征信息,實現(xiàn)一種結合了傅里葉變換的深度卷積 LSTM 神經(jīng)網(wǎng)絡模型,并應用在程序的漏洞檢測上面.Mao 等人[34]提出了基于注意力的雙向長短期記憶網(wǎng)絡(attentionbased bidirectional long short-term memory network,ABLSTM)模型,用于漏洞特征提取,取得了較好的漏洞檢測效果,此外該文獻也把深度學習的可解釋性用在漏洞的探測方面,使得深度學習技術不僅可以用在軟件方面,而且也使得內(nèi)在的工作機制為大眾所理解.此外,基于深度學習模型的漏洞檢測技術中還有基于抽象語法樹表征的漏洞挖掘模型[35-36]、基于圖表征的漏洞挖掘模型[37-41]、基于文本表征的漏洞挖掘模型[42-44]以及把抽象語法樹、文本表征、圖表征結合起來的漏洞檢測模型[45-46].
如圖1 所示,本文提出的基于比較學習的漏洞檢測技術分為多個步驟,下面分別介紹每一個步驟以及實現(xiàn)細節(jié).
Fig.1 Overall framework for comparative learning圖1 比較學習整體框架圖
本文采用的源程序數(shù)據(jù)集來自于NIST 軟件保障參考數(shù)據(jù)集(software assurance reference dataset,SARD)項目[47].該數(shù)據(jù)集能夠為研究者提供一些已知的軟件安全漏洞,可用于源碼漏洞檢測模型的訓練.SARD中的源代碼主要包括三大類別:1)“Fix”類型,表示源代碼中的漏洞已被修復,不再包含漏洞;2)“Flaw”類型,表示其中的源代碼含有漏洞;3)“Mixed”類型,表示相關源碼中不僅包含漏洞,同時也含有相應的補丁程序.到目前為止,SARD 共有測試案例251 336條,其中包括C 代碼96 494 個,C++代碼34 133 個,Java 代碼46 438 個,PHP 代碼42 253 個,C#程序32 018個.選取其中的C 程序創(chuàng)建了實驗的數(shù)據(jù)集,如表1所示.
Table 1 Data Set Composition表1 數(shù)據(jù)集構成
從表1 中可以看出,數(shù)據(jù)集中C 程序總數(shù)為96 494個,其中“Fix”類型的程序有568 個,它們沒有漏洞;“Flaw”類型的程序有6 171 個,含有漏洞類型115 種;“Mixed”類型的程序有89 755 個,含有漏洞類型124 種.把Flaw 類型和Mixed 類型重復的漏洞類型去掉后,漏洞類型總數(shù)為180 個.同時,有27 種漏洞類型對應的程序數(shù)量超過了1 000 個,如表1 最后一列所示.
在創(chuàng)建這個數(shù)據(jù)集時,首先對數(shù)據(jù)集中所有的C 代碼進行了檢查,以此發(fā)現(xiàn)其中的一些錯誤.經(jīng)過詳細的檢查,發(fā)現(xiàn)數(shù)據(jù)集中有20 個C 代碼存在字符編碼的錯誤,如表1 第4 列和圖1 中1)所示.這些錯誤當中大部分是雙引號的問題,其余是在語句行的末尾多了一些隱藏的字符,如“SUB”等.這些字符編碼的錯誤會使得在使用JSON 格式保存數(shù)據(jù)集時,產(chǎn)生意想不到的問題.因此對這些文件進行了處理,結果如圖1 中2)所示.
在基于深度學習的漏洞檢測方法中,為了提高模型的泛化能力,普遍都會對數(shù)據(jù)集中的代碼符號化,去除代碼中個性的特征,輔之以用統(tǒng)一的符號來代替這些特征,降低模型提取程序特征的難度,提高模型的泛化能力.基于此,本文基于文獻[26]的方式也對數(shù)據(jù)集中的C 代碼符號化.方式是把程序所有的語句放在一行中,當成一個完整的語句,然后符號化.此外,在符號化的過程中,由于程序語言本身的關鍵字、標準函數(shù)庫、API 函數(shù)庫以及常用的頭文件是程序特有的特征,所以符號化時保存了下來.代碼1 顯示了1 個示例程序源代碼,代碼2 表示把程序放在單獨的一行中,代碼3 表示符號化后的代碼.表2顯示了收集的程序本身的特征信息.數(shù)據(jù)集中代碼符號化完整的流程如圖1 中步驟①~③的1)~4)所示.然而在評價模型的實驗過程中發(fā)現(xiàn),在基于本文提出的比較學習的漏洞檢測方法中,是否對數(shù)據(jù)集中的代碼進行符號化,并不影響模型的漏洞識別能力,這從一個側面反映出本文提出的深度學習漏洞檢測方法具有比較強的學習能力,詳細的實驗內(nèi)容和結果請參閱本文的第3 節(jié).盡管如此,仍然在這里向大家展示深度學習中代碼符號化的具體過程,以此了解深度學習在程序漏洞檢測方面的普遍應用流程.
Table 2 Features of C Language表2 C 語言的特征
代碼1.示例源代碼.
代碼2.代碼中所有的語句放在一行中.
代碼3.符號化后的代碼.
在符號化完數(shù)據(jù)集中的代碼后,就可以創(chuàng)建語料庫,訓練一個新的詞向量模型,如圖1 步驟④中的5)和6)所示.之所以要創(chuàng)建新的語料庫并且訓練一個新的詞向量模型的原因是:當前并沒有一個專門針對C 語言的詞向量模型.現(xiàn)有的word2vec[48-50]模型大多數(shù)是處理自然語言的詞向量模型,并不適合用在某種編程語言上,例如C 語言.而C 語言有其自己的語法、語義和時序特征,這是與自然語言以及其他編程語言最大的不同點.通過創(chuàng)建專門針對C 語言的詞向量模型,可以讓深度學習模型更好地理解C語言的本質特征和內(nèi)在豐富的語義,學習到區(qū)別度更大的漏洞特征.創(chuàng)建語料庫和詞向量模型的具體方式為:首先對數(shù)據(jù)集中經(jīng)過符號化的96 494 個C程序進行單詞統(tǒng)計,得到詞匯量為97 425 010、單詞總數(shù)為24 610 的語料庫.然后使用word2vec 中的CBOW 方法訓練一個詞向量模型.如圖1 步驟⑤中的6)所示.CBOW 是word2vec 中用于將文本表示成向量的一種方法.在CBOW 方法中,通過周圍詞預測中心詞,從而利用中心詞的預測結果,并基于梯度下降法(gradient descent)不斷地去調(diào)整周圍詞的向量,從而獲得整個語料庫中所有單詞的詞向量.此外,也可以使用word2vec 中的Skip-gram 方法來訓練詞向量模型.在實驗中,2 種方法訓練的詞向量模型效果相差不多,這里不贅述.
當詞向量模型訓練完成后,就可以使用該模型來向量化數(shù)據(jù)集里的C 程序代碼.如圖1 步驟⑤所示.具體的實現(xiàn)方式為:1)讀取數(shù)據(jù)集中每一行內(nèi)容(一個完整的C 代碼);2)使用分詞工具NLTK[51-52]將一整行代碼分為若干個單詞;3)對每一個單詞使用前面訓練好的詞向量模型實施向量化,生成維度固定的詞向量;4)將每一個單詞對應的向量進行相加,取平均值,得到整個程序對應的向量,如式(1)所示.其中,XC表示一個C 代碼對應的向量表示,XW表示代碼中一個詞匯的向量表示,n表示代碼中詞匯的數(shù)量.5)重復圖1 步驟①~④,得到數(shù)據(jù)集中所有代碼各自對應的詞向量.結果如圖1 步驟⑥中的7)所示.基于圖1 的步驟①~⑥,得到整個數(shù)據(jù)集中所有程序的向量化表示.
其中W 表示C 代碼中的一個詞匯.
把數(shù)據(jù)集中所有的程序向量化后,就可以創(chuàng)建訓練集樣本和測試集樣本.正如在2.1 節(jié)描述的,數(shù)據(jù)集由96 494 個C 程序構成,有“Fix”“Flaw”“Mixed”這3 種類型的代碼.其中“Fix”類型中的代碼是已經(jīng)修復好的代碼,沒有漏洞;“Flaw”類型的代碼存在漏洞;“Mixed”類型的代碼不但存在漏洞,還有對應的修復好的代碼.基于這樣的特點,創(chuàng)建樣本:1)“Fix”類型的代碼由于沒有漏洞,直接就加入到樣本集里;2)“Flaw”類型的代碼由于性質單一,沒有對應的修復程序,并且每一個漏洞程序都有確定的CWE 類型說明,所以也直接加入到樣本集里,其CWE 類型說明可以作為樣本的漏洞類型標簽;3)“Mixed”類型的代碼不但存在漏洞代碼,而且存在對應的修復程序.基于這樣的特點,首先把漏洞代碼提取出來加入到樣本集中(對應的CWE 類型說明作為樣本標簽);其次把每一個漏洞程序對應的修復程序提取出來加入到樣本集里.這里需要注意的是,“Mixed”類型代碼中的漏洞代碼對應的修復程序數(shù)量不止1 個,有時候1個漏洞代碼有多個對應的修復代碼,其數(shù)量不固定,最少的有1 個,最多的有12 個.采用這3 種方式處理后,獲得了數(shù)量為280 894 的樣本集,其中含有漏洞的代碼95 926 個,漏洞類型總數(shù)為180;不包含漏洞的代碼184 968 個.但在實際的模型訓練過程中,有的漏洞類型對應的樣本數(shù)量非常少,不利于深度學習模型的學習,如CWE133 漏洞類型對應的樣本數(shù)量為1 個,CWE020 對應的樣本數(shù)量為2 個.因此把這些樣本數(shù)量非常少的漏洞類型以及對應的樣本從樣本集里刪除.經(jīng)過修正后的樣本集的樣本總數(shù)為280 793,其中含有漏洞的代碼為95 821 個,漏洞類型總數(shù)為150(詳細的漏洞類型以及對應的樣本數(shù)量請參閱附錄A 中的表A1);不包含漏洞的代碼為184 972 個.到此為止訓練模型需要的數(shù)據(jù)集就創(chuàng)建完成.接下來就可以把數(shù)據(jù)集隨機打亂,根據(jù)一定的比例劃分成訓練集、測試集和驗證集.上面的過程如圖1 步驟⑥和步驟⑦中的7)和8)所示.
比較學習思想的靈感來源于人類的一種學習方式.當人類學習一個分類時,總是尋找和這個類別相似的類和不同的類.從相同類別中學習該類別共有的一些特征,從不同的類別中學習不同類別之間明顯的區(qū)分特征.通過這種方式,人類可以非??斓卣莆漳撤N分類的重要和細微的特征.在本文中,比較學習思想采用3 種方式實現(xiàn).
1)統(tǒng)計訓練集中每一種漏洞類型的樣本數(shù)量,也就是每個樣本屬于哪一種漏洞類型.如算法1 所示.
算法1.統(tǒng)計每一個漏洞類型的樣本數(shù)量.
2)基于1)返回的結果,為訓練集里的每一個樣本尋找漏洞類型相同的樣本和漏洞類型不同的樣本.如算法2 所示.首先,從訓練集Train中選取1 個樣本,稱之為目標樣本;其次,在aDict中刪除該目標樣本,因為目標樣本本身不能作為自己比較學習的樣本;再次,在aDict中獲取與目標樣本類型相同的樣本的數(shù)量,如果該數(shù)值大于Num那么就可以在aDict中隨機選取Num個樣本作為目標樣本的同類型樣本,否則按aDict中實際的樣本數(shù)量為目標樣本選取同類型的樣本;最后,采用上面相同的步驟為目標樣本選取類型不相同的樣本.算法的輸出SameSam和DiffSam分別表示選取的同類型樣本集合和不同類型樣本集合.
算法2.選擇相同樣本和不相同樣本.
3)根據(jù)2)中返回的同類型樣本集合和不同類型樣本集合,構建目標樣本的同類型學習矩陣和不同類型學習矩陣.如算法3 所示.
算法3.創(chuàng)建目標樣本的同類型學習矩陣和不同類型學習矩陣.
在算法3 中,根據(jù)目標樣本的同類型樣本集合SameSam,創(chuàng)建同類型學習矩陣tmatr,然后把矩陣中每一個同類型樣本對應的向量進行相加并取平均值,得到最終的同類型學習矩陣SameMatrix.不同類型樣本集合DiffSam也采取這種方式,得到不同類型樣本集合的學習矩陣DiffMatrix.重復圖1 步驟①~③就可以為訓練集中每一個樣本建立同類型的學習向量和不同類型的學習向量,從而創(chuàng)建比較學習的樣本基礎.這一過程如圖1 步驟⑧中的9)所示.在9)中,第3 行表示目標樣本,第1 行和第2 行表示同類型的樣本,第4 行和第5 行表示不同類型的樣本.當為訓練集建立起比較學習矩陣后,就可以將訓練集以及比較學習矩陣輸入到深度學習網(wǎng)絡中,進行深度學習模型的訓練.
上面介紹了比較學習的核心思想和實現(xiàn)算法,其中必須要考慮的問題是當為數(shù)據(jù)集中的訓練樣本尋找類型相同和類型不相同的學習樣本時,所找的學習樣本的數(shù)量是主要的性能開銷.從直覺上看,所找的學習樣本數(shù)量越多,則深度學習模型訓練過程中將會花費更多的時間和消耗更大的內(nèi)存.而在本文進行的實驗評價過程中也證明了這一點.在實驗中發(fā)現(xiàn),基于比較學習的深度學習模型在訓練過程中的性能開銷與學習樣本的數(shù)量成正比關系,即:學習樣本越多,性能開銷越大.然而在大量的實驗過程中也發(fā)現(xiàn),基于比較學習的深度學習模型漏洞檢測的準確率不會受到學習樣本數(shù)量變化劇烈的影響,也就是學習樣本的數(shù)量與深度學習模型識別漏洞的能力沒有較大的關系.基于這個發(fā)現(xiàn),在使用本文所提出的比較學習方法訓練深度學習模型時,可以選取適當?shù)臄?shù)量值作為學習樣本的數(shù)量,從而降低深度學習模型的性能開銷,但不會對模型識別漏洞的能力造成太大的影響,詳細的實驗過程和結果請參閱3.4.2 節(jié)任務2.
本文采用的深度學習模型是一個簡單的全連接神經(jīng)網(wǎng)絡.因為在研究中發(fā)現(xiàn),即使是簡單的神經(jīng)網(wǎng)絡,基于本文的詞向量模型和比較學習也能獲得較高準確率的漏洞識別效果.本文使用的神經(jīng)網(wǎng)絡示例圖如圖1 步驟⑨中10)所示,詳細的結構如圖2 所示.
Fig.2 Deep learning network architecture圖2 深度學習網(wǎng)絡結構
該深度學習模型包含1 個輸入層模塊、1 個特征抽取層模塊和1 個分類層模塊.其中,輸入層模塊由1 個全連接網(wǎng)絡和ReLU 激活函數(shù)構成.特征抽取層模塊由數(shù)量不固定的全連接網(wǎng)絡構成,在全連接網(wǎng)絡之間采用ReLU 激活函數(shù),以及1 個丟棄層Dropout.分類層模塊由1 個全連接網(wǎng)絡構成,輸出每一個樣本的得分,然后使用Softmax 函數(shù)對得分進行計算后輸出150 個漏洞類別預測的概率值,其中概率值最大的即為最終的分類結果.
模型中使用的損失函數(shù)是交叉熵損失函數(shù)(cross entropy loss),如式(2)中,Closs表示損失值.除此之外,模型中也使用余弦相似度(cosine similarity)公式來計算相同類型向量之間相似性的損失計算,以及不同類型向量之間相似性的損失計算,如式(3)和式(4).其中,式(2)中的M表示漏洞類別的數(shù)量.yic表示符號函數(shù)(0 或者1),如果樣本i的真實類別等于c,則yic=1,否則yic=0.pic表 示樣本i屬于類別c的概率預測值.式(3)中的Sloss表示目標樣本與同類型樣本的相似性計算的損失值,式(4)中的Dloss表示目標樣本與不同類型樣本相似性計算的損失值,Ti,Si,Di分別代表目標樣本、同類型樣本和不同類型樣本向量的各分量.最后,把這3 個損失值進行相加得到最終的模型損失值Loss,如式(5)所示.
實驗所用的計算機使用的CPU 為2 顆E4216,32 核64 線程,主頻為2.1 GHz,顯卡為一塊NVIDIA Quadrp,顯存為4 GB,硬盤容量為3.6 TB,內(nèi)存大小是16 GB.軟件環(huán)境采用Linux 20.04,開發(fā)語言為Python 3.8.深度學習框架采用Pytorch1.10.1+Cuda11.3.
本文采用2.5 節(jié)所構建的數(shù)據(jù)集,樣本總數(shù)為280 793,其中含有漏洞的代碼為95 821 個,漏洞類型總數(shù)為150;不包含漏洞的代碼為184 972 個.樣本集中所有樣本的標簽根據(jù)SARD 數(shù)據(jù)集的注釋進行標注.
在深度學習領域,混淆矩陣是通用的衡量模型性能的指標,該矩陣描述了數(shù)據(jù)集中樣本的實際類別和預測類別之間的混合,即真陽性(true positive,TP)、假陰性(false negative,F(xiàn)N)、假陽性(false positive,F(xiàn)P)和真陰性(true negative,TN).其中,TP表示漏洞代碼被分類正確的情況,F(xiàn)N表示漏洞代碼被分類不正確的情況,F(xiàn)P表示非漏洞代碼被分類為漏洞代碼的情況,TN表示非漏洞代碼被分類為非漏洞代碼的情況.本文使用3 種評估指標:召回率(Recall)、精確率(Precision)和準確率記為(Accuracy),如式(6)~(8)所示.基于評估指標分別繪制模型的精確召回曲線(precision recall curve,PR)、接受者操作特征曲線(receiver operating characteristic curve,ROC).同時,在實驗的過程中也觀察了模型損失函數(shù)值的變化情況.
3.4.1 數(shù)據(jù)集的平衡性問題
如2.5 節(jié)所述,數(shù)據(jù)集中樣本總數(shù)為280 793.其中漏洞代碼數(shù)量為95 821,非漏洞代碼數(shù)量為184 972,包含的漏洞類型為150 種,漏洞種類以及各種漏洞對應的樣本數(shù)量請查閱附錄A 中的表A1.為了直觀地顯示出各種漏洞類型所占的比率,畫出它們的餅狀圖,如圖3 所示(注:由于數(shù)據(jù)集中漏洞類型較多,圖3中并沒有把所有漏洞類型的標注顯示出來).
Fig.3 Vulnerability type distribution of datasets圖3 數(shù)據(jù)集漏洞類型分布
從圖3 中可以看出,這樣的數(shù)據(jù)集存在2 個問題:問題1 是數(shù)據(jù)集中非漏洞代碼的數(shù)量非常大,如圖3中棕色區(qū)域所示;問題2 是漏洞代碼分布情況非常不平衡.這2 個問題都會使得模型產(chǎn)生嚴重的過擬合或欠擬合,降低模型的識別能力.針對這2 個問題采用2 種方式進行解決:1)對數(shù)據(jù)集中的非漏洞代碼進行隨機欠采樣處理,降低非漏洞代碼的比例,處理之后的數(shù)據(jù)集分布情況如圖4 所示.經(jīng)過這樣的處理后,數(shù)據(jù)集中非漏洞代碼的數(shù)量降為16 359,各種漏洞代碼數(shù)量仍為95821.如圖4 中灰色區(qū)域所示,數(shù)據(jù)集中樣本總數(shù)為112180.經(jīng)過處理之后的數(shù)據(jù)集中非漏洞的樣本數(shù)量大幅度地降低,使得數(shù)據(jù)集整體處于基本平衡的狀態(tài).2)把數(shù)據(jù)集中的樣本數(shù)量依據(jù)6:2:2 的比例分為訓練集、測試集和驗證集.訓練集用來訓練模型,測試集用來測試模型的評價指標,驗證集用來驗證模型的漏洞識別效果.正如問題2 數(shù)據(jù)集中各種漏洞類型的樣本數(shù)量存在不平衡的問題,對這個問題的解決采用對訓練集中漏洞數(shù)量較少的漏洞類型進行過度采樣的方法,具體使用邊界線-SMOTE(borderline-SMOTE)技術.之所以不對測試集和驗證集過度采樣,是因為測試集和驗證集是用來檢驗模型的效果,其數(shù)據(jù)分布情況必須保持原始狀況,這樣才能保證測試的真實性和有效性.
Fig.4 Vulnerability type distribution after data set processing圖4 數(shù)據(jù)集處理后的漏洞類型分布
經(jīng)過邊界線-SMOTE 技術處理后的訓練數(shù)據(jù)集中,樣本總數(shù)為239 691,各種漏洞類型平均樣本數(shù)量為1 597,整體分布情況如圖5 所示.從圖5 中可以看出訓練數(shù)據(jù)集中各漏洞類型的數(shù)據(jù)量基本保持平衡,非漏洞的數(shù)據(jù)量占比稍大,如圖5 中綠色部分所示.這和漏洞分布的實際情況保持一致.在真實的漏洞分布中,存在漏洞的程序的數(shù)量畢竟較少,而不存在漏洞的程序較多.到此為止,實驗中需要的數(shù)據(jù)集處理完成.從整體上看該數(shù)據(jù)集符合深度學習訓練對數(shù)據(jù)集平衡性的要求,而且從圖6 中可以看出,在訓練的過程中,模型訓練損失值和測試損失值下降趨勢相同,并且差值比較小,說明模型使用這樣的數(shù)據(jù)集進行訓練,泛化能力較強,可以有效地防止深度學習過程中出現(xiàn)的欠擬合和過擬合現(xiàn)象的發(fā)生.此外,在3.4.2 節(jié)評價實驗中較高的驗證準確率也說明該數(shù)據(jù)是比較合適的,可以應用于模型訓練與檢測的過程.
Fig.5 Vulnerability type distribution after over-sampling圖5 過度采樣后的漏洞類型分布
Fig.6 Changes of accuracy rate and loss value when comparative learning is not used during training圖6 訓練中未使用比較學習時準確率和損失值的變化
3.4.2 實驗評價
為了評價本文所提出的基于比較學習的方法的有效性,設置了3 個實驗任務.任務1 驗證比較學習的漏洞識別的準確率和訓練過程中的損失值變化情況;任務2 對比較學習的性能開銷進行分析;任務3對基于比較學習的模型學習能力進行檢測.在實驗過程中模型的各參數(shù)進行如下的設置:epoch=200,batchsize=2 048,pnum=10,nnum=10,dropout=0.2,learningrate=0.2,其中參數(shù)pnum表示訓練集中每個樣本對應的同類型樣本的數(shù)量,參數(shù)nnum表示訓練集中每個樣本對應的不同類型樣本的數(shù)量,它們都可以取不同的數(shù)值,這里設置為10.
任務1.比較學習在漏洞識別準確率和損失值方面的表現(xiàn).
對于任務1,分為2 組實驗:第1 組實驗比較在本文整理的數(shù)據(jù)集上應用比較學習前后的漏洞識別的準確率和損失值變化情況;第2 組實驗比較在文獻[28]的數(shù)據(jù)集上應用比較學習前后的表現(xiàn).經(jīng)過大量的實驗后,第1 組的實驗結果如圖6 和圖7 所示.其中圖6 顯示了未應用比較學習時模型訓練過程中訓練集、測試集和驗證集的準確率變化,以及訓練集和測試集損失值的變化情況.圖7 顯示了應用比較學習后訓練集、測試集和驗證集的準確率變化,以及訓練集和測試集損失值的變化情況.
Fig.7 Changes of accuracy rate and loss value after comparative learning is used during trinting圖7 訓練中使用比較學習后準確率和損失值的變化
從圖6 中可以看出,未應用比較學習前,模型的訓練集、測試集和驗證集的準確率不高,訓練集準確率為68.5%,測試集的準確率為62.9%,驗證集的準確率為62.5%;而且訓練集和測試集的損失值的下降趨勢不平穩(wěn),波動起伏較大,很不穩(wěn)定.從圖7 中可以看出,在應用比較學習后,模型的訓練集、測試集和驗證集的準確率穩(wěn)步提高,最后趨于平緩,訓練集的準確率達到95%,測試集的準確率達到92.0%,驗證集的準確率達到91.9%(注:由于測試集和驗證集的準確率幾乎相同,所以在圖6 和圖7 中顯示得不明顯).訓練集和測試集的損失值在前20 輪訓練中迅速下降,急速收斂,在之后的訓練中趨于平緩,顯示出模型逐步趨于穩(wěn)定.
在第2 組實驗中,選取文獻[28]的數(shù)據(jù)集驗證本文提出的比較學習方法的效果.文獻[28]使用的數(shù)據(jù)集被稱之為MVD(multiclass vulnerability dataset).在該漏洞數(shù)據(jù)集中,總共有181 641 個被稱為代碼片段(code gadgets)的樣本程序.其中,138 522 個樣本沒有漏洞,43 119 個樣本存在漏洞,其漏洞類型覆蓋40 種CWE 類型的漏洞.在實驗中,仍然按照6:2:2 的比例劃分訓練集、測試集和驗證集.圖8 和圖9 分別展示了在MVD 數(shù)據(jù)集上使用比較學習前后的模型訓練集、測試集和驗證集的準確率變化,以及訓練集和測試集損失值的變化情況.
Fig.8 Changes of accuracy value and loss value for MVD when comparative learning is not used during training圖8 訓練中未使用比較學習時MVD 準確率和損失值的變化
Fig.9 Changes of accuracy value and loss value for MVD after comparative learning is used during training圖9 訓練中使用比較學習后MVD 準確率和損失值的變化
從圖8 中可以看出,未應用比較學習前,文獻[28]的訓練集、測試集和驗證集的準確率不高,訓練集準確率為78.1%,測試集的準確率為73.1%,驗證集的準確率為73.09%;而且訓練集和測試集的損失值的下降趨勢不平穩(wěn),波動起伏較大,很不穩(wěn)定.
從圖9 中可以看出,在應用比較學習后,文獻[28]中的模型訓練集、測試集和驗證集的準確率在比較短的時間內(nèi)急速提高,在將近20 輪時達到95%以上,最后趨于平緩,訓練集的準確率穩(wěn)定在97.9%,測試集的準確率穩(wěn)定在95.9%,驗證集的準確率穩(wěn)定在96.2%(注:由于測試集和驗證集的準確率幾乎相同,圖9 中顯示得不明顯).訓練集和測試集的損失值在前20 輪之內(nèi)迅速下降,急速收斂,在之后的訓練過程中趨于平緩,顯示出模型逐步穩(wěn)定下來.
任務2.比較學習在性能開銷方面的實驗分析.
在比較學習中,由于需要為訓練集中每個樣本選取數(shù)量不同的同類型樣本和不同類型的樣本進行訓練學習,所以比較學習的性能開銷主要花費在為每個樣本選取學習的樣本方面.實驗數(shù)據(jù)集中總共包含150 種不同類型的漏洞樣本,所以為每個樣本選取不同數(shù)量的、不同類型的漏洞樣本時,其數(shù)量上限為150.對于為每個樣本選取漏洞類型相同的樣本,其數(shù)量與不同類型漏洞樣本的數(shù)量類似.因此在實驗中,以數(shù)量5 為步長,遞進地為每個樣本選取數(shù)量不同的同類型樣本和不同類型樣本,然后測量訓練時內(nèi)存的使用量和花費的時間.經(jīng)過30 次實驗后,繪制出了如圖10 所示的比較學習性能開銷圖.當選擇不同數(shù)量的比較學習樣本時,訓練集、測試集和驗證集的準確率變化情況,如圖11 所示.
Fig.10 Changes of model performance varying with the number of comparative learning samples圖10 模型性能隨比較學習樣本數(shù)量的變化
Fig.11 Changes of model accuracy varying with the number of comparative learning samples圖11 模型準確率隨比較學習樣本數(shù)量的變化
從圖10 中可以看出,總體上模型的性能開銷與選取的比較學習的樣本數(shù)量成正比關系,隨著比較學習樣本數(shù)量的增加,模型的性能開銷也逐漸增大.當為訓練集中的每個樣本選取150 個比較學習的樣本時,性能開銷達到最大值,此時內(nèi)存使用量達到614.9 MB,消耗的時間達到1 243 s.但同時在實驗中也觀察到,盡管模型的性能開銷隨著比較學習樣本數(shù)量的增加而增加,但模型的準確率并沒有隨著樣本數(shù)量的增加而劇烈地變化,總體上維持在固定的區(qū)間之內(nèi).訓練集準確率的范圍為0.948~0.952,測試集的準確率范圍為 0.914~0.921,驗證集的準確率范圍為0.915~0.920,如圖11 所示.因此針對這種情況,可以為訓練集中的樣本選取數(shù)量適當?shù)谋容^學習樣本來降低模型的性能開銷,而模型的準確率卻不會發(fā)生大的變化.而且,實驗也從模型的PR 曲線和ROC 曲線衡量了當比較學習樣本的數(shù)量發(fā)生變化時模型的PR 值和ROC 值的變化情況.經(jīng)過大量實驗表明,模型的PR 值和ROC 值總體保持穩(wěn)定,如圖12 和圖13 所示.圖12 顯示模型測試過程中每種漏洞類型的PR 曲線.從圖12 中可以看出,多數(shù)漏洞類型的PR值較高,在召回率與精確率之間取得了不錯的平衡.最終所有漏洞類型的平均PR 值為0.85,如圖12 中橘黃色區(qū)域所示.圖13 顯示了模型測試過程中每種漏洞類型的ROC 曲線以及AUC(area under curve).從圖13 可以看出,多數(shù)類型的 ROC曲線趨向于圖的左上方,并且所有類型的 AUC平均值為0.96,如圖13 中橘黃色區(qū)域所示,說明模型的總體效果與性能比較好.
Fig.12 PR curve of the model test圖12 模型測試的PR 曲線
Fig.13 ROC curve the model test圖13 模型測試的ROC 曲線
任務3.基于比較學習的模型學習能力的檢測.
本文在實驗的過程中,也對本文提出的基于比較學習的模型的學習能力進行了檢測.其具體的方式是比較模型對測試集中各種類型樣本的分類能力.圖14 是原始測試集特征的t-SNE(t-distributed stochastic neighbor embedding)圖,圖15 是使用訓練完的深度學習模型提取的測試集特征的t-SNE 圖.
Fig.15 t-SNE diagram of test set features extracted by deep learning model圖15 深度學習模型提取的測試集特征的t-SNE 圖
從圖15 中不難看出,本文基于比較學習訓練的深度學習模型具有較強的分類能力,如圖14 和圖15中的紫色區(qū)域所示.在圖14 中,紫色區(qū)域代表的漏洞類型比較分散.而在圖15 中,紫色區(qū)域代表的漏洞類型比較好地聚集在一起,說明模型學習到了測試集中各漏洞類型的特征,并且測試集中各漏洞類型的特征經(jīng)過本文訓練的深度學習模型的處理,具有了較強的可區(qū)分性,這就使得模型識別漏洞的能力大幅度地提高.
眾多基于深度學習的漏洞識別模型為了提高模型的泛化能力,都會對數(shù)據(jù)集中的樣本進行符號化,去除個性化的程序特征,輔之統(tǒng)一的符號來代替這些特征,降低模型提取程序特征的難度,提高模型的泛化能力.但在實驗過程中發(fā)現(xiàn),在基于比較學習的深度學習漏洞檢測任務中,數(shù)據(jù)集中的樣本程序是否符號化對模型的準確率并沒有太大的影響.實驗分別以本文整理的數(shù)據(jù)集和文獻[28]中的數(shù)據(jù)集為對象進行了驗證.實驗的過程為:首先對經(jīng)過符號化處理的數(shù)據(jù)集進行學習訓練,測量其準確率;然后再對未經(jīng)過符號化處理的數(shù)據(jù)集進行學習訓練,測量其準確率;最后對比這2 種模式下符號化與否對模型準確率的影響程度.實驗結果如圖16、圖17 和圖18、圖19 所示.圖16 中是本文中的數(shù)據(jù)集經(jīng)過符號化處理后,訓練學習時的準確率.其中,訓練集的準確率為95.1%,測試集的準確率為91.6%,驗證集的準確率為91.5%.圖17 顯示的是沒有經(jīng)過符號化處理的本文數(shù)據(jù)集訓練時的準確率,其中,訓練集的準確率為93.7%,測試集的準確率為92.0%,驗證集的準確率為91.8%.
Fig.16 Accuracy of our data set after symbolization圖16 符號化后的本文數(shù)據(jù)集的準確率
Fig.17 Accuracy of our data set after non-symbolization圖17 無符號化后的本文數(shù)據(jù)集的準確率
Fig.18 Accuracy of MVD data set after symbolization圖18 符號化后的MVD 數(shù)據(jù)集的準確率
Fig.19 Accuracy of MVD data set after non-symbolization圖19 無符號化后的MVD 數(shù)據(jù)集的準確率
從圖16 和圖17 中可以看出,對數(shù)據(jù)集進行符號化處理和不進行符號化處理,模型的準確率變化幅度不是很大,其中訓練集的變化幅度稍大點,差值達到了1.4,而測試集和驗證集的變化幅度很小,幾乎可以忽略不計.類似地,文獻[28]中的MVD 數(shù)據(jù)集在基于比較學習的模式下也有相同的情況.通過以上的2 個實驗不難看出,數(shù)據(jù)集中的樣本是否符號化并不會影響基于比較學習的深度學習模型的訓練方式,不會對訓練的準確率產(chǎn)生較大的影響.其原因在于:基于比較學習的深度學習方式,通過大量同類型樣本和不同類型樣本的比較學習,模型確實學到了同類型程序和不同類型程序內(nèi)在的特征,數(shù)據(jù)集中樣本是否符號化并不會影響比較學習模式下模型的實際表現(xiàn).
本文提出了一種基于比較學習的漏洞檢測方法.在比較學習法中,針對數(shù)據(jù)集中的每個樣本為其構建同類型的樣本集合和不同類型樣本的集合.通過這種方式,使得深度學習模型在訓練的過程中,可以提取同類型樣本的共有特征,以及不同類型樣本中可區(qū)分性較強的特征,使得深度學習模型識別漏洞的能力大幅度地提高.盡管本文提出的比較學習方法可以提高基于深度學習的漏洞識別模型的準確率,并且在本文整理的數(shù)據(jù)集以及相關文獻中的數(shù)據(jù)集上有不錯的表現(xiàn),漏洞識別準確率比較高,但本文方法并沒有在實踐中進行應用,這是未來將要開展的工作,相信會在不久的將來,本文所提出的方法會有不錯的實際應用效果.
作者貢獻聲明:陳小全、劉劍提出了算法思路和實驗方案,以及論文撰寫;夏翔宇、周紹翔負責數(shù)據(jù)收集整理與深度學習模型訓練.
附錄A.