Skip to content
This repository has been archived by the owner on Mar 19, 2024. It is now read-only.
/ MessyStack Public archive

Deployment stack for a vulnerable proxy server setup. (DubheCTF 2024 "authenticated mess & unauthenticated less" challenge)

License

Notifications You must be signed in to change notification settings

mix-archive/MessyStack

Repository files navigation

MessyStack

Deployment stack for a vulnerable proxy server setup. (DubheCTF 2024 "authenticated mess & unauthenticated less" challenge)

题面

给出一个 pcapng 文件,其中包含了一些网络流量。参赛者需要分析流量,来对题目中的代理服务器进行攻击。

题目描述

How can things go wrong when using a proxy server?

Hints
  1. 压缩包加密无需破解,请注意图片的出处和文件命名。
  2. 此题目后半部分更多偏向于 Web 方向。
  3. 流量解密后的唯一有效信息就是图片链接,之后的内容无需继续关注。
  4. 如果阅读流量相关的解密代码对你来说比较困难,不妨试试重放。

Writeup

分析流量

使用 Wireshark 来打开文件,我们可以看到有一个明文的 HTTP 请求:

GET /raw/sw2TFBLK HTTP/1.1
Host: pastebin.com
User-Agent: curl/8.5.0
Accept: */*

访问 https://pastebin.com/raw/sw2TFBLK 可以得到一个配置文件:

{
  "log": {
    "loglevel": "debug"
  },
  "inbounds": [
    {
      "port": 1080, // SOCKS 代理端口,在浏览器中需配置代理并指向这个端口
      "listen": "127.0.0.1",
      "protocol": "socks",
      "settings": {
        "udp": true
      }
    }
  ],
  "outbounds": [
    {
      "protocol": "vmess",
      "settings": {
        "vnext": [
          {
            "address": "1.95.11.7", // 服务器地址,请修改为你自己的服务器 ip 或域名
            "port": 40086, // 服务器端口
            "users": [
              {
                "id": "f3a5cae3-6bd2-40d1-b13b-2cc3d87af2c7",
                "security": "auto"
              }
            ]
          }
        ]
      }
    }
  ]
}

可以看到,这是一个 V2Ray 的配置文件。此时我们可以猜测,流量文件后半部分的内容可能是 VMess 协议的流量。

解密流量

这道题由于强网杯 2022 已经出现过对 VMessMD5 的解密手段,所以在出题时专门采用了更新的 VMessAEAD 的加密方式(也是现在版本的 v2ray-core 强制的加密方式)。

Important

VMessMD5 被弃用的原因是因为它能够被很容易地通过主动探测的手段检测到,见 v2ray-core#2523

解密流量有两种方法,一种是通过阅读代码来自己实现解密,另一种是通过重放流量来获取明文。

Note

关于协议的部分实现,可以参考 extra-VMessAEADdoc.zip 但是协议的最终实现还是需要参考 v2ray-core 的源码,因为有些地方的实现和文档中的描述不一致。

在这里我写了一个库专门用来解析 VMessAEAD 的流量。

import uuid

from vmess_aead.encoding import VMessBodyEncoder
from vmess_aead.headers.request import VMessAEADRequestPacketHeader
from vmess_aead.utils.reader import BytesReader

data = "a49502ee07ffdd20f11597e961f7768b41be7bc32030107fc81f235f72ff1b294d074ade94281242412b4c19123b15250ac3d5ad9524df9acd0ee5f6dcca7b0c2849b2f4df20190dd084c01c3f6e2834dd87cb8e97fa178b2ec454755f89d9b735ae6dab9c7989cf4154f7eae53774d9d6cdb55d0a76fdaf21e08bae26e49cbb3c56d11a3fe540454bfbae06305460301caca4109df3335b0c3646b6e2d856a927f9298b87da3a7cf3cffcca6c27259fc055faa9f3155cc95f698bb37436008783b6cd03d38a8e109f78a48c860b600fcbe825cd6c6a5be2c95fce121df574c70fe62e4f24e28de5983db6c3c0192d72ec785b6d58c4b8301c4f70eab683"
data = bytes.fromhex(data)

reader = BytesReader(data)
user_id = uuid.UUID("f3a5cae3-6bd2-40d1-b13b-2cc3d87af2c7")


header = VMessAEADRequestPacketHeader.from_packet(reader, user_id)
print(header)

encoder = VMessBodyEncoder(
    header.payload.body_key,
    header.payload.body_iv,
    header.payload.options,
    header.payload.security,
    header.payload.command,
)
body = encoder.decode_once(reader)
print(body)

在比赛中,重放流量应当是更加简单的方法。

Tip

因为 VMessAEAD 并没有类似于 VMessMD5 那样的请求头时间戳爆破机制,只有检查根据 UUID 最终解密后的结果中时间戳是否在合理范围内的机制。所以重放流量是行得通的,只需要 Patch 掉对时间范围的检查即可

流量解密后,我们能得到一个图片的链接:

玩BA玩的

图片解压

这张图片是一个压缩包和一张图片的合成图。我们可以使用 binwalk 来看到其中的文件:

$ binwalk __p0.png

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             PNG image, 2240 x 3272, 8-bit/color RGB, non-interlaced
62            0x3E            Zlib compressed data, default compression
1487451       0x16B25B        Zip archive data, encrypted compressed size: 28, name: .vscode/
1487528       0x16B2A8        Zip archive data, encrypted compressed size: 89, uncompressed size: 63, name: .vscode/settings.json
1487679       0x16B33F        Zip archive data, encrypted compressed size: 28, name: docker/
1487755       0x16B38B        Zip archive data, encrypted compressed size: 321, uncompressed size: 434, name: docker/Dockerfile
1488134       0x16B506        Zip archive data, encrypted compressed size: 284, uncompressed size: 513, name: docker/docker-compose.yml
1488484       0x16B664        Zip archive data, encrypted compressed size: 299, uncompressed size: 527, name: docker/v2ray-config.json
1488848       0x16B7D0        Zip archive data, encrypted compressed size: 28, name: src/
1488921       0x16B819        Zip archive data, encrypted compressed size: 9554, uncompressed size: 31864, name: src/index.js
1498528       0x16DDA0        Zip archive data, encrypted compressed size: 72, uncompressed size: 46, name: .dockerignore
1498654       0x16DE1E        Zip archive data, encrypted compressed size: 1009, uncompressed size: 2131, name: .gitignore
1499714       0x16E242        Zip archive data, encrypted compressed size: 80, uncompressed size: 63, name: .prettierrc
1499846       0x16E2C6        Zip archive data, encrypted compressed size: 261, uncompressed size: 337, name: healthcheck.js
1500162       0x16E402        Zip archive data, encrypted compressed size: 12134, uncompressed size: 35149, name: LICENSE
1512344       0x171398        Zip archive data, encrypted compressed size: 181, uncompressed size: 255, name: package.json
1512578       0x171482        Zip archive data, encrypted compressed size: 9647, uncompressed size: 26002, name: pnpm-lock.yaml
1522280       0x173A68        Zip archive data, encrypted compressed size: 107, uncompressed size: 81, name: README.md
1522437       0x173B05        Zip archive data, encrypted compressed size: 272, uncompressed size: 328, name: wrangler.toml
1523953       0x1740F1        End of Zip archive, footer length: 22

观察到图片文件命名为 __p0.png,我们可以联想到这张图片的原始文件名可能是 <某个数字id>_p0.png。通过以图搜图工具(例如 SauceNAO 或者 ASCII2D)搜索这张图片,我们可以找到原始图片的文件名为 116921220_p0

所以压缩包的密码可能是 116921220,解压缩得到题目的源码(即本仓库的内容)。

EdTunnel,Wrangler 和 SSRF

这部分开始就是 Web 的部分了。

观察 docker-compose.yml,我们可以看到一个名为 edtunnel 的服务。Flag 存在于 Worker 的env变量中。

EdTunnel 部分是来自 https://github.com/3Kmfi6HP/EDtunnel 的代码,只对 UUID 和默认路由进行了简单的修改。

可以看到,EdTunnel 是通过 Wrangler 本地的开发模式部署的,查看 Wrangler 的 GitHub,可以发现 CVE-2023-7080,这个漏洞描述了 Wrangler 的 Inspector 端口是对所有接口监听的,所以攻击者可以在临近网络上访问到 Inspector 端口从而实现 Worker 沙盒内的远程代码执行。

虽然题目版本的 Wrangler 已经修复了这个漏洞,但是由于这个代码的作用是使用 Cloudflare Worker 的 API 实现一个 VLESS over WebSocket 的代理,所以我们可以通过这个代理来 SSRF 到部署 EdTunnel 的容器,从而实现连接到 Inspector 的端口。

具体建立连接将 V8 Inspector 端口暴露到本地的配置文件可以参考 exp-config.json,使用 v2ray run -c exp-config.json -format jsonv5 命令来运行。(因为 V4 版本的 V2Ray 对传输层流量多层代理支持不佳)

将端口暴露到本地后,我们可以在 Chrome 的 DevTools 中直接连接到这个端口(左上会出现 Node.js 的标识)。在 DevTools 的 Memory Snapshot 中,我们可以打出 Heap Snapshot,然后在其中搜索关键字即可找到 Flag 变量。

图片

What a messy protocol & lessy debugger!

About

Deployment stack for a vulnerable proxy server setup. (DubheCTF 2024 "authenticated mess & unauthenticated less" challenge)

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published