成在人线av无码免费,,,

米樂M6

公司新聞

CodeQL米樂M6 M6米樂的自動化代碼審計之路(中篇)

  在上一篇文章中,我們已經(jīng)了解了關于CodeQL的基本語法,從實際案例角度來體驗了CodeQL在代碼審計中的作用。從這篇文章開始,我們將開始真正打造基于CodeQL的自動化代碼審計工具,由于這僅僅是來自于個人興趣的研究,并非來自成熟項目,所以在文章中可能缺陷,各位大佬如果有更好的意見建議,請私信。

  CodeQL的代碼審計整體過程可以分成兩個部分,如圖1.1所示,分別是從源代碼解析成CodeQL數(shù)據(jù)庫和從數(shù)據(jù)庫中查詢出安全隱患。本次分享主要關注第二階段的內(nèi)容,假設我們已經(jīng)有了CodeQL數(shù)據(jù)庫之后,下一步基于數(shù)據(jù)庫的自動化查詢。

CodeQL米樂M6 M6米樂的自動化代碼審計之路(中篇)(圖1)

  為什么我們最終結(jié)果得到的是安全隱患,而不是漏洞呢?這是因為CodeQL并不是萬能的,它只能幫我們找到可能的安全隱患,而不能一定確認漏洞存在,這在后面的文章中會說到原因。

  當前的自動化代碼審計工具將采用python3開發(fā),針對的目標語言是java,后續(xù)如果有時間,也會陸續(xù)支撐其他語言。目前代碼還不是特別完善,后期后繼續(xù)對代碼進行優(yōu)化,見github地址:

  基于CodeQL的自動化代碼審計工具流程其實和傳統(tǒng)的漏洞掃描工具相似,所以我們還是按照傳統(tǒng)漏掃的思路來設計工具。關于第一階段源碼轉(zhuǎn)化為數(shù)據(jù)庫的部分在下一篇文章來詳述,這里還是只關注第二階段數(shù)據(jù)庫查詢的內(nèi)容,如圖2.1所示。

CodeQL米樂M6 M6米樂的自動化代碼審計之路(中篇)(圖2)

  其實從流程中可以看出,工具的主要功能是基于ql插件的遍歷,對插件結(jié)果的格式化輸出。首先需要解決的問題是關于ql插件來源的問題,在上一篇文章中,我們有提到CodeQL官方給我們提供了很多測試用的demo實例

  官方按照CWE提供了多個不同類型的ql插件,部分插件是可以直接來用的,但是有的插件涉及到自定義qll庫,需要進行一定的轉(zhuǎn)化才能使用,如圖2.2所以,F(xiàn)ilePathInjection.ql腳本就是典型的有自定義庫的腳本。

CodeQL米樂M6 M6米樂的自動化代碼審計之路(中篇)(圖3)

  在我們設計的自動化工具中,為了方便會只查詢單個ql腳本,需要把ql腳本中調(diào)用的qll庫進行轉(zhuǎn)化。轉(zhuǎn)化的方式是顯示的把qll庫中定義的類和謂詞直接定義到ql腳本中,我已經(jīng)把官方提供的全部腳本都轉(zhuǎn)化了一遍,后續(xù)會將完整的代碼分享到github。

  為了方便統(tǒng)一的對結(jié)果進行格式化輸出,我們期待每一個ql文件最終返回的結(jié)果都是統(tǒng)一格式,所以還需要對每個ql文件最終的返回結(jié)果進行約束,典型的demo如下所示。其中select后面的值是ql腳本最終返回的數(shù)據(jù)。

  由于CodeQL官方并不對引擎開源,我們只能直接使用官方編譯好的版本,官方編譯好的引擎并不支持python這些語言,只能從命令行進行調(diào)用,如圖2.3所示。其中-d參數(shù)用于表示待查詢的數(shù)據(jù)庫路徑,最后跟的是要查詢的ql腳本路徑。

  由于CodeQL每次查詢都需要使用ql腳本文件路徑,如果每次查詢都需要先生成一個文件,然后查詢結(jié)束之后再刪除文件,代碼顯得怪怪的。好在python給我們提供了tempfile庫,可以稍微優(yōu)雅的解決這個問題,如圖2.4所示。這是一段我項目中檢查環(huán)境是否準備好了的代碼,通過tempfile生成臨時的ql腳本,臨時腳本在運行結(jié)束之后會自動自動刪除。

CodeQL米樂M6 M6米樂的自動化代碼審計之路(中篇)(圖4)

  本來想自己封裝了一個類來調(diào)用調(diào)用CodeQL運行,但是突然看到網(wǎng)上已經(jīng)有大佬寫好了一個相應的類,其實現(xiàn)思路和我之前的想法差不多,本質(zhì)上還是從命令行調(diào)用的CodeQL。然而我直接運行大佬的代碼卻運行不成功,主要原因還是在于生成的臨時文件必須要在ql sdk所在測試路徑,路徑下必須有正確配置的qlpack.yml文件。所以我在原代碼的基礎上修改了一下,主要是固定sdk路徑為配置好的路徑。

  這之后我們一個簡易的基于CodeQL的自動化代碼審計工具雛型就差不多了,后續(xù)會陸續(xù)在這個框架的基礎上優(yōu)化功能。

  官方雖然提供了大約59個java的ql查詢插件,但是實際上還遠不能滿足我們的需求,我們希望有更多的白帽子參與進來提供更多的ql查詢插件。當前階段,我按照自己日常漏洞挖掘過程補充一些ql查詢插件,如下所示,相關插件均在plugins/java_ext目錄。

  本次新增只是一個開端,并不能覆蓋全部,自知還相差很遠。但是不斷的優(yōu)化,總歸會有好的效果。由于部分小伙伴對與CodeQL的語法了解甚少,我們用一個簡單的腳本Unserialze.ql來說明完整的CodeQL腳本的寫法。

  反序列化漏洞是java中常見的漏洞,典型的漏洞代碼寫法如下。這是一段從某應用中提取的真實漏洞的部分代碼。

  其中最關鍵的是用戶可控的source點為request.getInputStream(),最后的危險操作sink點為objin.readObject()。也就是說外部傳入的postdata直接進行了反序列化操作,則可能導致反序列化漏洞。對于CodeQL中,可以編寫對應的查詢腳本如下。

  其中source點直接使用CodeQL預定義的類RemoteFlowSource,而sink點則是通過下面的代碼實現(xiàn)。判斷的邏輯是存在一個方法名為readObject的調(diào)用,并且調(diào)用的主體繼承自utStream類。注意這些說的是反序列化漏洞,不涉及利用鏈,不一定就真的能導致RCE效果。

  米樂M6 M6米樂

  單獨執(zhí)行對應的腳本,則可以發(fā)現(xiàn)程序中可能存在的反序列化漏洞,如圖3.1所示。

CodeQL米樂M6 M6米樂的自動化代碼審計之路(中篇)(圖5)

  其他腳本就不再依次講解,如果有小伙伴感興趣,非常期待小伙伴能為我們提供插件。如果小伙伴不知道怎么編寫CodeQL腳本,可以把有漏洞的代碼邏輯給私信我,由我來轉(zhuǎn)化為CodeQL插件。

  使用之前應該首先安裝CodeQL,并配置,其中最關鍵的是配置臨時生成的ql腳本保存的路徑qlpath,如圖4.1所示。確保qlpath當前目錄下面有配置文件qlpack.yml。如果使用的過程中有問題,建議把debug配置為on。

  米樂M6 M6米樂

CodeQL米樂M6 M6米樂的自動化代碼審計之路(中篇)(圖6)

  參數(shù)-s代表是否跳過環(huán)境檢查,不填默認為false,首次使用建議不跳過環(huán)境檢測。

CodeQL米樂M6 M6米樂的自動化代碼審計之路(中篇)(圖7)

  最終的掃描結(jié)果是以csv文件保存在out/result/目錄,打開相應的結(jié)果,如圖4.4所示。

CodeQL米樂M6 M6米樂的自動化代碼審計之路(中篇)(圖8)

  在圖4.4的結(jié)果中,有很多FilePathInjection插件掃描的結(jié)果,其中記過都很相似,以其中之一為例,我們基于文件的source和sink定位其中的問題。

CodeQL米樂M6 M6米樂的自動化代碼審計之路(中篇)(圖9)

CodeQL米樂M6 M6米樂的自動化代碼審計之路(中篇)(圖10)

  這里其實RuoYI已經(jīng)對上傳文件的文件擴展名進行了限制,然后CodeQL仍然把這里識別為漏洞,這是典型的誤報行為,而這也是CodeQL的代碼審計工具中最難解決的一個問題。

  米樂M6 M6米樂

  CodeQL可以跟蹤Source和Sink流,但是畢竟仍然只是靜態(tài)代碼審計工具,無法自動解析代碼中的一些過濾操作,導致可能會出現(xiàn)誤報。而這也是文章開頭提到的CodeQL只能作為輔助工具發(fā)現(xiàn)安全隱患,不能確定是否一定存在漏洞的原因。

  距離自動化的代碼審計工具,我們?nèi)匀挥泻荛L的路要走,如果小伙伴能提供一些可用的ql插件或者提供有漏洞的代碼樣本由我們來編寫ql插件,我們都將非常感激。