導(dǎo)語:新一代IAST灰盒安全測試技術(shù)憑借其極高的檢出精度、深度的業(yè)務(wù)透視能力及高度自動化CI/CD支持能力,正快速由行業(yè)頭部用戶的場景化探索實(shí)踐向廣大中小型用戶規(guī);瘧(yīng)用實(shí)踐演進(jìn)。由于其特殊的技術(shù)原理,使得該項(xiàng)新技術(shù)對業(yè)務(wù)語言的覆蓋支持成為關(guān)鍵落地因素之一。
今年6月,中國信息通信研究院(以下簡稱“中國信通院”)正式發(fā)布《交互式應(yīng)用程序安全測試工具能力要求》行業(yè)標(biāo)準(zhǔn)(以下簡稱“IAST標(biāo)準(zhǔn)”),并于首屆DevSecOps敏捷安全大會(DSO 2021)首次公開標(biāo)準(zhǔn)解讀。目前,中國信通院已完成首批評估測試,懸鏡靈脈IAST是全球首個通過該項(xiàng)專業(yè)測評認(rèn)證的IAST工具。
自IAST標(biāo)準(zhǔn)發(fā)布起,中國信通院同步啟動了首批IAST工具的測試工作。依托標(biāo)準(zhǔn)要求中的34個功能指標(biāo)項(xiàng),在統(tǒng)一并發(fā)場景下進(jìn)行性能檢測記錄。通過對測試結(jié)果分析發(fā)現(xiàn),各廠商IAST工具在以下三方面存在較大差異:
1、對主流編程語言支持的覆蓋率;
2、對不同安全漏洞類型及結(jié)果的定義規(guī)范;
3、配置缺陷和弱密碼等低危漏洞或信息漏洞的檢測結(jié)果。
其中,首當(dāng)其沖的是對主流編程語言的覆蓋率問題。在IAST標(biāo)準(zhǔn)當(dāng)中,“支持的編程語言”被標(biāo)定為全標(biāo)準(zhǔn)的第一條測試要求,由此可見其重要性。IAST工具是否支持多種主流編程語言,直接決定了其是否能適配客戶各種各樣的實(shí)際開發(fā)場景,進(jìn)而滿足助力客戶業(yè)務(wù)發(fā)展的需求。
圖:IAST標(biāo)準(zhǔn)中對編程語言的要求
多種編程語言的支持,對用戶的意義不是夠不夠好,而是能不能用。如果用戶核心業(yè)務(wù)使用的語言沒有被IAST探針支持,即使IAST產(chǎn)品有100分的其它功能,對用戶來說也是0分。
01 IAST工具介紹
IAST(Interactive Application Security Testing, 交互式應(yīng)用安全測試)是應(yīng)用程序在進(jìn)行自動化測試、人工測試等任何與應(yīng)用程序進(jìn)行“交互”的同時(shí),能自動分析應(yīng)用程序安全風(fēng)險(xiǎn)的技術(shù)。它可以實(shí)時(shí)返回結(jié)果,因此不會額外增加CI/CD的時(shí)間。
相比于其他AST技術(shù),IAST只會分析“交互”產(chǎn)生時(shí)所影響到相關(guān)代碼的安全風(fēng)險(xiǎn),而不是掃描所有代碼、配置文件或遍歷整個站點(diǎn)。IAST更適合在QA環(huán)節(jié)使用,讓安全團(tuán)隊(duì)在相對不影響開發(fā)、測試現(xiàn)有流程的情況下,較早地發(fā)現(xiàn)應(yīng)用程序中存在的安全風(fēng)險(xiǎn)。
需要注意的是,與其他AST技術(shù)相比,IAST還是一個比較新的概念,其基于請求、代碼數(shù)據(jù)流/控制流來綜合分析應(yīng)用程序的安全風(fēng)險(xiǎn)。IAST運(yùn)行時(shí)插樁技術(shù)可以發(fā)現(xiàn)更多應(yīng)用程序本身的安全弱點(diǎn),以及應(yīng)用程序中第三方組件的公開漏洞。由于該技術(shù)針對不同語言需要研發(fā)不同的插樁探針,因此對于廠商而來,其IAST工具每增加對一種語言的支持,即相當(dāng)于開發(fā)一款新產(chǎn)品,也就意味著IAST工具支持的編程語言越多,廠商所需投入的人力成本和經(jīng)濟(jì)成本也就越大。
支持多種編程語言插樁,是IAST技術(shù)未來發(fā)展的必然趨勢,原因在于不同行業(yè)由于屬性不同,對開發(fā)語言有特殊要求。例如金融行業(yè),普遍以Java語言為主;互聯(lián)網(wǎng)行業(yè)則是多語言環(huán)境的典型代表,使用的語言五花八門,Java占比較高,同時(shí)也會使用Python、Go、Node.js、.Net等語言來適配多種業(yè)務(wù)場景。如此,一款好的IAST工具支持多語言插樁是必要基礎(chǔ),也是IAST工具廠商在技術(shù)上必然的拓展方向。
02 主流編程語言分析
截至2021年7月TIOBE發(fā)布的編程語言指數(shù)報(bào)告,排在前十名的編程語言中,常見的應(yīng)用開發(fā)語言主要有Java、Python、C#、JavaScript、PHP這5種(VB.Net 隨著 .Net Core 和 .Net 5.0 的推出,跨平臺方面優(yōu)勢將不再明顯,因此不再討論)。
圖:TIOBE-2021年7月編程語言排行(TIOBE Index for July 2021)
根據(jù)TIOBE指數(shù)排行,這里列出了百度指數(shù)、Google Trends以及Stack Overflow Trends近年內(nèi)對Java、PHP、Node.js、Python、C#這些語言的熱度檢測趨勢:
圖:近4年間Java、PHP、Node.js、Python、C#編程語言百度指數(shù)趨勢
圖:近4年間Java、PHP、Node.js、Python、C#編程語言Google Trends趨勢
圖:近12年間Java、PHP、Node.js、Python、C#編程語言Stack Overflow Trends趨勢
通過對比上述各平臺的趨勢發(fā)現(xiàn),對著數(shù)據(jù)科學(xué)、人工智能等領(lǐng)域的興起,Python的熱度扶搖直上。作為一種動態(tài)類型語言,使用Python作為Web應(yīng)用程序的主要開發(fā)語言可以在初期為項(xiàng)目節(jié)省大量的時(shí)間和成本。例如:早期的YouTube、知乎平臺等,均使用Python作為主要的Web開發(fā)語言。
但是由于Python在多線程上的硬傷和動態(tài)類型語言后期不易維護(hù)的特點(diǎn),很多企業(yè)在完成初期的用戶積累后,都會選擇使用一門靜態(tài)類型的語言來重構(gòu)他們的應(yīng)用,例如Java、C#或者Golang。
Java憑借其簡單易懂的語言、活躍的社區(qū)支持、以及JVM優(yōu)秀的跨平臺支持,使其成為全球使用最多、最廣泛的Web應(yīng)用程序編程語言。
C#背靠Microsoft,憑借ASP.NET、Razor、良好的社區(qū)、宇宙級IDE:Visual Studio,再加上語法和Java、C等語言相近的特點(diǎn),也在Web應(yīng)用程序編程語言中占有一席之地,但在國內(nèi)熱度相對較低。
PHP 與 Python 一樣,也是一種動態(tài)類型語言。由于一定的歷史原因,PHP 作為“世界上最好的語言”在國內(nèi)熱度一直較高。低學(xué)習(xí)門檻、易于開發(fā)和部署的特點(diǎn),讓很多企業(yè)選擇使用 PHP 來編寫公司官方網(wǎng)站或者與微信開放平臺對接。
Node.js在嚴(yán)格意義上來說并非一門語言,而是使用JavaScript引擎構(gòu)建的平臺。Java、C#契合Web應(yīng)用程序開發(fā)的一部分原因是其能夠和JavaScript/TypeScript友好地融合(例如:Jsp技術(shù)和Razor技術(shù))而Node.js作為直接使用JavaScript來構(gòu)建的平臺,在這方面有天然優(yōu)勢。同時(shí),由于JavaScript引擎的更迭,其效率越來越高,加上原生支持異步處理等特點(diǎn),非常適合快速構(gòu)建Web應(yīng)用,因此熱度也在不斷上漲。
目前國內(nèi),面向互聯(lián)網(wǎng)的Web應(yīng)用程序主要以Java、PHP來編寫,內(nèi)網(wǎng)應(yīng)用則呈現(xiàn)出多元化的態(tài)勢,以快速實(shí)現(xiàn)功能為主要目標(biāo),因此使用Python、Node.js、Golang、C# 來開發(fā)的應(yīng)用占比也相對更高。
03主流語言插樁原理簡述
IAST 插樁探針想要分析數(shù)據(jù)流需要做兩件事情。第一點(diǎn)是如何“理解”代碼。我們需要根據(jù)不同語言來區(qū)分,需要關(guān)注哪些函數(shù),這些函數(shù)里哪些是污點(diǎn)輸入?哪些是污點(diǎn)傳播?哪些是污點(diǎn)清洗?以及又有哪些是污點(diǎn)匯聚?這個我們可以根據(jù)不同的漏洞原理來做分析,第二點(diǎn),我們?nèi)绾尾东@關(guān)鍵函數(shù)的調(diào)用情況?這需要我們從各種語言底層做突破,使得我們能讀取到關(guān)鍵函數(shù)何時(shí)被調(diào)用、傳入了什么參數(shù)、數(shù)據(jù)傳遞給了誰。下面將針對不同語言,淺析 IAST 插樁捕獲關(guān)鍵函數(shù)的原理。
圖:靈脈IAST支持的部分中間件及框架
作為全球首款通過中國信通院交互式應(yīng)用程序安全測試工具(IAST)能力認(rèn)證的產(chǎn)品,靈脈IAST是國內(nèi)唯一支持Java、PHP、Node.js、Python、.Net、Go等全部主流語言的IAST工具,其中各語言具體支持的部分中間件及框架如上圖所示。以下將結(jié)合靈脈IAST工具簡述主流語言插樁原理。
Java
如果語言本身提供了插樁的接口,那么探針開發(fā)的難度將會大大降低。例如Java提供了一個instrumentation 接口。通過該接口,可以以一種標(biāo)準(zhǔn)的方式,在啟動應(yīng)用時(shí)添加javaagent參數(shù)來加載插樁探針,從而實(shí)現(xiàn)動態(tài)數(shù)據(jù)流污點(diǎn)追蹤。大致流程如下:
圖:Java實(shí)現(xiàn)動態(tài)數(shù)據(jù)流污點(diǎn)追蹤流程
如圖所示,通過紅色的JVM Agent路徑,就可以獲取到Hello類中的方法何時(shí)被調(diào)用、接受到了哪些參數(shù)等信息。更進(jìn)一步,就可以阻斷它的執(zhí)行(RASP的功能),甚至修改它的執(zhí)行邏輯。當(dāng)然,即便官方已經(jīng)提供了標(biāo)準(zhǔn)做法讓插樁探針的研究少走彎路,但是構(gòu)建成熟的Java探針并非易事。
除Java外,其他一些語言也使用了JVM虛擬機(jī),例如Scala、Kotlin等,這些語言的插樁原理比較類似,不再贅述。
PHP
PHP Core使用C語言編寫,默認(rèn)情況下,PHP開發(fā)者使用的所有函數(shù)都在PHP Core和C中定義。當(dāng)PHP程序在運(yùn)行時(shí),有三個主要組件進(jìn)行交互:
l 用戶代碼(用戶自有代碼、框架等);
l 擴(kuò)展(數(shù)據(jù)庫驅(qū)動、cURL等);
l PHP Core。
PHP程序通常有如下兩種主要運(yùn)行方式:
l Web模塊(如Apache mod_php);
l 獨(dú)立進(jìn)程(如PHP-FPM),常用于與反向代理通信)。
在PHP中,沒有多線程的概念,每一個請求都會生成一個新的進(jìn)程。因此,很多PHP服務(wù)器上同時(shí)會處理成百上千個PHP進(jìn)程。一個進(jìn)程可以理解為一條請求。當(dāng)一條請求進(jìn)行PHP應(yīng)用程序后,將會經(jīng)歷如下生命周期:
1、 MINIT(模塊初始化)
2、 RINIT(請求初始化)
3、 執(zhí)行響應(yīng)PHP代碼邏輯,生成相應(yīng)并返回
4、 RSHUTDOWN(請求關(guān)閉)
5、 MSHUTDOWN(模塊關(guān)閉)
PHP插樁檢測的主要方式是替換內(nèi)部函數(shù),將原始請求暫存在特定的位置,并觸發(fā)探針分析,分析引擎通過比對函數(shù)列表檢索出被調(diào)用的函數(shù)并記錄,然后釋放原始請求,再以同樣的方式繼續(xù)執(zhí)行,分析之后的內(nèi)容。流程如下:
圖:PHP插樁檢測流程
如上圖所示,PHP插樁探針包裝了原始函數(shù),就像安檢一樣,你和你的行李(原始數(shù)據(jù))需要通過安檢儀器后才能進(jìn)入下一階段。但在早期的實(shí)踐中,我們發(fā)現(xiàn)過多的“安檢”會造成很大的性能損失,因此在靈脈IAST中,研發(fā)團(tuán)隊(duì)針對性插樁關(guān)鍵函數(shù),配合主動驗(yàn)證功能,在保證對業(yè)務(wù)影響最小的情況下,實(shí)現(xiàn)高效檢出。
Node.js
JavaScript的靈活性為Node.js動態(tài)插樁檢測提供了便利。但是由于Node.js有著眾多版本,很多版本之間API變化很大,因此,對于不同Node.js版本插樁探針的構(gòu)建將會有不少的坑要踩。對于Node.js插樁探針,通常采用和 PHP 類似的方法 ——包裝函數(shù)。要構(gòu)建一個Node.js插樁探針,至少需要從以下幾個方面著手研究:
1、跟蹤導(dǎo)入的模塊;
2、構(gòu)建包裝器;
3、構(gòu)建Hooks。
首先,由于Node.js導(dǎo)入模塊時(shí),會將模塊保存在本地位置(如node_modules)。通過require語句或者遍歷本地模塊目錄,可以檢索出所有需要跟蹤/監(jiān)聽的模塊。然后,根據(jù)上一步得到的模塊列表,針對性地篩選出需要包裝的方法/函數(shù)。接著,將構(gòu)建的Hooks置于包裝后的方法中。最后,當(dāng)Hooks被觸發(fā)時(shí),調(diào)用引擎對其進(jìn)行分析。至此,分析引擎將能獲取到原始數(shù)據(jù),根據(jù)需要,我們可以對數(shù)據(jù)流進(jìn)行阻斷、處理、放行等操作。
與PHP不同的是,在Node.js中導(dǎo)入模塊是一個同步的操作,添加一個跟蹤器來跟蹤模塊導(dǎo)入的開銷可以忽略不記。觸發(fā)Hooks會影響代碼邏輯的執(zhí)行時(shí)間,但這是不可避免的,和PHP一樣,需要篩選出關(guān)鍵函數(shù)來進(jìn)行監(jiān)控。
Python
得益于Python內(nèi)建的自省機(jī)制,使得在Python上構(gòu)建插樁探針變得安全可靠。和PHP、Node.js類似,構(gòu)建Python插樁探針的主要方法同樣是包裝底層函數(shù)。PEP 302提供了import hook的方式,在被引用的模塊被加載前,就可以動態(tài)地對特定函數(shù)添加裝飾器,也避免了在其他位置重復(fù)引用而導(dǎo)致裝飾器失效的糟心問題。
雖然對于使用Python定義的函數(shù)進(jìn)行包裝相對容易,但在常用的CPython解釋中,很多類都是由C定義(例如,大多數(shù)的DB Driver)。好在絕大多數(shù)的DB Driver(SQLite、MySQL等)都遵循 PEP 249 ,這樣就有機(jī)會順著DB Driver的調(diào)用鏈一路打補(bǔ)丁。對于未遵循DBApi2的DB Driver(NoSQL等),則需要更多的工作量。
.Net
眾所周知,.Net技術(shù)體系與Java高度重疊。表現(xiàn)在探針產(chǎn)品層面,就是.Net探針與 Java探針在作用原理與產(chǎn)品架構(gòu)上高度相似。所不同的是,.Net CLR并未提供類似java.lang.instrument包那樣易于使用的接口。實(shí)際上,.Net探針的主要技術(shù)難度集中在如何像Java改寫bytecode一樣動態(tài)地改寫JIT階段的CIL編碼。
在實(shí)際實(shí)現(xiàn)時(shí),.Net探針利用了CLR的Profiling接口,通過C++實(shí)現(xiàn)一套類似JVM Instrumentation API的IL改寫機(jī)構(gòu),以將基于C#安全保障業(yè)務(wù)邏輯注入到關(guān)鍵方法之中。除去這套IL改寫機(jī)構(gòu)帶來的麻煩外,GAC、mscorlib/System.Private.CoreLib等 .Net特性都最終使得探針在形態(tài)上與前述各語言區(qū)別較大。
目前,一場變革正在.Net技術(shù)世界中發(fā)生,無論是轉(zhuǎn)向開源的.Net Core還是作為“下一代”的.Net5/6都在底層上引入了不少變動。幸運(yùn)的是,在CLR層次上的變動仍然相對保守。因此,目前探針同時(shí)具備對傳統(tǒng)的 .Net Framework、.Net Core 與最新的 .Net 5/6 環(huán)境的適應(yīng)性。之后,我們也會持續(xù)跟蹤該領(lǐng)域內(nèi)的各項(xiàng)進(jìn)展。
GO
Go 語言是近幾年興起的技術(shù)門類,其核心優(yōu)勢在于開發(fā)/運(yùn)行效率高、工具鏈完善且二進(jìn)制易于部署。然而,對這種直接編譯為二進(jìn)制的技術(shù)體系,利用 Runtime 機(jī)制進(jìn)行插樁的方式就不再有效。因而,Go 探針在形態(tài)上與使用體驗(yàn)上與其他探針云泥之別。得益于Go的開源特性,可以直接對Go工具鏈的源碼進(jìn)行改寫。我們通過將 `go build`命令邏輯進(jìn)行改寫,實(shí)現(xiàn)`xmirror-go build`命令,即可在項(xiàng)目構(gòu)建過程中,將安全保障邏輯加入關(guān)鍵方法之中。
對Go語言的支持,是靈脈IAST全覆蓋主流編程語言的最后一公里,靈脈IAST Go探針已進(jìn)入測試驗(yàn)證階段,很快將在正式版產(chǎn)品中與大家見面。
04靈脈IAST探針的特點(diǎn)
懸鏡靈脈IAST在銀行、證券、保險(xiǎn)、能源、電力、運(yùn)營商、智能制造及泛互聯(lián)網(wǎng)等不同行業(yè)的復(fù)雜業(yè)務(wù)場景下進(jìn)行了廣泛的應(yīng)用和落地實(shí)踐,沉淀出了高適配、低消耗,高檢出、低誤報(bào)等綜合技術(shù)優(yōu)勢。目前靈脈IAST探針具有以下特點(diǎn):
插樁規(guī)則動態(tài)更新 :插樁檢測規(guī)則并非靜態(tài)在探針內(nèi)定義,而是以動態(tài)的方式下檢測規(guī)則集,并且檢測規(guī)則及規(guī)則集均支持自定義,最大程度上避免誤報(bào)、漏報(bào)的產(chǎn)生;
無需修改現(xiàn)有代碼 :無需修改現(xiàn)有代碼,只需在啟動時(shí)添加參數(shù)應(yīng)用插樁探針(啟動時(shí)加載),或者在應(yīng)用啟動后通過進(jìn)程ID(pid)動態(tài)加載(熱加載)即可完成插樁;
開源組件依賴分析 :運(yùn)行時(shí)動態(tài)分析應(yīng)用程序依賴鏈,通過指紋、同源代碼片段匹配等多種手段分析應(yīng)用程序引入第三方開源組件的風(fēng)險(xiǎn);
性能優(yōu)化 :經(jīng)過大量客戶驗(yàn)證,對性能影響極小。并提供熔斷開關(guān),當(dāng)階段內(nèi)CPU占用超過設(shè)定時(shí),自動停用,優(yōu)先業(yè)務(wù)順暢運(yùn)行;當(dāng)CPU空閑時(shí)自動恢復(fù)工作;
多功能探針 :主動插樁、被動插樁,甚至RASP插樁,共用同一個探針,可以通過Web界面隨時(shí)切換工作模式;
臟數(shù)據(jù)處理 :主動模式下,可通過Web界面上的開關(guān)控制是否釋放臟數(shù)據(jù);
自動回歸測試 :被動模式下,可通過Web界面啟動回歸測試,再次觸發(fā)請求,如果漏洞已修復(fù),將自動更新漏洞狀態(tài)為“已修復(fù)”。
05IAST語言支持的發(fā)展
從2012年首次被提出,到近年成為軟件安全領(lǐng)域的技術(shù)焦點(diǎn),IAST工具正在向規(guī)范化和規(guī);瘧(yīng)用發(fā)展。隨著IAST行業(yè)用戶的快速增長,對應(yīng)用編程語言的覆蓋率、IAST檢測精度及業(yè)務(wù)全場景支持已成為評判IAST工具成熟度的主要標(biāo)準(zhǔn)。
目前對Java、PHP、Node.js、Python、.Net、Go等主流語言的覆蓋率,相比國內(nèi)其他廠商僅支持一兩款語言,Contrast、懸鏡安全和Synopsys處于全面領(lǐng)跑地位。對主流語言的覆蓋率,是當(dāng)前絕大多數(shù)IAST工具需要在未來很長一段時(shí)間內(nèi)持續(xù)彌補(bǔ)的技術(shù)短板。
表:國內(nèi)外廠商IAST部分功能對比