PHP代碼審計學習
這是一次分享準備。
自己還沒有總結這個的能力,這次就當個搬運工好了~~
0x01 工具準備
PHPSTORM,不只是編程。
個人覺得只要能夠提供全局搜索、單頁搜索、函數跳轉的編輯器就能夠滿足要求。一般在審計的時候,先找到一個入口點,配合代碼和瀏覽器,一邊下斷點,一邊打印變量,再在瀏覽器上觀察反應。
自動化審計工具,食之無味,棄之可惜。
當然,我手邊能用到的自動化審計工具就是能在網上找到資源的那幾種。對於快速定位漏洞點來審計,自動化工具是有一定作用的,但是,大多數我能接觸到的審計工具大抵是基於規則匹配的或者有一定的數據流向,但由於不能做到語義識別,很多邏輯控制語句無法識別,導致敏感點可可控參數無法自由的跳轉結合。
現在的習慣是,有了代碼,先會扔進審計工具裏跑一跑,看一個大概趨勢,如果時間充裕,一般還是願意一點一點從代碼入口點跟進。
0x02 審計初步
審計可以從多個角度切入,首先是搞清楚審計對象的架構,是套了開源的框架,還是原生代碼;是MVC,還是僅僅是函數調用。
那麽在審計之前,最好就是使用或者熟悉這些常見框架的特性機制。
CI
https://codeigniter.org.cn/
YII2http://www.yiichina.com/
ThinkPHPhttp://www.thinkphp.cn/
Laravelhttps://laravel.com/
熟悉這些框架方便我們快速判斷審計點。比如之前的一次代碼審計就是套了ThinkPHP的核心代碼,結果導致ThinkPHP的漏洞對於那套系統依然適用。
為了能夠邊學習邊實踐別人的思想,我這裏以MetInfo為例進行學習。
對於快速審計,比如自動化工具,往往可以考慮以下一些切入點。
敏感函數切入
敏感函數包括能夠代碼執行(PHP、MYSQL)的函數、上傳下載文件的函數、文件讀取的函數、加載資源的函數。
- eval()- 海洋CMS6.28
@eval(“if(“.$strIf.”){\$ifFlag=true;}else{\$ifFlag=false;}”);
- exec()-imo雲辦公
$result = exec($_POST[‘command’]);
- preg_replace()-Thinkphp2.1
preg_replace(‘/test/e’, ‘phpinfo()’, ‘just test’);
preg_replace(‘@(w+)’.$depr.’([^’.$depr.’\/]+)@e’, ‘$var[\’\1\’]=”\2”;’, implode($depr,$paths));
……
這一類的函數有很多,這種漏洞一般可能會呈現兩種趨勢,一種就是常用函數過濾繞過,一種是不常見函數用法失誤的。
漏洞點切入
如果說白盒找敏感函數的話,黑盒上對應的就是優先查找程序的SQL執行點、上傳點、登錄點、密碼找回點等
登錄頁面、表單接收頁面、信息顯示頁面
普通拼接,這種不多說了,主流開源的代碼想挖到這種已經很難了,要麽沒有拼接的用法,要麽就做了更加嚴格的過濾。
當然,這裏有些小技巧,比如多次過濾情況下的繞過。如\include\mail\class.phpmailer.php的1741行:
tip1:
$textMsg = trim(strip_tags(preg_replace(‘/<(head|title|style|script)[^>]*>.*?<\/\\1>/s‘,‘‘,$message)));
這裏連續用了兩個過濾函數,這兩個函數在一起容易造成繞過。
可以使用這兩個payload做對比:
<head>evil</head>
<he<>ad>evil</head>
編碼註入:
二次編碼註入,addslashes、mysql_real_escape_string、mysql_escape_string或者開啟GPC來轉義,但是,如果再次使用urlencode就會出現二次編碼。
- 文件包含
模塊加載,模板加載,cache調用
- 任意文件讀取
尋找文件讀取敏感函數
- 文件上傳
move_uploaded_file()
- 文件刪除
unlink()
- 變量覆蓋
extract()
parse_str()
$$
index切入
從軟件的index入口點開始,逐漸遍歷到所有函數文件。
0x03 審計實踐
這裏以Metinfo為例進行演示,先大致了解一下該款CMS的結構。
根目錄下入口index.php,前臺客戶邏輯在/member/裏,後臺邏輯在/admin/裏,自己創建的應用在/app/中,
前臺的下載/搜索/等邏輯對應在相應的目錄下。
常用的功能函數集中在/include/下,重點在*.inc.php和*.func.php中
/index.php
|
/include/common.inc.php
這個文件很有意思,比如裏面有名的變量覆蓋,由變量覆蓋處跳轉到過濾函數daddslashes(),明顯這裏有國瓷打補丁的痕跡,分享時現場細說,這裏就不贅述。
/include/common.inc.php
|
/include/head.php
|
/app/
|
/include/
MetInfo由於特殊的變量傳遞機制和路由機制,使得我們可以輕易訪問到任意PHP文件並且攜帶參數進行測試,所以對於它的審計順序會更加松散一點。
我這裏先從關聯性較弱的/about/,/upload/,/search/等幾個文件夾看起,最後再集中閱讀用戶應用的/app/文件夾。
利用前面說到的斷點輸出變量的方法一點一點調試實例,分享用。
(http://127.0.0.1/case/index.php?metid=1&filpy=&fmodule=0&modulefname=2)
到這裏都沒有什麽太大的發現,唯一的感受就是有很多點都很驚險,由於沒有用MVC框架,顯然很多SQL語句之間的寫法差異都比較大。
之後就可以跟進include的功能函數來看,也就是在這裏終於知道了一個小漏洞。
前臺大概看得差不多,就可以跟進後臺admin文件夾看看,這裏就會覺得輕松很多,一個後臺就不在適用過濾函數了,另一個後臺功能更多一點,不過後臺漏洞大多就只能算代碼BUG,沒有前臺來得那麽驚艷。
大多數的內容打算分享的時候直接口述,這裏其實只能算是一個大綱,所以文字上可能不是很通順。
PHP代碼審計學習