淺談變形PHP webshell檢測
一、變形webshell
webshell比如eval($_POST[])大家都耳熟能詳,近幾年在常見的webshell基礎上衍生了很多變種,加大了檢測難度,下面先看幾個從網上摘取的樣本:
1、無ascii碼和數字的webshell
2、隱藏關鍵字
3、編碼 + 隱藏關鍵字
從目前已經公開的樣本來看,變形的php webshell都是采取了隱藏關鍵字(eval、system等)的方法來躲避查殺。有一位monyer同學寫過一篇webshell的檢測文章,他把webshell拆分為下面的結構,執行數據和數據傳遞,檢測思路是:以小括號為界限,匹配執行數據部分是否命中收集的樣本的關鍵字。這種思路很好,個人覺得有兩處不足:
1、需要人工維護收集新樣本。
2、誤報量不可預估。
再看這個結構,變形的webshell無非是隱藏了執行數據部分或者數據傳遞部分,不過無論怎么變形本質上還是去調用eval、調用system、exec等命令執行函數,殺毒軟件通過異常行為來檢測木馬病毒,比如開機自啟動,這種思想同樣也可以用在webshell的檢測中。獲取行為數據是第一步。
二、PHP HOOK
這里我們只需要一些敏感的行為數據,比如eval、system的調用。實現方法很簡單,hook這些php函數或語法結構,這里通過php擴展來實現hook。下面以eval和system來簡要概述下hook的方法。
Eval是一個語法結構,調用eval最終會調用php內核的zend_compile_string函數,hook eval的只需要重寫zend_complie_string函數即可,流程如下:
System是php的一個內部函數,php代碼是轉化為opcode(指令)來執行,函數調用的指令是ZEND_DO_FCALL,風雪之隅大牛在taint擴展(詳見參考二)就是通過重載ZEND_DO_FCALL的方法實現了。因為我們并不需要hook每個內部函數,所以這里介紹另外一種方法,流程如下:
上報的數據寫在一個日志文件中,包括文件名、調用函數名、代碼在文件的行數。日志結構和內容如下:
附件中有eval、system函數hook實現的demo,具體細節可以查看代碼。demo只在php-5.3.6上測試過,不兼容之處忘見諒。
三、檢測
變形webshell分為兩大類,下面依次說明一下檢測邏輯。
1、執行數據隱藏
一個正常的程序員如果使用eval、system是不會刻意的轉換隱藏的,如果發現某個函數執行了,代碼中卻找不到這個函數名,我們認為這是一個異常行為。以下面這個變形為例
比如黑客傳入參數nonalpha.php?_=system&__=whoami執行了一條命令,日志會記錄
我們在后端取nonalpha.php文件的第7行內容匹配system(字符串,如果沒找到,則認為是一個變形webshell。
2、數據傳遞隱藏
先看下面這個例子
這個webshell通過編碼的referer來傳遞攻擊載荷,利用日志文件記錄到的文件名和行數把代碼上報到后端,和后端svn中的代碼做對比,如果不一致,則認為是一個webshell。
四、不足
web承受著大量的訪問請求,增加的php擴展的性能和穩定性是一個嚴峻的考驗,另外在服務器比較多的公司還存在一個推廣和部署成本。