周 鵬 武延軍 趙 琛
1(中國科學院軟件研究所 北京 100190)2(中國科學院大學 北京 100049)3(計算機科學國家重點實驗室(中國科學院軟件研究所) 北京 100190)
隨著軟件系統復雜度的增加、開源軟件日益廣泛的應用對漏洞(vulnerability)披露的透明度和效率提升、各國政府和企業對軟件安全愈加重視而增加投入,軟件漏洞的披露數量逐年增加[1-2].同時軟件正滲透到經濟、社會生活的方方面面,Linux內核、基礎庫(如OpenSSL)被不同軟件系統廣泛共用,其安全漏洞被利用往往波及到廣泛的軟件系統和大量的用戶[3-4].因此幫助用戶及時應用安全漏洞補丁修復至關重要.
觀察開源社區安全漏洞生命流程,總結科研工作者和企業安全漏洞階段劃分慣例[1,4-6],開源軟件漏洞生命周期主要分為4個階段:1)發現新漏洞;2)開發發布漏洞修復補丁;3)將漏洞修復補丁通知用戶;4)用戶應用漏洞修復補丁到軟件系統.我們對這4個階段進行分析發現,軟件漏洞生命周期第3階段很容易被忽視并存在安全提示信息不足,進而造成第4階段存在明顯的管理不足,影響安全補丁的及時應用從而給用戶帶來安全威脅.
第1階段:該階段已經引起學者們的廣泛關注,比如漏洞檢測、漏洞挖掘、漏洞分析、漏洞利用(是評估新漏洞的重要手段之一)一直是安全領域的研究熱點,持續受到科研、企業、政府機構等密切關注[1,7-8].
第2階段:該階段反應快速,易獲得優先處理.新安全漏洞一旦被發現確認,開源社區維護者(maintainer)會積極做出反應,快速開發、評審、處理漏洞修復補丁[5],例如文獻[9]統計發現安全漏洞的修復反應速度比性能Bug快2.8倍,安全漏洞分配的開發者人數是性能Bug的3.51倍,是其他Bug的4.7倍;文獻[1]跟蹤分析的包括Linux內核、Ubuntu等600多個開源項目和Snyk安全公司發布的開源軟件安全狀態工作報告[5],統計發現維護人員對待安全漏洞和安全修復補丁的響應速度、重視程度要明顯高于其他Bug.
第3,4階段:第2階段研究表明通過補丁注釋特別是補丁的commit message明確告知補丁是修復安全漏洞、明確給出對應的CVE ID(common vulnerabilities and exposures identifiers)[10],對軟件的用戶(安全軟件工程師、操作系統發行版、軟件集成商、運維工程師等)識別安全漏洞修復補丁,盡早應用到軟件系統至關重要.但是,研究發現開源軟件維護者經常悄無聲息地修復安全漏洞,即漏洞修復補丁的代碼部分和commit message中未給出安全描述和CVE ID信息是很常見的.比如研究報告[5]統計發現,在漏洞修復補丁發布時,維護者在文件中明確標注CVE ID的只占9%,及時主動通知安全監控服務提供者只有3%,88%的維護者在新版本發布的發布說明里才通知修復了安全漏洞,但是相對于安全補丁的發布,軟件新版本發布要滯后很多,而且很多生產環境的基礎服務,出于安全性、穩定性考慮,管理員更偏向于補丁升級而非升級整個軟件版本,管理員不得不去識別具體的安全修復補丁;同時我們編寫工具統計了收錄到NVD[11]數據庫的Linux內核全部漏洞(2002—2020年5月23日),Linux內核一共有4 064個被NVD數據庫收錄確認的漏洞,然后我們的工具追蹤NVD和Linux內核源碼倉庫,發現修復補丁被登記到NVD追蹤的只有1 633個,即NVD已經確認收錄的Linux內核漏洞,其中只有40.2%的內核漏洞修復補丁登記關聯到NVD數據庫,從而可以NVD數據庫反向識別;我們的工具直接追蹤Linux內核源碼倉庫,發現其中只有380個漏洞修復補丁的提交信息給出了CVE ID等漏洞描述信息,僅占Linux內核NVD確認漏洞總數的9.35%,占NVD反向可追蹤數的23.27%,因此Linux內核維護者在安全修復補丁文件中明確標注CVE ID的情況跟開源軟件整體情況一樣比例很低.由此用戶(即便是專業的安全工程師)識別安全漏洞修復補丁,從而避免遺漏和盡早應用安全補丁面臨挑戰.
基于這些觀察分析,開發安全修復補丁的智能化自動識別工具,實現對漏洞修復補丁的及時識別、及時通知、降低人工識別的工作量和遺漏,從而促進安全補丁的及時應用是本文的主要研究動機.
因此,本文以代表性的Linux內核源碼社區為案例,設計實現了一種Linux安全漏洞補丁的自動化識別方法.該方法核心思想是為合并到Linux內核源碼的補丁的代碼和描述部分分別定義漏洞特征,構建機器學習模型,訓練學習可識別安全漏洞補丁的分類器.該方法的實現主要包括3個步驟:1)如何持續收集和標注安全漏洞補丁和非安全補丁;2)跟其他的Bug修復、功能增強補丁相比,分析安全漏洞修復補丁的特點,對原始補丁文件進行特征定義和特征抽取;3)設計、實現機器學習模型,使用收集的數據集訓練生成可識別漏洞修復補丁的分類器.
本文的主要貢獻包括3個方面:
1) 給出了一種可以自動識別漏洞修復補丁的機器學習建模方法,并詳細給出了如何做Code特征、Log特征的定義與提取,以及聯合Code和Log如何基于半監督的Co-Training方法建模.以代表性的Linux內核為應用實例,實驗表明該方法將識別精確率提升到91.3%,準確率到92%,召回率到87.53%,誤報率降低到5.2%,因此具有實用價值.并且該方法有很好的可擴展性,可以直接擴展支持其他開源項目.
2) 實現了一個可持續收集和標注安全漏洞修復補丁和Bug修復補丁的工具系統,并給出其設計與實現細節,該系統可以擴展支持其他以Git,SVN等版本控制工具管理的開源軟件.
3) 本文研究也啟示,不應盲目相信,或過度依賴NVD、開源軟件社區漏洞通告,因為其全面性、有效提示性和及時性存在不足.分析表明其通告質量存在漏、錯、未更新等問題.這要求我們需結合人工和自動化識別工具去主動識別漏洞修復補丁,及時修復.
近年來,使用機器學習技術對程序源代碼進行分析和處理成為研究熱點之一,其中分析軟件漏洞、Bug修復是重要的研究方面.下面介紹跟本文最相關的工作,以及我們的工作跟相關工作的區別.
文獻[12]提出了使用補丁的說明信息(Log message)和Bug報告抽取特征自動識別安全漏洞補丁的研究方法,該類方法只使用補丁的自然語言相關的素材信息,不涉及代碼;我們的方法同時從補丁的Log message和Code抽取特征,結合2方面的特征信息構建模型,因此在建模的特征工程和建模方法上都明顯不同.
文獻[13]提出了使用補丁的Log message和Code部分抽取特征識別漏洞修復補丁的方法,我們雖然都使用了補丁的Log message和Code部分,但是我們的特征工程和建模方法有明顯區別,比如文獻[13]將Code只做純文本對待抽取關鍵字,然后跟Log自然語言部分一起合并;而我們的方法將Code部分按照編程語言進行分析,抽取其標識符、循環、代碼修改等細粒度信息構建特征,并且我們將Code和Log部分的特征分開構建機器學習模型,因此建模方法也明顯不同.
文獻[14]提出了結合使用補丁的統計量(局部性、復雜度、控制循環)結合關鍵字抽取特征,然后用機器學習的方法對安全修復補丁進行更細粒度分類,如劃分為Buffer錯誤(如棧溢出)、Injection錯誤(如錯誤注入)、Numeric錯誤(如整數溢出)等,我們都是借助補丁的統計特征建模,但我們的研究目標和構建模型的方法完全不同,從其實驗效果可知文獻[14]細粒度補丁類型分類有效但并不顯著(其最佳準確率是54.75%),因此并不能達到本文研究目標的可實用的程度.
文獻[15]提出一種從Bug修復補丁中識別出漏洞修復的研究方法(漏洞修復補丁是Bug補丁的子類,所以我們在本文中稱純Bug修復補丁以做區分.),該方法使用LLVM編譯器將補丁修改的文件源碼預編譯為IR,然后使用手動建立的補丁模式(安全操作、關鍵變量、漏洞操作)對IR對照補丁模式進行預處理收集到模式數據,最后將收集的數據作為約束提供給手動定義的符號規則做約束求解,求解結果做出是否為安全補丁的判斷.該方法為應用程序的語法信息提供了一種可借鑒的思路,但其每個步驟都需要人工建立模式、規則,導致人工負擔較重,規則和模式的完備性需要驗證,這限制了其應用規模.因此我們的研究方法和應用規模都有明顯差異.
文獻[1,9,16-17]從經驗軟件工程角度對不同補丁的統計特性進行了大量實證研究,研究表明功能補丁、Bug修復補丁、安全漏洞修復補丁表現出統計上的顯著差異,這些經驗是本文對代碼補丁做特征工程時進行特征定義與選取的主要依據.但本文工作跟這些研究的研究方法和目標都是不同的.
文獻[18-19]等標注源碼的研究方法,我們的研究目標和研究方法都差別很大.
每個源代碼補丁(簡稱補丁)由Log message和Code部分組成,前者是自然語言描述的補丁性質和行為,后者指定對源代碼文件的修改(增、刪、替換).開源軟件是以補丁合并(merge)的方式發展演化,可分為Bug、功能、漏洞修復3類補丁.從Linux內核社區直接獲取補丁是很容易的;但是,因為補丁描述信息和補丁代碼有很強的隨意性,根據補丁信息對補丁進行直接自動化歸類(標注)比較困難.而模型訓練和更新需要足夠的標注補丁,這就要求給出能夠持續收集、標注補丁的方法,并設計開發自動化工具.
2.1.1 收集標注漏洞修復補丁的方法
因為直接根據補丁提交信息從Linux倉庫收集安全漏洞補丁識別困難,不可靠.而NVD數據庫里分配了CVE ID的漏洞是經過確認而具有可靠性.因此,我們采取了從NVD數據庫解析信息,然后反向追蹤Linux內核的Git源碼倉庫[20]的方法,其方法流程如圖1所示:
1) 從NVD站點自動下載NVD安全漏洞數據,每天更新一次.
2) 數據以JSON格式存儲,以名字為“CVE_Items”的JSON數組管理,數組的每一項是一個被確認的安全漏洞的信息,圖2是一個CVE Item格式和記載字段的例子,這里只列出重要字段,省略大部分字段.
3) 通過解析CPE[21]“cpe23Uri”字段判斷該漏洞是否屬于linux_kernel.
4) 通過解析“references”字段的所有選項,匹配是否存在“git.kernel.org”或“github.com/torvalds/linux”的url,如果有則表明可能提供了補丁鏈接.“references”字段一般有多項,是描述該漏洞情況的來自于互聯的相關說明鏈接.
5) 解析漏洞補丁URL,提取其中的Commit Hash ID字段,Linux內核是使用git管理的代碼倉,每次commit補丁提交對應一個唯一的Hash ID.
6) 通過Hash ID從Linux內核倉的主干分支(Linus Torvalds維護)提取相應的補丁.

Fig. 1 Continuously collect and label vulnerability fix patches of the Linux kernel

圖2 一個CVE安全漏洞例子
通過以上方法流程,我們可以巧妙地為Linux內核自動收集、標注可靠的漏報補丁數據集,并可持續更新.顯然該漏洞補丁標注方法很容易擴展支持其他開源項目.
2.1.2 收集標注功能和Bug修復補丁的方法
該部分工作是收集明確不是安全漏洞修復的補丁.其方法是收集可以明確是功能增強或純Bug修復的補丁.這些補丁最后都統一標注為“nonvulns”.
收集明確的Bug修復補丁:首先通過“fix(fix的派生詞)”過濾Log message做初步篩查,然后剔除掉有安全關聯敏感關鍵字的補丁[12],然后剔除掉在被明確做了安全標注的補丁,最后剔除掉有引用安全機構鏈接的補丁.
收集功能增強補丁:Log message出現Add support,Clean,Clean up,New feature等關鍵字,同時不屬于收集的安全漏洞修復、Bug修復補丁.
2.1.3 收集未標注補丁
收集無法做出安全漏洞標注、Bug修復標注、功能增強標注線索的補丁.這類補丁的分類標注為“unknowns”.
如圖3所示提交到Linux內核的修復CVE-2020-11494安全漏洞的補丁,可以看出該補丁并未給出可直接引人注意的安全提示信息.該補丁包括Log message文字說明部分(行⑤~所示)和代碼修改描述部分(行~所示).前者是自然語言,后者是嚴格的代碼規則語言,差別很大;因此需分別定義特征,分別給出特征提取方法.
2.2.1 補丁的代碼部分

圖3 一個CVE-2020-11494漏洞修復補丁例子

Fig. 4 Flow of feature extraction for commit log messages

Fig. 5 Test accuracy versus number of iterations for a training experiment
[1,9,16-17]
F01:跨越的函數體個數,度量局部性.
F02:改動的文件數,度量局部性.
F03:修改塊(hunk)數,局部性和復雜性.
F04:增加的行數,邏輯復雜性.
F05:刪除的行數,邏輯復雜性.
F06,F07:增加/刪除IF分支個數,邏輯復雜性.
F08,F09:增加/刪除循環數(for,while,goto),邏輯復雜性.
F10,F11:增加/刪除括號表達式,邏輯復雜性.
F12,F13:新增/刪除文件數,局部性,分別通過匹配“---/dev/null”“+++/dev/null”模式統計.
F14,F15:增加/刪除sizeof、取變量地址、指針運算操作.
F16至F19:增加/刪除函數調用數,邏輯復雜性.
F20,F21:增/刪函數返回(return),復雜性.
F22至F25:增加/刪除的continue,break控制數.
F26,F27:增加/刪除復制操作行數,復雜性.
F28,F29:增加/刪除關系運算(>,!=,<,|,&&等).
F30,F31:增加/刪除宏數,如#ifdef,#define,#undef,#endif,#elif.
F32:|F04-F05|,增加的減去刪除的,取絕對值.
F33:F04+F05,增加的加上刪除的.
F34至F54:特征F06至F11、F14至F31是以類似計算F32和F33的方式計算的特征.
2.2.2 補丁的Log message部分
特征抽取流程的詳細說明如下:
1) Log message文本抽取.提取每個補丁的Log message部分,并以commit Hash字符串命名文件存儲,這些文件按照vulns,nonvulns,unknowns這3個目錄組織管理.
2) 數據預處理.原始Log message文本包含噪音干擾信息,需在特征抽取前做清理.包括:剔除作者行(Signed-off-by,Reviewed-by,Acked-by等);統一小寫(避免大小寫增加詞匯庫);stemming處理把派生詞統一到詞根減小詞匯庫,如fixed,fixing,fixes都替換為fix,因為派生詞的提示信息是一樣的;停用詞(stop words)處理,剔除掉英語語言中信息量低的高頻詞,如his,hers,at,just,my,and等;最后Log message文檔的多行合并為一行,作為語料庫的一個文檔單元.
3) 構建語料庫.以前面步驟預處理后在vulns,nonvulns,unknowns目錄下管理的所有Log文檔為文檔單元構建BoW語料庫,該語料庫建設過程包括:收集所有的詞匯;統計語料庫全局空間詞頻(global term frequency),記為TFg;詞頻最高的前50的詞匯構成詞匯庫(Vocabulary);計算50個詞在語料庫全局空間的逆文檔頻率(inverse document frequency),記為IDF.選取的50個詞構成了每個Log文檔的特征分量.
語料庫中詞頻為
(1)
其中ngi是單詞i在所有Log文檔中出現次數,Ng是語料庫中所有單詞出現次數的和.
IDF的計算需要先計算DF(詞匯的文檔頻率):
DFi=Di,
(2)
其中Di={dj|ti是語料庫中的單詞,ti∈dj}.

(3)
其中,D={d1,d2,…,di,di+1,…,dn|di是Log文檔,n是文檔總數}.
4) 生成Log message特征.有了第3步統計學習得到的語料庫的Vocabulary,TFg,IDF信息,可以為每個Log message計算生成其TF-IDF特征表示(記為TFIDF).任意文檔di抽取的特征表示為
TFIDFi=‖[TFIDFi1,TFIDFi2,…,TFIDFij,…,TFIDFiV]‖2,
(4)
其中V=|Vocabulary|=50,特征權重分量TFIDFij為
TFIDFij=TFij×IDFj,
(5)
其中TFij是詞匯單詞j在文檔di中出現的次數.
流程的步驟4)完成了對Log message文檔的特征抽取,抽取50個特征,每個Log文檔用50維的向量表示,向量權重分量是相應特征的TF-IDF值表示.
收集的訓練數據集包括標注數據集(vulns,nonvulns)和未標注數據集(unknowns),其中未標注數據數量遠多于標注數據集,因此我們嘗試采取半監督(semi-supervisied)的Co-Training[24-25]方法建模.將vulns視為正數據點P,將nonvulns(包括功能和單純的Bug修復補丁)視為負數據點N,將unknowns視為未標注數據點U,P和N構成了標注數據集L.
算法1描述了訓練可識別安全漏洞補丁分類器的流程,該算法執行過程中我們設置nP=2,nN=4,nU=80,iter=30;算法2是使用由算法1學習的分類器做預測的流程,因為分類器有2個構成,分別是基于補丁的Code特征訓練和基于補丁的Log特征訓練得到,該算法描述了在預測推理階段如何整合這2個分類器構建1個統一安全漏洞補丁識別分類器.
注意:算法描述中的[begin:end]操作是從特征集中截取從begin索引開始到end結束的部分特征,end未指定表示到序列結尾,begin未指定表示從序列開頭;算法中用到的子分類器模型是基于SVM LinearSVC[26]構造.
算法1.模型訓練過程.
輸入:XL為標注樣本,y為補丁樣本標注,XU為未標注樣本,nP為每次迭代各分類器從XU中取出標注為正樣本的個數,nN為取出標注為負的個數,nU為未標注樣本緩沖池大小,iter為訓練迭代次數;
輸出:clfCode是用補丁的代碼特征訓練的分類器,clfLog是補丁的Log特征集訓練的分類器.
① FUNCTION:runTrain(XL,y,XU,nP,nN,nU,iter)/*將補丁的特征集分為Code和Log特征集*/
②XLCode=XL[0:CodeFeatureCount],
XLLog=XL[CodeFeatureCount:];
/*使用SVM LinearSVC建模初始化分類器*/
③clfCode←LinearSVC,clfLog←LinearSVC;
④c=0;/*Co-Training訓練迭代次數計數器*/
⑤UP←從XU隨機取nu個元素構建緩沖池;
⑥ WHILE(c ⑦clfCode←Train(clfCode,XLCode,y); /*使用補丁的Log特征集訓練分類器*/ ⑧clfLog←Train(clfLog,XLLog,y); /*Code分類器對池子樣本做預測*/ ⑨yPredByCode←Infer(clfCode,UP[0:CodeFeatureCount]);/*Log分類器對池子樣本做預測*/ ⑩yPredByLog←Infer(clfLog, UP[CodeFeatureCount:]);/*用Code推理標注nP個正樣本,nN個負樣本*/ set(Pl)∪set(Nl)); set(Nc)∪set(Pl)∪set(Nl))); 算法2.模型推理預測過程. 輸入:clfCode是算法1生成的代碼特征分類器、clfLog是算法1生成的Log特征分類器、x是數據點; 輸出:1預測為正(漏洞修復補丁),0為負. ① FUNCTION:vulInfer(x,clfCode,clfLog) ②pred1=pred2=-1; ③pred1←Infer(clfCode, x[0:CodeFeatureCount]); ④pred2←Infer(clfLog, x[CodeFeatureCount:]); ⑤ IF(pred1==pred2) ⑥ RETURNpred1; ⑦ ENDIF/*Code和Log分類器預測一致Code預測為正、負的置信概率*/ ⑧ (pp1,pn1)←InferProbability(clfCode,x[0:CodeFeatureCount]);/*Log預測為正、負的置信概率*/ ⑨ (pp2,pn2)←InferProbability(clfLog,x[CodeFeatureCount:]); ⑩ IF (pp1+pp2>pn1+pn2) /*正、負置信度和相等,隨機預測*/ 在本節中,首先介紹數據集的情況;然后給出模型訓練收斂性的實驗測試評估,接著實驗評估了模型的性能、跟代表性研究的對比;最后評估了安全漏洞補丁的報告情況分析.實驗表明本文給出的漏洞修復補丁識別方法可行、效果明顯,跟代表性研究對比其預測性能有明顯提升.同時安全漏洞補丁的追蹤情況現狀分析表明,完全直接依托NVD和補丁的Log信息識別、管理,難以實現及時、全面地響應安全漏洞威脅;因此通過自動化識別等方法提升對漏洞修復補丁的識別準確率和推送效率很有必要. 我們定義準確率、召回率和精確率公式為: (6) Recall= (7) (8) 其中,#TruePositive表示在測試時正數據點被正確識別為正的個數.#TrueNegative表示負數據點被正確識別為負的個數.#FalseNegative表示正數據點被錯誤識別為負的個數.#FalsePositive表示負數據點被錯誤識別為正的個數.#Positive表示正數據點的個數,等于#TruePositive+#FalseNegative.#Negative表示負數據點的個數,等于#TrueNegative+#FalsePositive. 準確率、召回率和精確率這3個指標方便跟相關研究做對比.在工程實踐中我們也關心誤報率和漏報率這2個直觀指標,前者影響補丁識別工作量,后者影響工具可靠性.因為漏報率是召回率的相反指標,所以我們只需定義誤報率公式為 (9) 本文使用2.1節給出的方法收集和標注數據,收集的數據集整理為正數據、負數據和未標注數據.正數據是安全漏洞修復補丁,標注為1;負數據是非安全漏洞修復補丁,標注為0;未標注數據是分類未知的補丁,標記為-1.表1給出了收集的Linux內核補丁數據集的構成與使用分配情況.覆蓋了2002—2020年5月23日Linux內核補丁. Table 1 Data Set Composition and Assignment 實驗參數設置:設置從無標注樣本集選擇標注的訓練迭代次數(參數iter)為30,設置參數nP=2,nN=4,nU=80.模型的內部子分類器選型SVM LinearSVC(只需完成正和負2個分類).正樣本1 633個、負樣本2 613個、未標注樣本42 359個;標注樣本的3/4用做訓練數據,1/4為測試數據.圖5所示,當迭代訓練到第18輪時模型可以趨于穩定收斂. 關于參數選取的說明:參數nP,nN,nU的設置參考Co-Training原始文獻[25]里的論述.Co-Training模型對內部子模型的選擇并沒有特別的限制,本文考慮到識別漏洞修復補丁是二分類問題,因此使用SVM LinearSVC可以滿足實驗驗證的需要;實際上選擇或構建其他模型(如構建二分類的神經網絡模型)代替這里的SVM LinearSVC作為參數傳遞給Co-Training,充當內部子模型二分類器也是可行的. 本節通過實驗測試模型的準確率、召回率、精確率和誤報率,對模型的預測效果進行評估.跟代表性研究模型的性能指標對比表明,本文的方法模型能明顯提高預測性能. 表2是實驗測試的主要性能指標,其精確率、召回率和準確率指標表明本文建模方法對安全漏洞修復補丁識別效果顯著.同時誤報率5.2%是可接受的. Table 2 The Test Results of Model Performance 表3是跟主流模型的性能對比.文獻[12]建模只使用了補丁的Log message信息;文獻[13]同時使用了Log message信息和補丁的Code信息,但是對Code信息只做純文本,因此特征抽取比較粗糙;我們的方法同時使用Log message和Code信息,并且將Code部分按照代碼對待,抽取其標識符、結構、語言構造等程序信息,因此特征提取更充分.性能指標對比表明我們的方法可以明顯提升模型的預測性能. Table 3 Performance Comparison with State-of-the-Art 實驗目的是檢驗模型從未標注補丁中發現漏洞修復補丁的能力.表4給出了自動檢測報告的13個補丁的情況,其中前11個是漏洞修復補丁,后2個是被工具誤報的純Bug修復補丁.該實驗表明本文方法可以有效檢測漏洞修復補丁. Table 4 Automatic Detection of Vulnerability Fix Patches 實驗方法是從unlabled數據集中隨機抽取1 500個交由訓練的模型做檢測,然后對檢測結果報告為正(即漏洞修復補丁)的補丁做人工檢查.眾所周知,Bug具有漏洞的特點并不表示很快可以找到該漏洞的利用方法,從而確定性證實或者證偽該漏洞.即該實驗的嚴格驗證比較困難.因此人工檢查是按照補丁是否修復典型的漏洞特征進行界定.工具報告了13個安全漏洞修復補丁,經過手動檢查11個被確認,2個是誤報(純Bug修復補丁). 我們的工具自動收集了從2002年起到2020年5月23日止,收錄于NVD數據庫的Linux內核全部登記漏洞.這些漏洞狀態的匯總統計如表5所示: Table 5 Statistics of Linux Vulnerability NVD Status 登記信息的完整性:一共有4 064個被NVD數據庫收錄確認的漏洞,只有380個漏洞修復補丁的Log message給出了CVE ID信息,僅占內核確認漏洞的9.35%,占NVD反向可追蹤數的23.27%;漏洞修復補丁在NVD的CVE信息中被記錄追蹤的只有1 633個(關聯1 497個CVE),即只有40.2%的漏洞修復補丁在NVD數據庫端有引用、只有1 497個CVE的登記信息是完整的.因此用戶如果通過Linux社區補丁提交的Log message信息收集漏洞修復補丁,只能及時識別9.35%. 登記信息的正確性:我們的工具分析發現,NVD數據庫匯總有51個內核CVE登記的補丁鏈接已經失效,涉及Linux內核的55個失效補丁,因此錯誤率為51/1 497=3.4%. 因此無論從源碼倉庫端或NVD數據庫端收集、識別安全漏洞修復補丁都存在全面性、有效提示性和及時性的不足,這表明完全依靠NVD和開源軟件社區漏洞通告做安全維護是不可靠的.同時這也表明智能自動化的漏洞修復補丁識別研究具有重要價值. 1) 局限性.本文實驗表明,從補丁的統計量構建特征,將補丁區分為安全漏洞修復和非安全漏洞修復準確率很高.但如果進一步將安全漏洞修復補丁做細粒度分類(比如區分為緩沖區溢出、整數溢出、錯誤注入、訪問控制錯誤等)則面臨挑戰.同樣,如果某個補丁違背了實證軟件工程的一般統計規律,本文的研究方法很難區分這類異常補丁,考慮到在規范的大型開源項目比如Linux,Xen,OpenStack,實踐中出現可能性很少,所以總體而言這種少量異常補丁的可能存在不影響本文方法的應用價值.如果一個社區的補丁管理嚴重不規范,比如功能混淆、缺乏一般的統計規律,對本文方法將是很大的挑戰,這不僅對工具是挑戰,對自然人手動識別也會帶來困難.我們認為結合補丁的語法語義解析構建特征,有可能對這類補丁的識別帶來幫助,這是我們下一步工作重點考慮的建模因素. 2) 模型的可擴展性.本文給出的識別漏洞修復補丁的建模方法是通用的,即可以直接擴展支持其他開源項目.雖然,因為一方面不同開源項目存在編程語言、功能代碼粒度、項目功能、編程規范等差異,另一方面當前AI技術尚存在泛化能力瓶頸(即一般地,一個訓練好的AI模型只能解決一個專門的問題,難以像人類智能做到觸類旁通、舉一反三),因此用Linux數據集訓練的模型并不能直接應用于其他開源項目的檢測;但是可以用同樣的建模方法,必要時對特征工程的參數做適當調整,為其他開源項目訓練預測模型.另外,如果想復用在一個項目上的訓練經驗,遷移學習是值得探討的. 在實際應用中,我們提供了2套部署場景. 場景1:識別上游Linux內核最新合并的補丁是否是漏洞修復補丁.腳本程序周期性地將Linux官方分支拉取(Pull)到團隊的內部內核倉庫,腳本檢測到更新則通過git show獲取新補丁,然后傳遞給我們的模型識別,模型將識別結果郵件推送給安全工程師. 場景2:內核開發團隊補丁評審(review).工程師創建PR(pull request)請求新補丁評審,機器人評審員(reviewer)對補丁進行安全識別,如果識別為安全漏洞修復補丁,則在評審中要求在Log message里增加安全提示性說明,并郵件通知安全工程師確認. 本文提出了一種漏洞修復補丁自動化識別的機器學習建模方法.幫助用戶和安全工程師更及時、全面地識別安全漏洞修復補丁.實驗結果表明,本文實現的漏洞補丁識別模型可以明顯提高識別性能,取得91.3%的精確率、87.53%的召回率,降低誤報率,因此,本文的方法是可行且高效的.下一步,有必要對以下工作進行探討: 1) 語法特征.為補丁構建特征工程時將補丁語法結構作為特征定義、提取的要素.這對于識別復合補丁(可能存在的一個補丁同時涉及漏洞修復、增加新功能、或普通Bug修復)是否涉及安全漏洞修復,以及進一步提高模型預測性能可能是有幫助的; 2) 跨開源項目的遷移學習.出于提升模型的訓練效率、預測性能或泛化能力考慮,以及解決一些開源項目可標注數據稀缺問題,應用遷移學習的方法將一個項目的訓練學習經驗在另一個開源項目的訓練中進行遷移復用,是下一步很值得探討的工作. 作者貢獻聲明:周鵬負責論文觀點的提煉與細化,完成論文撰寫,負責試驗設計、試驗實施、專家意見修改回復等;武延軍負責研究方向指引、論文框架、論文評審與詳細修改,參與試驗設計、專家意見討論評審等;趙琛負責論文指導、論文評審與修改,參與試驗框架設計、對專家意見的改進方法進行改進,開發試驗環境保障等.3 實驗評估
3.1 度量標準




3.2 數據集

3.3 模型訓練收斂過程
3.4 模型的預測性能


3.5 對unlabled補丁的自動檢測

3.6 Linux安全漏洞補丁報告概況

3.7 討 論
4 系統部署
5 總 結