中国菜刀等工具管理WebShell的时候会有一些固定的特征,容易被waf或者IPS检测到,最近1年出来了个动态加密的WebShell管理工具,给检测带来了一定的困难,所以写个文章简单解剖一下
注:本文只针对当前的最新版冰蝎(Behinder) v2.0.1,以php webshell为例,其他webshell只是有细微的差别,有兴趣可以自行研究
实验环境
客户端: windows 7 + 冰蝎(Behinder) v2.0.1
服务端:ubuntu 16.04 + apache + php
webshell文件分析
以php为例
1 | <?php |
其实就两个功能
1、首先存在pass参数的情况(其实这个就是通常所说的一句话木马),就是通过截取随机数的md5的高16位作为密钥,保存在服务器的全局 $_SESSION
变量中,同时打印出来,这样客户端接收到就可以用这个密钥进行通信了
2、假如不带参数,就是加密通信的过程。假如php不存在openssl这个extension,就是用base64解码后,使用key进行循环异或解密。而存在openssl就使用AES128进行解密
基于上面分析可以得到通信流程
下面我们看看实际通信流量
数据包分析
通过在服务器上传webshell,客户端连接后通过wireshark抓取数据包
可以看到请求了两次密钥才开始真正的POST通信
接下来的通信,就是AES128加密后的base64密文
所以我们检测只能从请求密钥阶段入手了
通过获取密钥的数据包,我们发现以下特征
1、使用GET方法
2、参数名即木马的密码(这个可以修改,不能作为特征),但是参数值为纯数字可以作为特征,暂时来看应该1到5位数字可以匹配到了,保险一点可以1-8都可以
3、请求中有HEADER字段:Content-type: application/x-www-form-urlencoded
4、响应中会有Content-Length: 16
5、当然响应的body肯定也是16长度,而且字符是16进制的字符,即[0-9a-f]
通信过程实际发送的payload
通过在webshell中加入如下代码,即可获得解密后的payload
获得的如下:(由于base64_decode后面的比较长所以省略了)
1 | assert|eval(base64_decode('QGVycm9yX3JlcG9ydGluZygwKTsNCg0KZnVuY..............................')); |
所以它就是将字符串base64解密之后通过eval执行
解码上面的base64串得到下面真正的代码(下面是以命令执行为例的代码)
1 | @error_reporting(0); |
可以看到考虑了编码问题,还有一些执行命令的函数被禁用的问题
最后输出结构也是AES128加密的
工具每次只需倒数第二行的$cmd即可更换要执行的命令
总结
攻防是不断对抗升级的,冰蝎虽然通信过程加密,但是请求密钥阶段有很多特征,假如将请求密钥阶段特征抹掉,那么我们防御端会更加难以检查。