?

基于抽象語法樹壓縮編碼的漏洞檢測方法

2022-01-12 04:45陳傳濤潘麗敏羅森林
信息安全研究 2022年1期
關鍵詞:源代碼漏洞語句

陳傳濤 潘麗敏 龔 俊 馬 勇 羅森林

(北京理工大學信息系統及安全對抗實驗中心 北京 100081)

(chencht163@163.com)

開源軟件是當前信息技術產業的重要支撐,同時也成為攻擊者的重點攻擊目標[1].由于開源軟件具有透明、開放、協作開發等特性,而開發人員的技術水平和安全意識參差不齊,導致開源軟件自身容易存在漏洞代碼.此外,攻擊者還可以直接向開源軟件注入惡意代碼.因此,研究高效能源代碼漏洞檢測方法,對保護開源軟件穩定運行、提升信息系統安全防御能力具有重要意義.

源代碼漏洞檢測技術是發現軟件安全漏洞的主要手段之一,近年來利用深度學習技術檢測源代碼漏洞成為研究熱點.抽象語法樹(abstract syntax tree, AST)是程序語法結構的一種抽象化表示,是源代碼在編譯過程的中間產物,用以分析檢查源代碼的語法語義是否正確.編譯器在生成AST時一般需要經過詞法分析、語法分析和語義分析3個步驟:1)編譯器首先對源代碼字符流進行掃描,識別詞法單元,并提取Token序列;2)在語法分析階段,Token序列被分解成各類語法短語,并生成語法樹;3)語義分析是編譯過程的邏輯檢查階段,主要任務是對結構上正確的源代碼進行語義審查,包括上下文相關性審查、Token類型匹配審查、類型轉換等.現有基于抽象語法樹的方法多將完整抽象語法樹作為深度學習模型的輸入,然而漏洞代碼解析的抽象語法樹通常規模較大,而語法、結構相關節點在樹中上下不相鄰,導致模型難以有效提取語法樹中的特征信息.因此,如何從大規模語法樹中學習源代碼漏洞模式,實現高性能漏洞檢測模型,是當前源代碼漏洞檢測課題的研究重點.

針對上述問題,本文提出一種結合程序語法和結構特征的源代碼漏洞檢測方法.通過對抽象語法樹進行壓縮編碼,在保留語法和結構信息的同時降低樹的復雜度;采用遞歸神經網絡算法提取代碼語句中的語法特征;通過樹卷積神經網絡捕捉代碼語句間的結構信息;利用注意力機制生成程序向量表示,增強模型對程序語法和結構信息的表征能力,提高檢測準確率.

1 相關工作

針對基于機器學習算法的漏洞檢測在學術界已有大量相關研究工作.VulDeePecker[2]是最早應用深度學習算法的源代碼漏洞檢測方法之一,其靈感來源于自然語言處理技術.該方法將源代碼視為文本序列,并采用基于序列的深度學習算法構建漏洞檢測模型.然而,該方法忽略了程序語法和結構特征,導致模型對漏洞的表征能力不足,檢測準確率低.對此,有大量工作針對源代碼的抽象語法樹構建漏洞檢測模型[3-9].

針對冒名頂替他人上學的案件至少有三個,除了齊玉苓案,還有齊玉苓案的湖北版“黎良珍與陳朝陽等侵害受教育權糾紛上訴案”[注]參見湖北省咸寧市中級人民法院(2001)咸民終字第76號民事判決書。和河南版張某被冒名頂替上學案[注]該案沒有找到判決書原文,但是在有的學者的研究中提到。參見范履冰:《受教育權法律救濟制度研究》,北京:法律出版社2008年版,第62-63頁。,后兩個案件的裁判均受到前述案件所涉司法批復的深刻影響。

不同于自然語言,程序編程語言具有復雜的語法和結構特征,如循環、嵌套、分支等,以及復雜的數據流與控制流等.Dam等人[3]提出一種基于長短時記憶模型的代碼語義和語法特征自動學習方法,該方法從抽象語法樹提取Token序列,然后構建LSTM模型自動學習代碼語義和語法特征,挖掘潛在漏洞模式.實驗結果表明,在22個跨項目漏洞檢測案例中,平均查全率達到80%,證明該方法能夠有效地檢測實際漏洞.Mou等人[10]提出一種用于代碼特征學習的樹卷積神經網絡(tree-based convolutional neural networks, TBCNN),該方法可以直接在抽象語法樹上卷積計算,捕捉程序語法和結構特征.Liang等人[6]在TBCNN的基礎上,提出一種利用深度學習方法提取漏洞詞匯特征和語法特征的漏洞定位方法,該方法通過將語義相似的語法實體進行分組以減少抽象語法樹的冗余單元.然而,有研究指出,基于樹結構的神經網絡模型容易出現梯度消失的問題.由于樹中語義相關節點之間的距離可能較遠,導致模型在訓練過程中梯度逐漸變得很小,尤其是當樹的深度較大、葉子節點過多時梯度消失問題更加明顯[11].

為了緩解梯度消失問題,Zhang等人[11]提出一種基于抽象語法樹的神經網絡算法(AST-based neural network, ASTNN),該方法將抽象語法樹分解為1組較小的子樹,然后分別對每個子樹進行特征學習,再將子樹的向量表示進行拼接得到程序向量表示.這種方法雖然能夠有效緩解因樹深度過大而導致的梯度消失問題,但其向量拼接方法難以保留不同子樹間所含有的程序結構信息.

綜上所述,現有源代碼漏洞檢測方法存在如下問題:1)基于代碼語義的漏洞檢測方法將源代碼文本序列作為輸入并采用序列模型學習代碼語義信息,該方法關注于代碼文本的語義信息而忽略了程序語法和結構信息,無法建立有效的漏洞特征表示方法;2)基于語法和結構特征的漏洞檢測方法針對程序完整的抽象語法樹進行特征學習,由于程序代碼的抽象語法樹規模通常較大,且代碼語義相關節點在樹中不相鄰,導致模型難以有效提取漏洞特征,檢測準確率低.

2 結合程序語法和結構特征的源代碼漏洞檢測方法

2.1 原理框架

針對大規模語法樹的語法和結構特征提取不充分的問題,本文提出基于抽象語法樹簡化的源代碼漏洞檢測方法.該方法原理如圖1所示,主要包括數據預處理、語句嵌入網絡、程序嵌入網絡和分類器4個模塊.為充分提取代碼語法和結構信息,首先將原始抽象語法樹以代碼語句為單元分割成多個子樹,并將子樹壓縮為單個節點后按原始抽象語法樹的結構生成新樹.在子樹和新樹的基礎上構建語句嵌入和程序嵌入2層網絡.在語句嵌入網絡中,采用遞歸神經網絡(recursive neural network, RvNN)提取代碼語句內的語法信息,生成語句向量表示;在程序嵌入網絡中,利用樹卷積神經網絡算法捕捉代碼語句間的結構信息,然后利用注意力機制生成程序向量.通過對抽象語法樹的分割、聚合、重建,顯著減小抽象語法樹的深度并減少了節點數量,在保留程序語法和結構信息的同時捕捉節點語義信息,增強漏洞表征能力.

圖1 基于抽象語法樹壓縮編碼的源代碼漏洞檢測方法原理圖

2.2 數據預處理

為了在不損失程序語法和結構特征前提下提取抽象語法樹中的特征信息,需要對程序源代碼進行數據預處理,包括源代碼解析和抽象語法樹簡化.

2.2.1 源代碼解析

本文提出的方法是一種函數級源代碼漏洞檢測方法,輸入數據為函數代碼段.使用開源工具PyCparser[12]將源代碼解析為抽象語法樹,解析后1個函數對應1棵抽象語法樹.以圖1所示的程序源代碼為例,其解析后得到的完整抽象語法樹如圖2上部分所示,為了簡化表示,圖2省略了部分代碼語句所對應的子樹.從圖2可以看出,大約10行的源代碼解析得到的抽象語法樹中節點數多達50個以上.

圖2 抽象語法樹簡化過程

2.2.2 抽象語法樹壓縮編碼

抽象語法樹壓縮編碼如圖2所示,圖2的上半部分為原始抽象語法樹,圖2的下半部分為壓縮編碼后的語法樹.具體包含如下3個步驟:

1) 首先將原始抽象語法樹以代碼語句為單元分割成多個子樹,如圖2中虛線框所示.

2) 使用RvNN算法學習子樹中的語法信息生成語句嵌入向量,然后將子樹壓縮為單個節點,用語句嵌入向量表示,具體過程見2.3節.

3) 根據語句子樹在原始抽象語法樹中的組織結構,將壓縮后的節點重新構建為1棵新樹,稱為ASTCC(AST compressed encoding).與原始AST相比,ASTCC的深度和節點數量大大減小.此外,ASTCC中不僅保留了結構特征,其每個節點的向量表示中還含有語法信息.

2.3 語句嵌入網絡

語句嵌入網絡用于從1句源代碼語句所對應的抽象語法樹中捕捉代碼語法信息,并得到語句嵌入向量.受ASTNN[11]啟發,通過遞歸神經網絡RvNN[13]構建語句嵌入網絡.RvNN是針對自然語言的語法解析樹的神經網絡,不同于基于時間序列的訓練神經網絡(recurrent neural network, RNN),RvNN按樹結構處理輸入數據,提取空間結構特征.RvNN將樹結構數據分解為一系列相同的基本單元,該基本單元在輸入數據的結構上展開,并且沿著展開方向傳遞信息.因此,語句嵌入網絡的結構隨著輸入數據的結構變化而變化,其中,RvNN神經元如圖3所示:

圖3 RvNN神經元示意圖

語法樹中所有節點向量記為vi,其中i表示子節點的數量,初始化時使用節點上Token的詞嵌入vt作為初始值.父節點的向量表示vp由其左右孩子節點所共同影響,計算公式:

vp=?(W[v1,v2]T+b),

(1)

其中W為權重矩陣,b為偏置項,?為激活函數.學習分數score計算公式為

score=UTpi,

(2)

其中U為輸出權重.為了加快訓練速度,RvNN中所有神經元共享權重W和U.

語句嵌入網絡在語法樹上的訓練過程由下向上,葉子節點信息傳遞到其父節點,層層遞歸直至根節點.根節點的向量表示中包含語句子樹中所有節點的語法信息,稱為語句嵌入向量,記為vs.

2.4 程序嵌入網絡

程序嵌入網絡采用基于樹結構的卷積神經網絡TBCNN[10]算法,以捕捉程序結構信息.不同于傳統卷積神經網絡(CNN),TBCNN是一種在樹結構數據上展開卷積計算,通過卷積核捕捉語法樹的空間結構特征.網絡結構如圖1所示,圖1中三角形虛線框為卷積核,其深度為固定值,廣度隨樹結構變化而變化.

對于每個非葉子節點,其輸出向量vp由初始詞嵌入vt及子節點嵌入向量vs所編碼,計算公式為

(3)

其中N為所有節點數量,Nc為第c個節點的子節點數量,Wt和Wb為組合權重,Wn為所有子節點vs,c的系數權重,bn為偏置項,激活函數為tanh.

卷積核在語法樹中由下向上從葉子節點滑向根節點,每次滑動時更新非葉節點的值,記為v′,計算方法為

(4)

其中Wconv,c為卷積權重矩陣,bconv為卷積核偏置項.更新所有節點信息后,使用注意力機制生成程序嵌入向量p的計算方法:

(5)

(6)

(7)

2.5 分類器

得到程序嵌入向量p后,通過一層全連接網絡構建分類器模型,使用Softmax作為激活函數:

(8)

其中C為類別數量,yi表示樣本預測為第i類的概率.

檢測模型利用隨機梯度下降法進行訓練,采用L2正則化的分類交叉熵作為損失度量.

3 實驗分析

3.1 實驗目的和數據來源

為測試ASTCC方法的可行性和有效性,本文進行了消融測試實驗和對比分析實驗.消融測試實驗針對原始抽象語法樹與壓縮編碼后的抽象語法樹進行測試,以探究壓縮編碼對檢測方法的貢獻度;本文方法與VulDeePecker[2]和TBCNN[10]算法在相同數據集上進行對比實驗,驗證ASTCC的有效性.

實驗數據采集來自NVD[14]和SARD[15]數據庫,選用C/C++程序中常見的2種漏洞類型:緩沖區錯誤(CWE-119)和資源管理錯誤(CWE-399).NVD(national vulnerability database)是由美國國家標準與技術局創建和維護的通用漏洞數據庫,包含漏洞詳細信息,如漏洞編號、公布時間、漏洞來源、解決方案和補丁鏈接等.SARD(software assurance reference dataset)是一個軟件保障參考數據集,專門供研究人員和軟件開發人員進行工具測試,數據集中包括真實軟件中的已知漏洞.根據MITRE[16]的研究,CWE-119和CWE-399是最常見和最危險的軟件漏洞,因此也被廣泛用于測試源代碼漏洞檢測模型的性能.數據集概況如表1所示,按8∶2劃分訓練集和測試集.

表1 數據集概況

3.2 實驗環境

實驗硬件環境為:Intel(R) Xeon(R) CPU E5-2680 v4 @ 2.40 GHz,64 GB RAM,NVIDIA GeForce GTX 1080 GPU.主要軟件和開發工具包為:Python 3.7,TensorFlow v1.14.0,scikit-learn v0.22,PyCparser v2.18.

3.3 評價方法

CWE-119和CWE-399漏洞檢測任務屬于二分類,實驗采用機器學習領域常見指標評估檢測模型的性能,包括誤報率(FPR)、漏報率(FNR)、召回率(Recall)、準確率(Accuracy)及 F1分數(f1),計算方法如下:

(9)

(10)

(11)

(12)

(13)

其中:FP指分類器錯誤地將正常樣本判定為漏洞樣本的數量;FN指分類器錯誤地將漏洞樣本判定為正常樣本的數量;TP指分類器正確地判定出漏洞樣本的數量;TN指分類器正確判定出正常樣本的數量.

3.4 消融測試實驗

3.4.1 實驗過程和參數設置

基于抽象語法樹壓縮編碼的漏洞檢測方法消融測試實驗主要過程如下:

1) 使用PyCparser將數據集中所有源代碼樣本解析為AST,作為基本數據格式;

2) 采用深度優先的遍歷順序提取原始AST的節點Token序列;

3) 基于訓練集中的所有樣本的Token序列構建語料庫,訓練word2vec模型并生成Token詞嵌入;

4) 針對原始AST,使用詞嵌入初始化節點向量,然后利用樹卷積神經網絡算法訓練漏洞檢測模型訓練;

5) 針對原始AST,進行壓縮編碼,然后根據2.3節和2.4節所述方法構建語句嵌入網絡和程序嵌入網絡2層網絡,訓練檢測模型,ASTCC模型超參數如表2所示;

6) 分別針對2種模型在測試集上進行漏洞檢測實驗.

表2中卷積核深度設置為2,卷積層輸出維度設置為600.實驗中發現當訓練迭代次數超過80時,模型幾乎達到了最佳的預測結果.因此將迭代次數統一設置為固定值100,使得模型能夠充分學習特征信息.當每批訓練數據的樣本數設置為默認值256時,可能會出現內存不足的情況,而當批大小設置過小時,模型可能會出現振蕩問題,難以收斂.因此,實驗中將批次大小設置為128,其他參數使用默認值.

表2 漏洞檢測模型超參數

3.4.2 實驗結果分析和主要結論

消融測試實驗結果如表3所示,表中分別列出在緩沖區錯誤(CWE-119)和資源管理錯誤(CWE-399)數據集上的測試結果.

表3 消融測試實驗結果 %

根據表3實驗結果可以看出:

1) 與原始AST相比,基于ASTCC的檢測模型綜合性能較優,在CWE-119和CWE-399數據集上檢測準確率分別提升了2.9%和4.1%,F1均提升了6%以上,說明對抽象語法樹的壓縮編碼能夠提升模型檢測性能.

2) ASTCC方法在CWE-399數據集上的性能優于在CWE-119數據集,可能原因是CWE-119相比于CWE-399具有更復雜的漏洞模式,如涉及更多內存操作函數、從source到sink之間存在更復雜的數據流和控制流等.

3.5 對比分析實驗

3.5.1 實驗過程和參數設置

ASTCC模型的超參數設置與消融測試實驗所用相同,并在相同數據集上進行對比實驗,對比方法的實現過程如下:

1) 針對TBCNN[10]方法,在作者公開源碼的基礎上將其應用于源代碼漏洞檢測任務;

2) 針對VulDeePecker[2]方法,根據原論文所述網絡結構和參數進行復現.

3.5.2 實驗結果分析和主要結論

對比分析實驗結果如表4所示,表中分別列出不同方法在CWE-119和CWE-399數據集上的測試結果.

表4 對比分析實驗結果 %

根據表4的對比分析實驗結果可以看出:

1) ASTCC在CWE-119和CWE-399數據集上的檢測準確率分別達到93.48%和95.23%,且誤報率和漏洞率均較低,ASTCC綜合表現最優.

2) 與TBCNN相比,ASTCC在2個數據集上的準確率分別提升了10.19%和9.04%,得益于2點改進工作:一是對AST的壓縮編碼減小語法樹的復雜度,在不損失語法和結構特征的條件下縮小相關節點之間的距離,緩解了TBCNN中梯度消失的問題;二是通過構建語句嵌入和程序嵌入2層網絡充分提取程序語法和結構特征,并利用注意力機制代替TBCNN中的池化層,以提取語法樹中關鍵節點特征,增強模型漏洞表征能力.

3) 與VulDeePecker相比,ASTCC在F1指標上具有較大優勢.原因在于VulDeePecker方法側重于提取源代碼的數據流特征和語義依賴信息,而忽略了語法結構特征.相比之下,ASTCC針對程序語法和結構特征構建語句嵌入網絡和程序嵌入網絡,并通過注意力機制捕捉節點的語義依賴信息,增強模型對源代碼漏洞的表征能力.

4 結 論

針對基于抽象語法樹的漏洞檢測方法難以充分挖掘大規模語法樹中的漏洞特征而導致檢測準確率低的問題,本文提出了一種基于抽象語法樹壓縮編碼的源代碼漏洞檢測方法(ASTCC).首先,通過將原始抽象語法樹以代碼語句為單元進行分割、壓縮、重建,在保留語法和結構信息的前提下較大程度地減小抽象語法樹的深度并減少節點的數量,降低樹的復雜度,達到對抽象語法樹“壓縮編碼”的效果;然后,通過構建基于RvNN的語句嵌入網絡以提取代碼語句內的語法信息,再構建基于TBCNN程序嵌入網絡以提取壓縮編碼樹中結構信息,緩解TBCNN方法中由于語法樹規模過大導致梯度消失的問題;最后,利用注意力機制捕捉壓縮編碼后的抽象語法樹中節點關聯信息,提升漏洞檢測模型的性能.基于NVD和SARD公開數據集分別進行消融測試實驗和對比分析實驗.消融測試實驗中,與原始抽象語法樹相比,基于抽象語法樹壓縮編碼的檢測模型取得了更好的檢測效果,F1提升了6%以上,說明對抽象語法樹的壓縮編碼能夠提升模型檢測效果;在與VulDeePecker和TBCNN的對比分析實驗中,ASTCC方法在緩沖區錯誤(CWE-119)和資源管理錯誤(CWE-399)2類漏洞檢測任務中均取得了較好效果.結果表明ASTCC能夠有效降低抽象語法樹的規模,增強模型對源代碼漏洞的表征能力,提升源代碼漏洞檢測準確率.

猜你喜歡
源代碼漏洞語句
漏洞
基于TXL的源代碼插樁技術研究
偵探推理游戲(二)
保護好自己的“源代碼”
解密別克安全“源代碼”
漏洞在哪兒
基本算法語句
我喜歡
作文語句實錄
視頻、Office漏洞相繼爆發
91香蕉高清国产线观看免费-97夜夜澡人人爽人人喊a-99久久久无码国产精品9-国产亚洲日韩欧美综合