由于博客實在沒什么可以更新的了,我就把目前做的事情總結一下,當做一篇博客,主要是談一談項目中所運用的一些技術。目前市面上有不少PHP的自動化審計工具,開源的有RIPS、Pixy,商業(yè)版本的有Fortify。RIPS現(xiàn)在只有第一版,由于不支持PHP面向?qū)ο蠓治?,所以現(xiàn)在來看效果不是太理想。Pixy是基于數(shù)據(jù)流分析的工具,但是只支持PHP4。而Fortify是商業(yè)版本,由于這個限制,對它的研究也就無從談起。國內(nèi)對于PHP自動審計的研究一般都是公司在做,目前有些工具大多數(shù)使用簡單的token流分析或者直接粗暴一些,使用正則表達式來匹配,效果會很一般。
今天所要談的技術是基于靜態(tài)分析的一種PHP自動化審計的實現(xiàn)思路,也是我的項目中的思路。為了進行更加有效的變量根據(jù)和污點分析,以及很好的應對PHP腳本中的各種靈活的語法表示,正則表達式效果肯定是不理想的,我所介紹的思路是基于代碼靜態(tài)分析技術和數(shù)據(jù)流分析技術的審計。
首先,我認為一個有效審計工具至少包含如下的模塊:
1、編譯前端模塊
編譯前端模塊主要運用編譯技術中的抽象語法樹構建、控制流圖構建方法,將源碼文件轉為適合后端靜態(tài)分析的形式。
2、全局信息搜集模塊
該模塊主要用于對分析的源碼文件進行統(tǒng)一的信息搜集,比如搜集該審計工程中有多少類的定義,并對類中的方法名、參數(shù)、以及方法定義代碼塊的起始和終止的行號進行搜集,用于加快后續(xù)的靜態(tài)分析的速度。
3、數(shù)據(jù)流分析模塊
該模塊不同于編譯技術中的數(shù)據(jù)流分析算法,在項目中更注重對PHP語言本身特性的處理。當系統(tǒng)的過程間和過程內(nèi)分析過程中發(fā)現(xiàn)了敏感函數(shù)的調(diào)用,則對該函數(shù)中敏感的參數(shù)進行數(shù)據(jù)流分析,即跟蹤該變量的具體變化,為后續(xù)污點分析做準備。
4、漏洞代碼分析模塊
該模塊基于數(shù)據(jù)流分析模塊收集的全局變量、賦值語句等信息,進行污點數(shù)據(jù)分析。主要針對敏感sink中的危險參數(shù),如mysql_query函數(shù)中的第一個參數(shù),經(jīng)過回溯獲取到相應的數(shù)據(jù)流信息,如果在回溯過程中發(fā)現(xiàn)該參數(shù)有用戶控制的跡象,就進行記錄。如果該危險參數(shù)有相應的編碼、凈化操作也要進行記錄。通過對危險參數(shù)的數(shù)據(jù)進行跟蹤和分析,完成污點分析。
0×02
有了模塊,那么如何進行有效的流程來實施自動化審計,我使用了如下的流程:
分析系統(tǒng)經(jīng)過的大致流程如下:
1、框架初始化
首先進行分析框架的初始化工作,主要是搜集待分析源碼工程中的所有用戶自定義類的信息,包括類名,類屬性,類方法名,類所在的文件路徑。
這些Record存放在全局上下文類Context中,該類使用單例模式進行設計,并且常駐內(nèi)存,便于后續(xù)的分析使用。
2、判斷Main File
其次判斷每個PHP文件是否是Main file。在PHP語言中,沒有所謂的main函數(shù),大部分Web中的PHP文件分為調(diào)用和定義兩種類型,定義類型的PHP文件是用來定義一些業(yè)務類、工具類、工具函數(shù)等,不提供給用戶進行訪問,而是提供給調(diào)用類型的PHP文件進行調(diào)用。而真正處理用戶請求的則是調(diào)用類型的PHP文件,比如全局index.php文件。靜態(tài)分析主要是針對處理用戶請求的調(diào)用類型的PHP文件,即Main File。判斷依據(jù)為:
在AST解析完成的基礎上,判斷一個PHP文件中的類定義、方法定義的代碼行數(shù)占該文件所有代碼行數(shù)是否超過一個范圍,如果是,則視為定義類型的PHP文件,否則為Main File,添加到待分析的文件名列表中。
3、AST抽象語法樹的構建
本項目基于PHP語言本身進行開發(fā),對于其AST的構建,我們參考目前比較優(yōu)秀的PHP AST構建的實現(xiàn)————PHP Parser。
該開源項目基于PHP語言本身進行開發(fā),可以對PHP的大多數(shù)結構如if、while、switch、數(shù)組聲明、方法調(diào)用、全局變量等語法結構進行解析??梢院芎玫耐瓿杀卷椖康木幾g前端處理的一部分工作。
4、CFG流圖構建
使用CFGGenerator類中的CFGBuilder方法。方法定義如下:
具體思路是采用遞歸構建CFG。首先輸入遍歷AST獲取的nodes集合,遍歷中對集合中的元素(node)進行類型判斷,如判斷是否是分支、跳轉、結束等語句,并按照node的類型進行CFG的構建。
這里對于分支語句、循環(huán)語句的跳轉條件(conditions)要存儲至CFG中的邊(Edge)上,方便數(shù)據(jù)流分析。
5、數(shù)據(jù)流信息的收集
對于一段代碼塊,最有效的并且值得收集的信息是賦值語句、函數(shù)調(diào)用、常量(const define)、注冊的變量(extract parse_str)。
賦值語句的作用就是為了后續(xù)進行變量跟蹤,在實現(xiàn)中,我使用了一種結構來表示賦值的value以及l(fā)ocation。而其他的數(shù)據(jù)信息是基于AST來判別和獲取的。比如函數(shù)調(diào)用中,判斷變量是否受到轉義、編碼等操作,或者調(diào)用的函數(shù)是否是sink(如mysql_query)。
6、變量凈化、編碼信息處理
$clearsql = addslashes($sql) ;
賦值語句,當右邊是過濾函數(shù)時(用戶自定義過濾函數(shù)或者內(nèi)置過濾函數(shù)),則調(diào)用函數(shù)的返回值被凈化,即$clearsql的凈化標簽加上addslashes。
發(fā)現(xiàn)函數(shù)調(diào)用,判斷函數(shù)名是否是配置文件中進行配置的安全函數(shù)。
如果是,則將凈化標簽添加至location的symbol中。
7、過程間分析
如果在審計中,發(fā)現(xiàn)用戶函數(shù)的調(diào)用,這時候必須要進行過程間的分析,在分析的工程中定位到具體方法的代碼塊,帶入變量進行分析。
難點在于,如何進行變量回溯、如何應對不同文件中的相同名稱的方法、如何支持類方法的調(diào)用分析、如何保存用戶自定義的sink(比如在myexec中調(diào)用exec函數(shù),如果沒有經(jīng)過有效的凈化,那么myexec也要視為危險函數(shù))、如何對用戶自定義的sink進行分類(如SQLI XSS XPATH等)。
處理流程如下:
8、污點分析
有了上面的過程,最后要進行的就是污點分析,主要針對系統(tǒng)中內(nèi)置的一些風險函數(shù),比如可能導致xss的echo。并且要對危險函數(shù)中的危險參數(shù)做有效的分析,這些分析包括判斷是否進行了有效的凈化(比如轉義、正則匹配等),以及制定算法來回溯前面該變量的賦值或者其他變換。這無疑對安全研究人員工程能力的一個考驗,也是自動化審計最重要的階段。
0×03
通過上面的介紹,你可以看到要實現(xiàn)一款自己的自動化審計工具所要趟的坑是很多的。我的嘗試中也是遇到了N多的困難,并且靜態(tài)分析確實帶有一定的局限性,比如動態(tài)分析中輕易可以獲得的字符串變換的過程,在靜態(tài)分析中就難以實現(xiàn),這不是技術上能夠突破的,而是靜態(tài)分析本身的局限性導致的,所以單純的靜態(tài)分析如果想要做到誤報和漏報很低,畢竟引入一些動態(tài)的思想,比如對eval中的代碼進行模擬,對字符串變化函數(shù)以及正則表達式進行處理等。還有就是對于一些基于MVC框架的,比如CI框架,代碼很分散,比如數(shù)據(jù)凈化的代碼放在input類的擴展中,像這種PHP應用,我認為很難做到一個通用的審計框架,應該要單獨對待。
以上只是粗略的把我當前的嘗試(目前沒有完全實現(xiàn))拿來share,畢竟大學狗不是專業(yè)人員,希望可以拋磚引玉,使得越來越多的安全研究人員關注這一領域。
聯(lián)系客服