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

來源:互聯網
上載者:User
PHP自動化白盒審計技術與實現

0x00前言

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

0x01 基礎知識

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

靜態分析工作所要做的第一件事情就是將源碼進行建模,通俗一點講,就是將字串的源碼轉為方便於我們後續漏洞分析的中間表示形式,即一組代表此代碼的資料結構。建模工作中一般會採用編譯技術領域中的方法,如詞法分析產生token,產生抽象文法樹,產生控制流程程圖等。建模工作的優劣,直接影響到後續汙染傳播分析和資料流分析的效果。
執行分析就是結合安全知識,對載入的代碼進行漏洞分析和處理。最後,靜態分析工具要產生判斷結果,從而結束這一階段的工作。

0x02 實現思路

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

  • 首先載入使用者輸入的待掃描的工程目錄中所有的PHP檔案,並對這些PHP檔案做判別,如果掃描的PHP檔案是Main file,即真正處理使用者請求的PHP檔案,那麼對這種類型的檔案進行漏洞分析。如果不是Main file類型,比如PHP工程中的類定義,工具函數定義檔案,則跳過不做分析。
  • 其次進行全域資料的搜集,重點搜集的資訊有待掃描的工程中類資訊的定義,如類所在的檔案路徑、類中的屬性、類中的方法以及參數等資訊。同時對每個檔案組建檔案摘要,檔案摘要中重點搜集各個指派陳述式的資訊,以及指派陳述式中相關變數的淨化資訊和編碼資訊。
  • 全域初始化之後,進行編譯前端模組的相關工作,使用開源工具PHP-Parser對待分析的PHP代碼進行抽象文法樹(AST)的構建。在AST的基礎上,使用CFG構建演算法構建控制流程圖,並即時地產生基本塊的摘要資訊。
  • 編譯前端的工作中,如果發現敏感函數的調用,就停下來進行汙染傳播分析,進行過程間分析、過程內分析,找到對應的汙點資料。然後基於資料流分析過程中搜集的資訊,進行淨化資訊和編碼資訊的判斷,從而判斷是否為漏洞代碼。
    如果上一步是漏洞代碼,則轉入漏洞報告模組進行漏洞程式碼片段的收集。其實現的基礎是在系統內容中維護一個單例模式的結果集內容物件,如果產生一條漏洞記錄,則加入至結果集中。當整個掃描工程結果之後,使用Smarty將結果集輸出到前端,前端做掃描結果的可視化。

0x03 初始化工作

在真實的PHP審計中,遇到敏感函數的調用,比如mysql_query,我們就會不由自主地去手動分析第一個參數,看是否可控。事實上,很多CMS都會將一些資料庫查詢的方法進行封裝,使得調用方便且程式邏輯清晰,比如封裝為一個類MysqlDB。這時,在審計中我們就不會搜尋mysql_query關鍵字了,而是去找比如db->getOne這種類的調用。
那麼問題來了,在自動化程式進行分析的時候,如何獲知db->getOne函數是個資料庫的訪問類方法呢?
這就需要在自動化分析的初期就要對整個工程的所有類與定義的方法進行搜集,以便於程式在分析的時候尋找需要跟進的方法體。
對於類資訊和方法資訊的搜集,應該作為架構初始化的一部分完成,儲存在單例上下文中:

同時,需要識別分析的PHP檔案是否是真正處理使用者請求的檔案,因為有些CMS中,一般會將封裝好的類寫入單獨的檔案中,比如將資料庫操作類或者檔案操作類封裝到檔案中。對於這些檔案,進行汙染傳播分析是沒有意義的,所以在架構初始化的時候需要進行識別,原理很簡單,分析調用類型語句和定義類型語句的比例,根據閾值進行判別,錯誤率很小。
最後,對每個檔案進行摘要操作,這一步的目的是為了後續分析時碰到require,include等語句時進行檔案間分析使用。主要收集變數的賦值、變數的編碼、變數的淨化資訊。

0x04 使用者函數處理

常見的web漏洞,一般都是由於危險參數使用者可控導致的,這種漏洞稱之為汙點類型漏洞,比如常見的SQLI,XSS等。
PHP內建的一些函數本身是危險的,比如echo可能會造成反射型XSS。然而真實代碼中,沒人會直接調用一些內建的功能函數,而是進行再次封裝,作為自訂的函數,比如:

function myexec($cmd){    exec($cmd) ;}

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

  • 利用初始化中擷取的上下文資訊,定位到相應的方法程式碼片段
  • 分析這個程式碼片段,尋找到危險函數(這裡是exec)
  • 定位危險函數中的危險參數(這裡是cmd)
  • 如果在分析期間沒有遇到淨化資訊,說明該參數可以進行傳染,則映射到使用者函數myexec的第一個參數cmd,並將這個使用者自訂函數當做危險函數存放至上下文結構中
  • 遞迴返回,啟動汙點分析過程

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

0x05 處理變數的淨化和編碼

在真實的審計過程中,一旦發現危險參數是可控的,我們就會迫不及待地去尋找看程式員有沒有對該變數進行有效過濾或者編碼,由此判斷是否存在漏洞。
自動化審計中,也是遵循這個思路。在實現中,首先要對每一個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,那麼你懂的,相當危險。

0x06 變數回溯和汙點分析

1、變數回溯

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

  • 迴圈當前基本塊的所有入口邊,尋找沒有經過淨化的traceSymbol並且尋找基本塊DataFlow屬性中,traceSymbol的名字。
  • 如果一旦找到,那麼就替換成映射的symbol,並且將該符號的所有淨化資訊和編碼資訊都複製過來。然後,追蹤會在所有的入口邊上進行。
  • 最後,CFG上不同路徑上的結果會返回。

當traceSymbol映射到了一個靜態字串、數字等類型的靜態對象或者當前的基本塊沒有入口邊時,演算法就停止。如果traceSymbol是變數或者數組,就要檢查是否在超全域數組中。

2、汙點分析

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

  • 首先,在當前基本塊中尋找危險參數的賦值情況,尋找DataFlow的右邊節點中是否存在使用者輸入source,比如GET_POST等超全域數組。並使用不同類型漏洞判別的外掛程式類判斷這些節點是否是安全的。
  • 如果當前基本塊中沒有尋找到source,則進入本檔案多基本塊間分析過程。首先擷取當前基本塊的所有前驅基本塊,其中前驅基本塊中包含平行結構(if-else if-else),或者非平行結構(普通語句)。並進行危險變數分析,如果當前迴圈的基本塊中沒有前驅節點,則分析演算法結束。
  • 如果基本塊間分析沒有找到漏洞,則進行最後的檔案間分析。載入當前基本塊之前的包含檔案摘要,遍曆這些檔案摘要做出判斷。
  • 如果上述步驟中,出現漏洞,則進入漏洞報告模組。否則,系統繼續往下進行程式碼分析。

0x07 目前的效果


我們對simple-log_v1.3.12進行了測試性掃描,結果是:
Total : 76 XSS : 3 SQLI : 62 INCLUDE : 5 FILE : 3 FILEAFFECT : 1
測試代碼都是一些比較明顯的漏洞,且沒有使用MVC架構,什麼字元截斷吃掉轉義符這種,目前的技術還真的支援不了,不過也是可以掃出一些了。從測試過程來看,bug層出不窮,主要是前期實現時,很多文法結構與測試案例沒有考慮進去,加上演算法幾乎都是遞迴的,所以很容易就造成無限遞迴導致Apache跪掉。
所以目前的代碼真的只能算是實驗品,代碼的健壯性需要無數次重構和大量的測試來實現,筆者已經沒有太多時間維護。

0x08 總結

靜態分析領域中,很多安全研究人員都是做C/C++/反編譯彙編等方向,目前指令碼語言領域也急需技術力量投入進去,因為這是一件很有意義的事情。
回到坑上面來,筆者和小夥伴們的實現中,有個重大的問題就是不支援MVC架構。這些MVC如CI架構,資料流很難進行統一捕捉,因為架構封裝度很高。所以針對不同的架構估計需要不同的分析方式。
目前的狀況是,可以識別一些簡單的漏洞,代碼不夠健壯存在諸多bug。
最後,talk is cheap, show me the code. 實現代碼在github上可以找到。
代碼分享出來的目的是供有志於或者已經投身於該領域的安全研究人員進行研究與討論,目前還達不到隨便拿出一個CMS就能跑的效果,望大家不要有所幻想。

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.