本篇文獻做者提出了一種基於深度學習來檢測軟件漏洞的方案。git
摘要:做者開始基於深度學習的漏洞檢測研究,是爲了減輕專家手工定義特性的繁瑣任務,須要制定一些指導性原則來適用於深度學習去進行漏洞探測。出於這個目的,做者用代碼 gadgets 來表明程序,而後把它們轉化爲向量,其中代碼gadget是一些彼此語義相關的代碼行。基於這設計了評估系統VulDeePecker,做者爲深度學習方法提供了最初始的漏洞數據集,實驗結果代表:與其餘方法相比,系統可以實現更少的誤報,將系統用於Xen,Seamonkey和Libav這3個軟件產品檢測到了4個未報告的漏洞。github
現有的漏洞檢測的解決方案有兩個主要缺陷:強制執行繁重的體力勞動和致使較高的誤報率。在本文中做者針對如下漏洞檢測提出了一個解決方案,同時考慮到這些侷限性:給定目標程序的源代碼,如何肯定目標程序是否脆弱,若是是,漏洞在哪裏。算法
基於以上,做者作了三部分工做:(1)開始利用深度學習進行漏洞檢測的研究。這種方法具備很大的潛力,由於深度學習不須要人工定義特性,這意味着漏洞的檢測能夠自動化。固然深度學習的有一些指導性的初步原則,包括使深度學習應用於漏洞檢測的軟件程序的表示,基於深度學習的漏洞檢測的粒度的肯定以及漏洞檢測的特定神經網絡的選擇。建議使用代碼小部件來表示程序,代碼小部件是一些(不必定是連續的)代碼行,它們在語義上相互關聯,能夠向量化爲深度學習的輸入。(2)介紹了一種基於深度學習的漏洞檢測系統的設計與實現,該系統被稱爲漏洞深度學習識別系統(VulDeePecker).有效性體如今能識別多種類型的漏洞,這就解釋了VulDeePecker使用漏洞模式(做爲深度神經網絡學習)來檢測漏洞。(3)提供了第一個用於評估VulDeePecker和其餘基於深度學習的漏洞檢測系統的數據集,該數據集來自美國國家標準與技術研究所(NIST)維護的兩個數據源NVD[10]和軟件保證參考數據集(SARD)項目[12]。數據集包含61638個代碼小部件,包括17725個易受攻擊的代碼小部件和43913個不易受攻擊的代碼小部件。在17725個易受攻擊的代碼小部件中,10440個代碼小部件對應於緩衝區錯誤漏洞(CWE-119),其他7285個代碼小部件對應於資源管理錯誤漏洞(CWE-399),做者已經在https://github.com/CGCL-codes/VulDeePecker上提供了數據集。數組
接下來主要研究基於深度學習的漏洞檢測的一些初步指導原則和VulDeePecker的設計。網絡
一.深度學習檢測漏洞的初步原則,其核心是回答三個問題(1)如何表示基於深度學習的漏洞檢測程序?(2)深度學習漏洞檢測的適當粒度是多少?(3)如何選擇特定的神經網絡進行漏洞檢測?函數
如何表示軟件程序?學習
因爲深度學習或神經網絡以向量做爲輸入,須要將程序表示爲具備語義意義的向量,即須要將程序編碼成向量,這些向量是深度學習所須要的輸入。指導原則1.程序能夠首先轉換成某種中間表示,稱爲代碼gadget。術語「代碼小部件」的靈感來自代碼重用攻擊上下文中的術語"小部件"[18],代碼小部件是少許(不必定是連續的)代碼行。編碼
什麼是適當的粒度?spa
因爲不只須要檢測程序是否易受攻擊,並且還須要肯定漏洞的位置,所以須要更細的粒度來進行基於深度學習的漏洞檢測。這意味着漏洞檢測不該該在程序或函數級別進行,這是很是粗粒度的,由於程序或函數可能有不少行代碼,肯定其漏洞位置自己就是一項困難的任務。指導原則2.爲了幫助Pin定位漏洞位置,程序應該被表示爲更細的粒度,而不是函數或者程序級別的。代碼小部件適用於指導原則2。設計
如何選擇神經網絡?
神經網絡在圖像處理,語音識別,天然語言處理([21][30][40])等不一樣於漏洞檢測的領域很是成功。這意味着許多神經網絡可能不適合漏洞檢測,須要一些原則來指導選擇適合漏洞檢測的神經網絡。指導原則3.由於一行代碼是否包含漏洞可能取決於上下文,可以處理上下文的神經網絡可能適用於漏洞檢測。這一原理代表,用於天然語言處理的神經網絡可能適用於漏洞檢測,由於上下文在天然語言處理[33]中很重要。將上下文的概念引入到本文的設置中,觀察到程序函數調用的參數常常是受到程序中較早操做的影響,也可能受到程序中較晚操做的影響。
因爲天然語言處理有許多神經網絡,首先從遞歸神經網絡(RNNs)[51][53]開始,這些神經網絡在處理順序數據方面是有效的,而且確實被用於程序分析(但不是漏洞檢測的目的)[20][48][56][57].然而RNNs存在消失梯度(VG)問題,致使模型訓練[16]失效。注意,VG問題是由RNNs的雙向變體(BRNNs[47])繼承的。
VG問題能夠經過將記憶細胞植入RNNs來解決,包括長期記憶(LSTM)細胞和門控循環單元(GRU)細胞[17][22]。因爲GRU在語言建模[27]上沒有超過LSTM,因此做者選擇LSTM進行漏洞檢測。因爲程序函數調用的參數可能受到程序中較早的語句影響,也有可能受到較晚的語句影響,這說明單向LSTM可能還不夠,應該使用雙向LSTM(BLSTM)進行漏洞檢測。BLSTM神經網絡圖以下:
、
有多個BLSTM層,一個Dense層和一個Softmax層。學習過程的輸入是一個肯定的表示向量,BLSTM層有兩個方向,向前和向後。Dense層減小了從BLSTM層接收到的向量維數,Softmax層以Dense層接收到的低維向量做爲輸入,負責表示和格式化結果,爲學習階段更新神經網絡參數提供反饋。學習階段的輸出是一個調好模型參數的BLSTM神經網絡,檢測階段的輸出就是分類結果。
二.VulDeePecker的設計
A.定義代碼小部件
爲了用適合神經網絡輸入的向量表示程序,提出了將程序轉換爲代碼小部件的表示,其定義以下:代碼小部件是由許多程序語句組成的(例如,這些代碼行),它們在數據依賴關係或控制關係方面在語義上彼此相關。爲了生成代碼小部件,提出了從關鍵點的啓發式概念,來從特定的角度表示程序。關鍵點在緩衝區溢出漏洞中能夠是:庫/API函數調用,數組和指針。本文中,將重點討論如何使用庫/API函數調用的特定關鍵點來證實它在基於深度學習的漏洞檢測中的有效性。
與庫/API函數調用相同的關鍵點對應,代碼小部件能夠經過數據流或者程序控制流分析的方式生成,其中著名的[23]算法,[50]算法和Checkmax[2]等易於使用的商業產品。
B.VulDeePecker的概述
系統有兩個階段:學習訓練階段和檢測階段。學習階段的輸入是帶有脆弱和不脆弱的大量訓練項目,所謂脆弱指的是包含已知的漏洞。學習階段的輸出爲被編碼成BLSTM神經網絡的漏洞模式。
學習階段有4個步驟:
Step 1:提取庫/API函數調用和相關的的程序片斷
1.1從訓練程序中庫/API函數的調用,同時注意VulDeePecker有關庫/API函數調用的關鍵點。
1.2爲在步驟1.1中提取的庫/API函數調用的每一個參數(或者變量)提取一個或多個程序片斷。
Step 2:生成訓練程序的代碼小部件及其標定好的真實數據
2.1將步驟2.2中得到的程序片斷組裝爲代碼小片斷,每個庫/API函數調用對應一個代碼小部件。代碼小部件不必定對應某些連續的代碼行,相反,它是由多行語義相關的代碼組成。
2.2對代碼小部件標記真實數據。這個步驟將每一個代碼小部件標記爲1(或0不是脆弱的),代碼小部件的真實數據標籤是可用的,由於咱們知道訓練程序是否脆弱,若是脆弱,咱們就知道了脆弱的位置。
Step 3:將代碼小部件轉換爲向量表示
3.1將代碼小部件轉換爲特定的符號表示,稍後將對此進行詳細說明。這個步驟的目的在於保存一些訓練程序的語義信息。
3.2對3.1步驟中的符號表示的代碼小部件進行編碼爲向量,這向量做爲訓練BLSTM神經網絡的輸入。
Step 4:訓練BLSTM神經網絡
4.1將編碼小部件編碼成向量並得到其標定好的真實數據後,這種訓練過程對於學習BLSTM神經網絡是標準的。
檢測階段是給定一個或者多個目標程序,從它們中提取庫/API函數調用以及相應的程序片斷,這些程序片斷組裝成代碼小部件。這些代碼小部件被轉化成符號表示,而後編碼成向量做爲訓練後的BLSTM神經網絡的輸入。網絡輸出哪些向量,所以哪些代碼小部件是脆弱的("1")或者是不脆弱的("0"),若是一個代碼小部件很脆弱,它會肯定目標程序中漏洞的位置。如圖所示:
檢測階段有2個步驟:
Step 5:將目標程序轉換爲代碼小部件和向量
5.1從目標程序提取庫/API函數調用(相似步驟1.1)
5.2根據庫/API函數調用的參數提取程序片斷(相似步驟1.2)
5.3將程序片斷組成爲代碼小部件(相似步驟2.1)
5.4將代碼小部件轉換爲它們的符號表示(相似步驟3.1)
5.5將代碼小部件的符號表示編碼爲向量(相似步驟3.2)
Step 6:檢測。這個使用學習到的BLSTM神經網絡對從目標程序中提取的代碼小部件相關的向量進行分類。當這個向量被分類爲「1」,意味着相關的代碼小部件是脆弱的,而且肯定了漏洞的位置。不然隊對應的相關代碼小部件不是脆弱的("0")。
具體每一個步驟的實現,因爲時間和篇幅關係,下一節進行探討。