1. 程式人生 > >A Deep Learning-Based System for Vulnerability Detection(二)

A Deep Learning-Based System for Vulnerability Detection(二)

  接著上一篇,這篇研究實驗和結果。

A.用於評估漏洞檢測系統的指標

TP:為正確檢測到漏洞的樣本數量

FP:為檢測到虛假漏洞樣本的數量(誤報)

FN:為未檢真實漏洞的樣本數量(漏報)

TN:未檢測到漏洞樣本的數量

  這篇文獻廣泛使用指標假陽性率(FPR),假陰性率(FNR),真陽性率或者召回率(TPR),精確度(P)和F1-measure來評估漏洞檢測系統[39]。

FPR=FP/(FP+TN)指標衡量的是假陽性率漏洞佔不容易受到攻擊的整個群體樣本的比例(在非脆弱樣本中誤報比率);

FNR=FN/(TP+FN)指標衡量的是假陰性率漏洞與整個樣本脆弱群體的比例(在脆弱樣本中的漏報比率);

TPR=TP/(TP+FN)指標衡量的是真正檢測到脆弱的樣本在樣本脆弱群體中的比例(TPR=1-FNR);

P=TP/(TP+FP)指標衡量的是正確性;

F1=2*P*TPR/(P+TPR)指標兼顧了精確度和真實陽性率。

  檢測系統既不漏報(FNR=0)也不誤報(FPR=0)以及正確率極高接近1,這是理想情況,現實實踐中是不可能的。只可能的是儘量的降低FNR和FPR。

B.準備VulDeePecker的輸入

收集資料  NIST維護的漏洞資料庫有兩個廣泛使用的來源:包含生產軟體漏洞的NVD[10]和包含生成,合成和學術安全漏洞或漏洞的SARD專案[12]。在NVD中,每個漏洞都有一個唯一的公共漏洞和識別符號(CVE ID)和一個公共的弱點列舉識別符號(CWE ID),該識別符號指示著所涉漏洞的型別。在本篇文獻中,關注兩種型別的漏洞:緩衝區錯誤(CWE-119)和資源管理錯誤(CWE-399),其中每一個都有許多子型別。這些漏洞非常常見,這意味著可以收集足夠的資料來可進行深度學習。本片文獻選擇了19個流行的C/C++開源產品,包括Linux核心,Firefox,Thunderbird,Seamonkey,Firefox esr,Thunderbird esr,Wireshark,FFmpeg,Apache Http Server,Xen,OpenSSL,Qemu,Libav,Asterisk, Cups,Freetype, Gnutls,Libvirt,VLC media player。

根據NVD,還在SARD中收集了包含這兩種漏洞的C/C++程式。總共從NVD收集了520個有關緩衝區漏洞相關的程式,320個與資源管理錯誤漏洞相關的程式。還從SARD收集了8112個關於緩衝區錯誤的程式(測試用例)以及1729個資源管理錯誤相關的程式,實際上,包含漏洞的程式包含多個程式檔案。

訓練程式 vs 目標程式   本篇文章隨機地選擇80%的程式作為訓練程式剩下的20%作為目標程式,當在處理一種或者同時兩種型別漏洞時這種比例是相對比較平等適用的。

C.學習BLSTM神經網路

這階段對應著系統VulDeePecker的學習階段。作者使用Theano[24]和keras[8]在Python中實現了BLSTM神經網路。

第一步:提取函式呼叫和相應的程式片段。從程式中提取C/C++庫/API函式呼叫,有6045個C/C++庫/API函式呼叫,包括標準庫函式呼叫[1],基本的Windows API和Linux核心API函式呼叫[9],[13]。總共從程式中提取了56902個庫/API函式呼叫,包括7255個正向函式呼叫和49647個反向函式呼叫。

第二步:1.生成程式碼小部件

  程式碼小部件由程式片段生成,利用訓練程式的程式片段生成的48744個程式碼小部件和目標程式的程式片段生成的12894個程式碼小部件獲得了一個有關61638個程式碼小部件的的資料庫(Code Gadget Database)。生成程式碼小部件的時間複雜度主要依賴於資料流分析工具,例如,從SARD中隨機選擇100個程式(99232行語句)生成2494個程式碼需要花費883秒,這意味著每個程式碼小部件的生成平均需要354毫秒。基於效率的考慮,使用CGD(前面提到的程式碼小部件的資料庫)總結出了以下6個數據集。

·BE-ALL:CGD的子集,針對緩衝區錯誤漏洞(CWE-119)和所有的庫/API函式呼叫。

·RM-ALL:CGD的子集,針對資源管理錯誤漏洞(CWE-399)和所有的庫/API函式呼叫。

·HY-ALL:和CGD一樣,針對前面兩種錯誤漏洞和所有的庫/API函式呼叫。

·BE-SEL:CGD的子集,針對緩衝區錯誤漏洞(CWE-119)和手動選擇的函式呼叫(而不是所有的函式呼叫)。

·RM-SEL:CGD的子集,針對資源管理錯誤漏洞(CWE-399)和手動選擇的函式呼叫(而不是所有的函式呼叫)。

·HY-SEL:和CGD一樣,針對前面兩種錯誤漏洞和手動選擇的函式呼叫(而不是所有的函式呼叫)。

2.給程式碼小部件做標記

  對於從NVD程式中提取的程式碼小部件,著重關注於涉及到行刪除或修改的被打補丁的漏洞。這個過程有兩個步驟:第一步,如果一個程式碼小部件至少有一行語句通過補丁形式被刪除或者修改,那麼會被自動標註為“1”(脆弱的,存在安全隱患),否則,標註為“0”(安全的)。然而,這種自動標註過程會誤標註一些程式碼小部件(不是脆弱的被標註為“1”),為了改善這種誤標註,第二步,手動去檢查這些標記為“1”的程式碼小部件,去糾正錯誤標註(如果有的話)。

  對於從與SARD有關的程式中提取的程式碼小部件,,由於每個在SARD中的程式都已經被分別標註為"good"(沒有安全缺陷),“bad”(包含安全缺陷),“mixed”(包含有安全缺陷的函式和修補以後的版本)。所以從帶有“good”標籤的程式提取的程式碼小部件標註為“0”(安全的),從帶有“bad”或者“mixed”標籤的程式提取的,程式碼小部件至少包含一行脆弱的語句,那麼該程式碼小部件標記為“1”,否則為“0”。由於在SARD程式的標籤中使用了啟發式方法,查看了1000個隨機程式碼小部件的標籤,發現只有6個(0.6%)小部件誤標註了,這是由於不容易受到攻擊的程式碼段中的語句與容易受到攻擊的程式碼段中的語句是相同的。由於誤標註的程式碼小部件非常少,並且神經網路對於一小部分標記錯誤的樣本具有健壯性,因此不需要人工手動檢查SARD程式提取的程式碼小部件的所有標籤。

  可能會遇到程式碼小部件同時被標記為“1”和“0”,這種情況是由於資料流分析工具的不完善造成的,本篇文獻的做法是將這些程式碼小部件刪除即可。

第三步:將程式碼小部件轉換為向量

  CGD總共包含6166401個標記,其中23464個是不同的,當將使用者自定義的函式名稱和變數名對映成符號之後,不同的標記進一步減少到10480個。將這些符號表示被編碼成向量後,作為訓練一個BLSTM神經網路的輸入。

第四步:訓練BLSTM神經網路

  對於表中描述的每個資料集,作者採用10倍交叉驗證的方法訓練BLSTM神經網路,並選擇與有效性相對應的最佳引數值進行漏洞檢測。例如。作者改變每個BLSTM神經網路的隱藏層數,觀察對結果F1-measure的影響。當調整隱藏層的數量時,當引數的預設值可用時,設定引數為其預設值以及將這些引數設定為深度學習社群廣泛使用的值。有關程式碼小部件的向量表示的標誌數目(tokens)設定為50個,dropout設定為0.5,batch size設定為64,epochs設定為4,ADAMAX的minibatch隨機梯度下降法(這部分我不熟悉,所以語言組織難免出錯),選擇300個隱藏節點,採用預設的學習率1.0來進行訓練。

  上圖繪製了VulDeePecker相對於6個數據集用不同的數量的隱藏層數,每一個數據集導致了不同的神經網路,觀察到6個BLSTM神經網路的F1-measure在隱藏層數的個數為2-3時達到最大,當層數大於6時,這些BLSTM神經網路的大多數F1-measure會下降。BLSTM神經網路的其他引數可以以類似的方式進行調優。

D.實驗結果與意義

  為了測試VulDeePecker是否可以應用於多種型別的漏洞,作者在三個資料集上進行了實驗:BE-ALL,RM-ALL,HY-ALL,這分別導致了三種神經網路,其有效性如下表所示:

經結果分析得:

1.VulDeePecker可以同時檢測多種型別的漏洞,但是其有效性取決於與漏洞相關的庫/API函式呼叫的數量(即越少越好)。

2.可以利用人工專業知識來選擇庫/API函式呼叫來提高VulDeePecker的有效性,尤其是F1-measure中的整體效率。

3.利用資料流分析的優勢基於深度學習的漏洞檢測系統會更加有效。

4.VulDeePecker比基於程式碼相似性的漏洞檢測系統更有效,後者無法檢測出不是由於程式碼克隆引起的漏洞,因此,經常導致漏報,然而VulDeePecker的高效性體現在對大量的資料很敏感,這是一種深度學習的固有性質。