PHP自動化白盒審計技術與實現

2021-09-11 11:21:28 字數 3808 閱讀 2318

路人甲 · 2015/05/29 11:07

國內公開的php自動化審計技術資料較少,相比之下,國外已經出現了比較優秀的自動化審計實現,比如rips是基於token流為基礎進行一系列的**分析。傳統靜態分析技術如資料流分析、汙染傳播分析應用於php這種動態指令碼語言分析相對較少,但是卻是實現白盒自動化技術中比較關鍵的技術點。今天筆者主要介紹一下最近的研究與實現成果,在此拋磚引玉,希望國內更多的安全研究人員將精力投入至php自動化審計技術這一有意義的領域中。

自動化審計的實現方式有多種,比如直接使用正規表示式規則庫進行定位匹配,這種方法最簡單,但是準確率是最低的。最可靠的思路是結合靜態分析技術領域中的知識進行設計,一般靜態分析安全工具的流程大多是下圖的形式:

靜態分析工作所要做的第一件事情就是將原始碼進行建模,通俗一點講,就是將字串的原始碼轉為方便於我們後續漏洞分析的中間表示形式,即一組代表此**的資料結構。建模工作中一般會採用編譯技術領域中的方法,如詞法分析生成token,生成抽象語法樹,生成控制流程圖等。建模工作的優劣,直接影響到後續汙染傳播分析和資料流分析的效果。

執行分析就是結合安全知識,對載入的**進行漏洞分析和處理。最後,靜態分析工具要生成判斷結果,從而結束這一階段的工作。

經過一段時間的努力,筆者和小夥伴也大致實現了一款針對自動化的靜態分析工具。具體實現思路正是採用了靜態分析技術,如果想深入了解實現思路,可以閱讀之前發過的文章。 在工具中,自動化審計流程如下:

如果上一步是漏洞**,則轉入漏洞報告模組進行漏洞**段的收集。其實現的基礎是在系統環境中維護乙個單例模式的結果集上下文物件,如果生成一條漏洞記錄,則加入至結果集中。當整個掃瞄工程結果之後,使用smarty將結果集輸出到前端,前端做掃瞄結果的視覺化。

在真實的php審計中,遇到敏感函式的呼叫,比如mysql_query,我們就會不由自主地去手動分析第乙個引數,看是否可控。事實上,很多cms都會將一些資料庫查詢的方法進行封裝,使得呼叫方便且程式邏輯清晰,比如封裝為乙個類mysqldb。這時,在審計中我們就不會搜尋mysql_query關鍵字了,而是去找比如db->getone這種類的呼叫。

那麼問題來了,在自動化程式進行分析的時候,如何獲知db->getone函式是個資料庫的訪問類方法呢?

這就需要在自動化分析的初期就要對整個工程的所有類與定義的方法進行蒐集,以便於程式在分析的時候尋找需要跟進的方法體。

對於類資訊和方法資訊的蒐集,應該作為框架初始化的一部分完成,儲存在單例上下文中:

同時,需要識別分析的php檔案是否是真正處理使用者請求的檔案,因為有些cms中,一般會將封裝好的類寫入單獨的檔案中,比如將資料庫操作類或者檔案操作類封裝到檔案中。對於這些檔案,進行汙染傳播分析是沒有意義的,所以在框架初始化的時候需要進行識別,原理很簡單,分析呼叫型別語句和定義型別語句的比例,根據閾值進行判別,錯誤率很小。

最後,對每個檔案進行摘要操作,這一步的目的是為了後續分析時碰到require,include等語句時進行檔案間分析使用。主要收集變數的賦值、變數的編碼、變數的淨化資訊。

常見的web漏洞,一般都是由於危險引數使用者可控導致的,這種漏洞稱之為汙點型別漏洞,比如常見的sqli,xss等。 php內建的一些函式本身是危險的,比如echo可能會造成反射型xss。然而真實**中,沒人會直接呼叫一些內建的功能函式,而是進行再次封裝,作為自定義的函式,比如:

#!php

function myexec($cmd)

複製**

在實現中,我們的處理流程是:

總結為一句話,我們就是跟入到相應的類方法、靜態方法、函式中,從這些**段中查詢是否有危險函式和危險引數的呼叫,這些php內建的危險函式和引數位置都是放在配置檔案中的進行配置完成的,如果這些函式和引數一旦被發現,且判斷危險引數並沒有被過濾,則將該使用者自定義函式作為使用者自定義危險函式。一旦後續的分析中發現呼叫這些函式,則立即啟動汙點分析。

在真實的審計過程中,一旦發現危險引數是可控的,我們就會迫不及待地去尋找看程式設計師有沒有對該變數進行有效的過濾或者編碼,由此判斷是否存在漏洞。 自動化審計中,也是遵循這個思路。在實現中,首先要對每乙個php中的安全函式進行統計和配置,在程式分析時,對每一條資料流資訊,都應該進行回溯收集必要的淨化和編碼資訊,比如:

#!php

$a = $_get['a'] ;

$a = intval($a) ;

echo $a ;

$a = htmlspecialchars($a) ;

mysql_query($a) ;

複製**

上面的**片段看起來有些怪異,但只是作為演示使用。從**片段可以看出,變數a經過了intval和htmlspecialchars兩個淨化處理,根據配置檔案,我們順利的收集到了這些資訊。這時,要進行一次回溯,目的是將當前**行向上的淨化和編碼資訊進行歸併。 比如在第三行時,變數a的淨化資訊只有一條intval,但是第五行時,要求將變數a的淨化資訊歸併,收集為乙個list集合intval和htmlspecialchars,方法就是收集到前驅**中的所有資料流的資訊,並進行回溯。

細節部分是,當使用者同時對同乙個變數呼叫了如base64_encode和base64_decode兩個函式,那麼這個變數的base64編碼會被消除。同樣,如果同時進行轉義和反轉義也要進行消除。但是如果呼叫順序不對或者只進行了decode,那麼***,相當危險。

為了尋找出所有的危險sink點的引數(tracesymbol),將向前回溯與當前block相連的所有的基本塊,具體過程如下:

當tracesymbol對映到了乙個靜態字串、數字等型別的靜態物件或者當前的基本塊沒有入口邊時,演算法就停止。如果tracesymbol是變數或者陣列,就要檢查是否在超全域性陣列中。

汙點分析在過程間分析處理內建和使用者定義函式過程中開始,如果程式分析時遇到了敏感的函式呼叫,則使用回溯或者從上下文中獲取到危險引數節點,並開始進行汙點分析。通俗講,就是進行危險引數是否可能導致漏洞的判別。汙點分析工作在**taintanalyser中進行實現,獲取到危險引數後,具體步驟如下:

我們對******-log_v1.3.12進行了測試性掃瞄,結果是:

total : 76 xss : 3 sqli : 62 include : 5 file : 3 fileaffect : 1

複製**

測試**都是一些比較明顯的漏洞,且沒有使用mvc框架,什麼字元截斷吃掉轉義符這種,目前的技術還真的支援不了,不過也是可以掃出一些了。從測試過程來看,bug層出不窮,主要是前期實現時,很多語法結構與測試用例沒有考慮進去,加上演算法幾乎都是遞迴的,所以很容易就造成無限遞迴導致apache跪掉。

所以目前的**真的只能算是試驗品,**的健壯性需要無數次重構和大量的測試來實現,筆者已經沒有太多時間維護。

靜態分析領域中,很多安全研究人員都是做c/c++/反編譯彙編等方向,目前指令碼語言領域也急需技術力量投入進去,因為這是一件很有意義的事情。

回到坑上面來,筆者和小夥伴們的實現中,有個重大的問題就是不支援mvc框架。這些mvc如ci框架,資料流很難進行統一捕捉,因為框架封裝度很高。所以針對不同的框架估計需要不同的分析方式。

目前的狀況是,可以識別一些簡單的漏洞,**不夠健壯存在諸多bug。

最後,talk is cheap, show me the code. 實現**在github上可以找到。

**分享出來的目的是供有志於或者已經投身於該領域的安全研究人員進行研究與討論,目前還達不到隨便拿出乙個cms就能跑的效果,望大家不要有所幻想。

PHP自動化白盒審計技術與實現

國內公開的php自動化審計技術資料較少,相比之下,國外已經出現了比較優秀的自動化審計實現,比如rips是基於token流為基礎進行一系列的 分析。傳統靜態分析技術如資料流分析 汙染傳播分析應用於php這種動態指令碼語言分析相對較少,但是卻是實現白盒自動化技術中比較關鍵的技術點。今天筆者主要介紹一下最...

php實現自動化執行環境檢測

正確的處理方式應該是在不同的環境下讀取該環境特有的標識從而讀取不同的配置,而php.ini檔案就是乙個很好的選擇,在各個開發環境server中的php.ini內配置不同的runmode值來區分執行環境。在.ini中 的配置方式舉例如下 runmode projecta.runmode test 以上...

Atitit 自動化gui 與 發帖機 技術

atitit 自動化 gui 與 發帖機 技術 1.1.gui tech 11.2.自動化軟體測試 11.3.selenium attilax 11.4.圖形指令碼語言 sikuli 11.5.dom1 1.6.jsbridge 11.7.browser tech 1atitit.木馬病毒的免殺原理...