陳克豪,程 偉,丁 蓀,劉 楊,3
(1.浙江理工大學(xué)信息學(xué)院,浙江杭州 310018;2.思探明信息科技有限公司,新加坡 128424;3.南洋理工大學(xué)計(jì)算機(jī)學(xué)院,新加坡 639798)
為節(jié)約成本、提高開發(fā)效率,大量開源組件被引入到在企業(yè)軟件開發(fā)過程中,且程序員不愿意使用新版本組件[1-2]。新加坡軟件安全公司Scantist 的調(diào)查報(bào)告顯示,97% 的軟件應(yīng)用程序(包括企業(yè)軟件)依賴于某種形式的開放源碼[3],避免使用存在安全隱患的組件對(duì)于保證軟件安全具有重大意義[4-5]。當(dāng)前安全測(cè)試步驟處于軟件開發(fā)過程中較為靠后的階段,且開發(fā)人員對(duì)軟件安全方面的技術(shù)不夠了解,安全測(cè)試人員對(duì)于軟件開發(fā)技術(shù)也不夠了解[6],存在信息不對(duì)等現(xiàn)象。軟件成分分析(Software Component Analysis,SCA)是指在開發(fā)過程中對(duì)應(yīng)用程序進(jìn)行分析,以檢測(cè)開源軟件組件是否存在已知的漏洞。例如,Imtiaz 等[7]對(duì)現(xiàn)有maven 和npm 源碼掃描的SCA 結(jié)果進(jìn)行了橫向?qū)Ρ确治?,著重?duì)測(cè)試結(jié)果之間的覆蓋情況進(jìn)行了比較,發(fā)現(xiàn)不同SCA 工具的檢測(cè)結(jié)果差異較大,并分析了這些差異可能產(chǎn)生的原因;Zhan 等[8]研究了安卓二進(jìn)制文件SCA 識(shí)別的檢測(cè)效率、版本識(shí)別、混淆恢復(fù)能力等問題;Dann 等[9]對(duì)開源代碼的微小幅度修改對(duì)SCA 掃描準(zhǔn)確性的影響進(jìn)行了研究,并介紹了目前常見的開源組件修改方式及其對(duì)SCA 分析產(chǎn)生的影響;Dann 等[10]還對(duì)不同編譯器產(chǎn)生的不同字節(jié)碼文件對(duì)字節(jié)碼匹配產(chǎn)生的影響進(jìn)行了研究,并設(shè)計(jì)了一種工具SootDiff,用于解決不同編譯器產(chǎn)生的字節(jié)碼文件不同而導(dǎo)致的匹配不準(zhǔn)確問題。
近年來,隨著軟件開發(fā)周期縮短、迭代速度加快,安全測(cè)試越來越難以全面覆蓋[11],安全左移的概念隨之被提出,即將安全程序(代碼審查、分析、測(cè)試等)移至軟件開發(fā)生命周期的早期階段[12],從而防止缺陷產(chǎn)生并盡早找出漏洞,減少經(jīng)濟(jì)損失[13]。為此,本文嘗試采用黑盒測(cè)試的方式研究安全左移的現(xiàn)狀,以及安全測(cè)試過程中采用SCA 方法應(yīng)對(duì)各種安全左移場(chǎng)景下組件和漏洞分析結(jié)果的準(zhǔn)確性,以了解安全左移對(duì)開源組件安全帶來的挑戰(zhàn)。
首先從現(xiàn)有學(xué)術(shù)文獻(xiàn)和主流搜索引擎中檢索以下關(guān)鍵詞及其相應(yīng)的組合,分別為開源、組件、依賴、軟件成分、掃描、檢測(cè)及其對(duì)應(yīng)的英文描述,以盡量覆蓋所有SCA 軟件;然后對(duì)檢索到的SCA 工具進(jìn)行二次驗(yàn)證,發(fā)現(xiàn)有些文獻(xiàn)中提及的SCA 工具無法在互聯(lián)網(wǎng)上找到相應(yīng)鏈接,排除后得到21 個(gè)SCA 工具;最后基于以下條件進(jìn)行篩選:①非老舊項(xiàng)目;②對(duì)于開源工具有編譯可執(zhí)行文件,或可編譯出可執(zhí)行文件;③對(duì)于商業(yè)工具能夠免費(fèi)試用;④SCA 功能可正常使用。
通過篩選發(fā)現(xiàn),大部分工具支持Java 語言,因此將不支持Java 的SCA 工具排除,最終篩選出Debricked、Github Dependabot、ScantistSCA、Synk、OWASP dependency check、Eclipse Steady 6 個(gè)SCA 工具。根據(jù)實(shí)際情況,在后續(xù)實(shí)驗(yàn)中選擇合適的SCA 工具。由于每個(gè)SCA 工具產(chǎn)生的掃描報(bào)告標(biāo)準(zhǔn)與格式不統(tǒng)一,本文指定一套標(biāo)準(zhǔn),將不同SCA工具檢測(cè)結(jié)果轉(zhuǎn)化為統(tǒng)一格式。
為使測(cè)試結(jié)果更完備,待測(cè)項(xiàng)目應(yīng)盡可能包含各種不同情況。選取國(guó)內(nèi)開源社區(qū)Gitee 的GVIP 項(xiàng)目,這些項(xiàng)目覆蓋了開發(fā)工具、服務(wù)器應(yīng)用、運(yùn)維、數(shù)據(jù)庫(kù)、插件、人工智能、區(qū)塊鏈等16 個(gè)不同領(lǐng)域的熱門開源項(xiàng)目。為使項(xiàng)目結(jié)構(gòu)更加多樣化,挑選完全由Java 編寫的單模塊和包含多種語言的多模塊項(xiàng)目,其中有些多模塊項(xiàng)目明確定義了子模塊,有些以互相依賴的方式相關(guān)聯(lián)。下載這些項(xiàng)目對(duì)應(yīng)的源碼并進(jìn)行適當(dāng)修改,使其能在本文實(shí)驗(yàn)環(huán)境中通過編譯,最終篩選出13個(gè)工程共68個(gè)子項(xiàng)目。
現(xiàn)有文獻(xiàn)很少對(duì)安全左移場(chǎng)景進(jìn)行系統(tǒng)性梳理,且由于大部分SCA 工具的具體實(shí)現(xiàn)原理是對(duì)用戶屏蔽的,很難直接評(píng)判這些工具是否支持相應(yīng)的安全左移場(chǎng)景。為此,本文定義了一些規(guī)則和認(rèn)定標(biāo)準(zhǔn),梳理出以下安全左移場(chǎng)景:①開發(fā)過程中只使用經(jīng)過審核的開源組件;②對(duì)上游廠商提供的組件進(jìn)行安全檢測(cè);③在項(xiàng)目正式開發(fā)前確定了依賴組件,希望能夠提前了解項(xiàng)目的安全性;④在開發(fā)過程中了解當(dāng)前項(xiàng)目的安全情況。
對(duì)搜集到的SCA 工具進(jìn)行左移場(chǎng)景支持情況統(tǒng)計(jì),結(jié)果見表1。
Table 1 Support for secure left shift of the SCA tool表1 SCA工具安全左移支持情況
驗(yàn)證性實(shí)驗(yàn)的目的為證明安全左移會(huì)使SCA 產(chǎn)生偏移而導(dǎo)致測(cè)試結(jié)果不準(zhǔn)確,從而誘發(fā)開源組件產(chǎn)生安全問題。本文實(shí)驗(yàn)選取軟件開發(fā)過程中常見的安全場(chǎng)景之一,即在項(xiàng)目確定依賴組件時(shí)希望能夠提前了解其供應(yīng)鏈安全性[14-15]。
OWASP TOP10 是軟件安全領(lǐng)域最知名的最危險(xiǎn)安全漏洞類型榜單[16],2021 年該榜單的第一名為訪問權(quán)限控制破壞榜單。Apache Shiro 是一款強(qiáng)大且易用的Java 安全框架,近期其權(quán)限繞過漏洞頻發(fā)?;诖耍x取幾個(gè)包含不同CVE(Common Vulnerabilities&Exposures)漏洞的Shiro 組件,在其基礎(chǔ)上進(jìn)行二次開發(fā)得到新的組件,以構(gòu)造間接引入的不安全項(xiàng)目。選取的Shiro 版本及對(duì)應(yīng)的漏洞見表2。
Table 2 Shiro component version and corresponding CVE vulnerabilities表2 Shiro組件版本及對(duì)應(yīng)的CVE漏洞
首先對(duì)構(gòu)建的4 個(gè)項(xiàng)目進(jìn)行漏洞利用,結(jié)果發(fā)現(xiàn)這4個(gè)漏洞都能夠被成功利用。將4 個(gè)項(xiàng)目的BOM 文件以pom.xml 的格式提取出來用于模擬安全場(chǎng)景,使用Snyk 進(jìn)行基于BOM 和源碼SCA 的SCA 檢測(cè)[17]。對(duì)于基于BOM的SCA,共檢測(cè)出372 個(gè)漏洞,148 個(gè)組件依賴;對(duì)于基于編譯的SCA,共檢測(cè)出388 個(gè)漏洞,201 個(gè)組件依賴。漏洞數(shù)量比組件多的原因?yàn)樵S多漏洞被多個(gè)組件重復(fù)報(bào)告,這些組件之間有傳遞的依賴關(guān)系。此外,二者組件數(shù)有明顯差距,漏洞數(shù)差距不大,且對(duì)于特意間接引入的Shiro 組件漏洞,所有安全左移場(chǎng)景下的SCA 均無法檢測(cè)出。根據(jù)基于編譯的漏洞掃描結(jié)果對(duì)項(xiàng)目進(jìn)行漏洞修復(fù),然后再次對(duì)程序進(jìn)行驗(yàn)證,發(fā)現(xiàn)漏洞已經(jīng)無法再次被利用。該結(jié)果證明編譯場(chǎng)景下SCA 工具對(duì)于軟件安全有非常重要的作用,安全左移將會(huì)導(dǎo)致測(cè)試結(jié)果不準(zhǔn)確。
現(xiàn)有SCA 工具的測(cè)試側(cè)重點(diǎn)多為對(duì)于IDE、CI/CD 工具的支持情況,并沒有量化數(shù)據(jù)的準(zhǔn)確性,而本文更多關(guān)注數(shù)據(jù)準(zhǔn)確性方面,希望將關(guān)注點(diǎn)從各種繁雜的IDE 和DevOps[18]工具中剝離開來。各種安全左移場(chǎng)景中集成的SCA 工具實(shí)際上調(diào)用的是底層服務(wù),檢測(cè)這些安全左移場(chǎng)景的準(zhǔn)確度,最終將其轉(zhuǎn)化為檢測(cè)SCA 工具對(duì)于二進(jìn)制文件、BOM 文件、源碼等的掃描準(zhǔn)確度問題。
對(duì)于安全左移場(chǎng)景1,其準(zhǔn)確度完全依賴于SCA 工具本身使用的漏洞數(shù)據(jù)庫(kù),無法評(píng)估其檢測(cè)結(jié)果的正確性[14]。另外3 種安全左移場(chǎng)景下的代碼可以依據(jù)自身存在的蛻變關(guān)系將測(cè)試結(jié)果與傳統(tǒng)場(chǎng)景下的SCA 進(jìn)行比較。因此,本文對(duì)這3 種安全左移場(chǎng)景進(jìn)行研究,嘗試揭示現(xiàn)有SCA 工具在安全左移場(chǎng)景和傳統(tǒng)使用場(chǎng)景下的表現(xiàn)差異。除開源SCA 工具外,其他工具的內(nèi)部實(shí)現(xiàn)原理是未知的,因此本文采用黑盒測(cè)試[19]的方式進(jìn)行實(shí)驗(yàn)。
基于二進(jìn)制文件和源代碼編譯模式的SCA 之間存在一種蛻變關(guān)系,即二者依賴的組件和漏洞是相同的。為避免不同SCA 工具自身掃描結(jié)果存在誤差的情況,本文對(duì)同種SCA 工具的二進(jìn)制掃描結(jié)果與編譯后的掃描結(jié)果進(jìn)行比較,選擇的SCA 工具為ScantistSCA 和OWASP Dependency Check。
使用編譯將待測(cè)項(xiàng)目集打包為二進(jìn)制文件。通常情況下,對(duì)于Java 項(xiàng)目,二進(jìn)制文件有.jar 和.war 兩種格式,而.war 文件是不會(huì)作為組件依賴被引入項(xiàng)目之中的,即不存在一種安全左移場(chǎng)景會(huì)使用.war 文件,因此從實(shí)驗(yàn)數(shù)據(jù)中去除會(huì)生成.war 文件的項(xiàng)目數(shù)據(jù)。多模塊項(xiàng)目在編譯過程中會(huì)產(chǎn)生多個(gè).jar 文件,因此在統(tǒng)計(jì)多模塊項(xiàng)目數(shù)據(jù)時(shí)對(duì)于父模塊包含子模塊的項(xiàng)目,其父模塊的jar 包已經(jīng)依賴了子模塊,則只對(duì)父模塊的jar 包進(jìn)行測(cè)試;而對(duì)于不存在父子關(guān)系的多模塊項(xiàng)目,則對(duì)每個(gè)子模塊打包得到的.jar文件進(jìn)行測(cè)試。
該實(shí)驗(yàn)的目的為探究SCA 工具對(duì)BOM 文件的檢測(cè)支持情況,了解安全左移場(chǎng)景3 下的安全初步評(píng)估與項(xiàng)目開發(fā)完成后實(shí)際安全情況的誤差。對(duì)于maven 項(xiàng)目來說,其BOM 文件為pom.xml。由于目前可使用的SCA 工具并不能直接對(duì)pom.xml 文件進(jìn)行處理,本實(shí)驗(yàn)采用源碼SCA 的方式間接實(shí)現(xiàn)基于BOM 的SCA 檢測(cè),即在原始項(xiàng)目數(shù)據(jù)的基礎(chǔ)上編寫腳本提取出的pom.xml文件,以此構(gòu)建空的maven 項(xiàng)目,然后對(duì)該項(xiàng)目進(jìn)行源碼掃描作為基于BOM 的SCA。由于源碼掃描分為編譯和不編譯兩種情況,使用不同方式對(duì)同時(shí)支持這兩種方式的SCA 工具進(jìn)行測(cè)試,并在實(shí)驗(yàn)統(tǒng)計(jì)階段將前端的js 等非Java 項(xiàng)目的數(shù)據(jù)從結(jié)果中去除。
本實(shí)驗(yàn)使用的SCA 工具為Github dependabot、Eclipse Steady、ScantistSCA、Snyk、OWASP dependency check,實(shí)驗(yàn)最后統(tǒng)計(jì)漏洞數(shù)、依賴數(shù)、不安全依賴數(shù),并根據(jù)漏洞、依賴列表之間的差異得到BOM 文件檢測(cè)相對(duì)于源碼編譯檢測(cè)的精確度(precision)、召回率(recall)、F1 分?jǐn)?shù)(F1-score)等結(jié)果,計(jì)算公式分別為:
式中,TP 為真正例,F(xiàn)P 為假正例。
不經(jīng)過編譯的依賴樹結(jié)構(gòu)是通過模擬方式生成的,與實(shí)際結(jié)果有一定偏差。在安全左移場(chǎng)景下,項(xiàng)目很有可能不被編譯通過。在SCA 工具的內(nèi)部實(shí)現(xiàn)中,經(jīng)常會(huì)對(duì)不能編譯的項(xiàng)目進(jìn)行依賴樹的模擬生成,以此得到其間接依賴。本實(shí)驗(yàn)的目的為探究各SCA 工具在不編譯情況下模擬生成的依賴相較于編譯得到的結(jié)果偏差,以此了解SCA工具在不能編譯項(xiàng)目的安全左移場(chǎng)景下的精確度情況。采用同時(shí)支持不編譯掃描和編譯掃描的SCA 工具對(duì)項(xiàng)目進(jìn)行測(cè)試,比較源碼編譯結(jié)果的精確度、召回率、F1分?jǐn)?shù)。
對(duì)最終生成jar 包的項(xiàng)目進(jìn)行編譯,得到43 個(gè)不同的jar,對(duì)這些.jar 文件進(jìn)行二進(jìn)制掃描,對(duì)工程文件進(jìn)行編譯的SCA 檢測(cè),數(shù)據(jù)統(tǒng)計(jì)結(jié)果見表3,其中dep、dep*、vuln 分別表示組件數(shù)、不安全的組件數(shù)、漏洞數(shù)。
對(duì)上述數(shù)據(jù)進(jìn)行去重,然后統(tǒng)計(jì)二進(jìn)制與編譯方式的SCA 掃描結(jié)果分布情況,并繪制韋恩圖,見圖1??梢钥闯?,二進(jìn)制SCA 掃描與編譯SCA 掃描結(jié)果存在較大差異,尤其是漏洞數(shù)相較于組件數(shù)方面難以分辨。分析其原因可能為大多數(shù)Java 項(xiàng)目都采用Spring Boot 腳手架進(jìn)行構(gòu)建,Spring Boot 默認(rèn)使用插件進(jìn)行打包,在打包過程中會(huì)將jar 包構(gòu)建為fatjar,給二進(jìn)制掃描帶來了挑戰(zhàn)。同時(shí)二進(jìn)制文件的編譯過程中存在代碼混淆的情況[20-21],如將標(biāo)識(shí)符重命名為無意義的信息、給字符串信息進(jìn)行加密、對(duì)未知文件進(jìn)行移動(dòng)、將代碼轉(zhuǎn)化為偽代碼字節(jié)流等,這些都會(huì)給二進(jìn)制SCA 造成不便。對(duì)于Java 語言來說,使用不同的編譯工具也會(huì)使編譯結(jié)果的字節(jié)碼文件不相同,這可能是導(dǎo)致二進(jìn)制SCA 與基于編譯模式的SCA 結(jié)果差異巨大的原因。
采用Scantist 和Snyk 對(duì)BOM 文件進(jìn)行SCA 檢測(cè)時(shí)可通過基于源碼編譯和不編譯兩種方式得到數(shù)據(jù)。值得注意的是,Snyk 在采用編譯SCA 方式掃描時(shí)存在報(bào)錯(cuò)而不能正常通過掃描的情況。命令行日志中提示的原因?yàn)椴荒苌梢蕾嚇涞拿?,源自于maven 無法在中央倉(cāng)庫(kù)中找到一個(gè)依賴的jar 包,而這個(gè)jar 包是子模塊的jar 包,在此之前mvn install 已經(jīng)安裝到本地倉(cāng)庫(kù),且在本地maven 倉(cāng)庫(kù)中能找到對(duì)應(yīng)的jar 包,執(zhí)行mvn dependenchy:tree 命令能夠正常生成依賴樹。使用其他SCA 工具并不存在這樣的問題,因此對(duì)于基于編譯的SCA 支持不佳的現(xiàn)象可能是由于Snyk 本身不夠完備,這也說明了源碼直接檢測(cè)雖然在準(zhǔn)確度方面可能存在一定問題,但也帶來了檢測(cè)成功率高的優(yōu)勢(shì)。
Fig.1 Wayne diagram of binary and compiled SCA result圖1 二進(jìn)制與編譯SCA結(jié)果韋恩圖
基于BOM 的SCA 檢測(cè)相較于編譯SCA 的偏差情況見表4??梢钥闯觯琒nyk 的source control 和Scantist 的airgap模式相較于其他模式偏差較大,原因可能為這兩種模式是對(duì)源代碼進(jìn)行分析后對(duì)依賴樹進(jìn)行模擬生成,這與基于編譯的SCA 掃描的實(shí)現(xiàn)原理有較大差異,且其源代碼是不完全的,最終導(dǎo)致偏差較大。其他幾個(gè)針對(duì)pom 文件進(jìn)行的SCA 掃描均基于編譯模式,因此數(shù)據(jù)比較接近。Github Dependabot 的精確度、召回率等指標(biāo)全部為1,意味著其在安全左移場(chǎng)景下不會(huì)產(chǎn)生任何偏差,這個(gè)結(jié)果不在預(yù)期之中。通過查閱資料了解到其源碼SCA 檢測(cè)結(jié)果本身就是不準(zhǔn)確的,Dependabot 僅對(duì)BOM 文件中的信息進(jìn)行檢測(cè)[22],而源碼中的BOM 文件是相同的,因此導(dǎo)致最后檢測(cè)結(jié)果相同。
Table 3 Comparison of binary and source compiled SCA表3 二進(jìn)制SCA與編譯SCA比較
Table 4 Deviation between BOM SCA and source compiled SCA表4 基于BOM的SCA檢測(cè)相較于編譯SCA的偏差
所有SCA 工具測(cè)試結(jié)果中漏洞檢測(cè)精確度和召回率均較高,這是由于一個(gè)漏洞可能會(huì)被多個(gè)不同組件引入或組件之間存在依賴關(guān)系,從不同地方發(fā)現(xiàn)了同一個(gè)漏洞,該種安全左移場(chǎng)景下的漏洞檢出率較高。所有基于編譯方式對(duì)pom 文件進(jìn)行的SCA 掃描精確度均接近于1,而召回率存在一定差距,召回率較高的為Eclipse Steady 和Scantist的bom detect模式,這說明對(duì)pom.xml文件進(jìn)行SCA掃描的安全左移場(chǎng)景誤報(bào)概率較小,主要是由于出現(xiàn)數(shù)據(jù)不完整而造成漏報(bào)。
不同SCA 工具對(duì)于是否處理編譯和不編譯模式存在差異。例如Scantist 的命令行工具提供了airgap 模式,在該種模式下,Scantist 將不會(huì)對(duì)源碼進(jìn)行編譯處理,而是通過對(duì)源碼進(jìn)行檢測(cè)模擬生成依賴樹來進(jìn)行掃描。而Snyk 的命令行工具在執(zhí)行測(cè)試命令前要求項(xiàng)目能夠使用mvn install 命令進(jìn)行編譯,如果項(xiàng)目無法編譯通過,Snyk 的測(cè)試命令將因無法正常執(zhí)行而拋出異常。在實(shí)測(cè)過程中發(fā)現(xiàn),執(zhí)行Snyk 命令行時(shí)實(shí)際上是調(diào)用maven 命令生成依賴樹,因此Snyk 使用命令行工具是以編譯的方式進(jìn)行檢測(cè)的,對(duì)于那些Snyk 不能正常導(dǎo)入的項(xiàng)目則通過Git倉(cāng)庫(kù)集成的方式得到掃描結(jié)果,而這種方式顯然是不編譯的。
基于源碼的不編譯與編譯模式SCA 結(jié)果比較見表5??梢钥闯觯琒cantist 和OWASP Dependency Check 兩個(gè)工具在組件數(shù)和有漏洞的組件數(shù)方面存在較大偏差,在漏洞數(shù)檢測(cè)方面均表現(xiàn)較好。分析原因可能為多個(gè)組件會(huì)引入同一個(gè)漏洞,最終同時(shí)被檢測(cè)出。導(dǎo)致組件數(shù)結(jié)果不準(zhǔn)確的原因在于不編譯方法的依賴樹信息是基于代碼信息模擬生成的,組件及其依賴關(guān)系是通過推測(cè)得到的,由于模擬生成依賴樹的每一層都有偏差,最終導(dǎo)致其與編譯SCA方法生成的依賴樹相差較大。
Table 5 Comparison of results between uncompiled and compiled modes based on source code表5 基于源碼的不編譯和編譯模式結(jié)果比較
本文提出在安全左移場(chǎng)景下開源組件安全可能面臨的挑戰(zhàn),并設(shè)計(jì)了多組實(shí)驗(yàn)對(duì)不同安全左移場(chǎng)景下的開源組件安全檢測(cè)準(zhǔn)確率進(jìn)行研究。結(jié)果顯示,現(xiàn)有SCA 檢測(cè)工具在安全左移場(chǎng)景下的檢測(cè)結(jié)果均產(chǎn)生了較大偏差,進(jìn)而對(duì)偏差產(chǎn)生的原因進(jìn)行分析,為SCA 檢測(cè)的優(yōu)化方向提供了參考。然而,本次實(shí)驗(yàn)僅針對(duì)Java 語言和maven 構(gòu)建工具展開,對(duì)于其他編程語言和構(gòu)建工具不一定具有適用性。后續(xù)將針對(duì)基于其他編程語言和構(gòu)建工具的軟件開發(fā)在安全左移場(chǎng)景下的開源組件安全進(jìn)行研究,同時(shí)將通過融合SCA 構(gòu)建出漏洞檢測(cè)和自修復(fù)的二進(jìn)制制品倉(cāng)庫(kù),為安全左移場(chǎng)景下的軟件開發(fā)提供更多網(wǎng)絡(luò)安全保障。