挑战设计:为 2022 年信息安全挑战赛打造 CalDAV 协议漏洞利用关卡
挑战设计背景
虽然我不常参加 CTF 比赛,但热衷于设计 CTF 挑战题目,因为这能迫使我通过实践学习。设计优秀的 CTF 挑战更像艺术而非科学。作为去年 3 万美元奖金"The InfoSecurity Challenge"(TISC)的获胜者,我决定今年贡献一个挑战题目。
设计原则
教育性
最好的 CTF 挑战应该具有教学价值。我的挑战围绕 CalDAV 协议设计,这是 WEBDAV(HTTP 的扩展协议)的研究较少的超集协议,从 iOS 默认日历到 IoT 设备都在使用。在 DEF CON 30 大会上,我展示过 iCalendar 文件格式的研究,但未公开其通信协议的相关发现。
真实性
尽管所有 CTF 挑战都存在人为设计成分,我尽量保持真实性:使用真实开源代码(Radicale 服务器),确保漏洞利用链逻辑合理,还原日常 Web 漏洞研究中的代码审计体验。
透明性
避免"通过 obscurity 增加难度"的黑盒模式,我构建了白盒挑战,所有相关代码都对参赛者可见。
挑战性
Web 类题目通常是最容易的 CTF 挑战类别。我试图打破这种认知:虽然提供源代码,但要求参赛者阅读 RFC 文档并构造特殊 payload。
最重要的是——这个挑战必须足够优雅:
🚫 禁止暴力破解
🚫 禁止盲目猜测
🎯 最终获得反向 shell
"几乎可利用"的漏洞
漏洞研究中最痛苦的时刻,就是发现某个潜在漏洞点因输入过滤、验证或数据转换而无法利用。Radicale(流行开源 CalDAV 服务器)中就存在这样的"准漏洞"。
Radicale 除了处理 iCalendar 文件外,还使用 Python 标准库 pickle 存储日历元数据。当调用pickle.load()
反序列化时,会执行 pickle 文件中类的__reduce__
方法——这是众所周知的代码执行向量。
Radicale 在三处调用了pickle.load()
,其中一处位于storage/multifilesystem/sync.py
:
触发路径需要满足:
发送 REPORT 请求,XML 正文包含
D:sync-collection
根元素和D:sync-token
子元素sync-token 值格式必须为:
http://radicale.org/ns/sync/<64位小写hex字符串>
pickle 文件必须存在于:
<根目录>/<用户名>/<日历名>/.Radicale.cache/sync-token/<合法token名>
但 Radicale 的路径消毒函数is_safe_filesystem_path_component()
会检查路径段是否以点开头,阻止写入.Radicale.cache
目录。
构造利用链
作为 CTF 挑战,我通过以下设计使"准漏洞"变得可利用:
用 Go 编写"开发版"CalDAV 服务器,共享 Radicale 的根目录
保留授权检查但移除
.
开头的路径限制利用 WebDAV 的 MOVE/COPY 方法(通过 Destination 头指定目标路径)绕过路径段限制
完整攻击仅需 4 个 HTTP 请求:
意外挑战与解决方案
测试中发现三个意外问题:
其他 pickle.load()调用点:通过 nginx 反向代理禁用 GET 等方法,强制使用 REPORT 方法触发目标路径
环境隔离问题:使用 radicale 受限用户和定时清理脚本防止解题干扰
解题时间预估偏差:原预计 6 小时,实际平均耗时 7 天,最终通过三条渐进式提示引导参赛者:
"将其视为代码审计挑战,已提供反向代理配置"
"研究 RFC 中的 PROPFIND 方法,关注其他 HTTP 方法"
"两个服务器共存的原因?尝试利用一个服务器攻破另一个"
经验总结
这次挑战设计揭示了:
难度评估的复杂性
在"透明性"和"挑战性"之间需要权衡
充分的测试环节至关重要
最终目标不仅是比赛——希望参赛者能深入理解这个广泛使用但陈旧的协议标准,并掌握代码审计的核心方法论。祝贺所有获胜者!更多精彩内容 请关注我的个人公众号 公众号(办公 AI 智能小助手)公众号二维码

评论