CTF出题手记构建Easy Notes的Session反序列化陷阱在2019年HarekazeCTF赛事中我设计了一道名为Easy Notes的Web题目这道题后来被收录进BUUCTF题库。与其他CTF题目不同这道题的核心漏洞点是PHP Session反序列化但解题路径需要选手串联多个看似无害的功能点。今天我想从出题人视角分享这道题的设计思路和背后的安全考量。1. 场景设定与核心机制设计任何好的CTF题目都需要一个合理的应用场景作为载体。我选择了一个极简的笔记系统包含三个核心功能用户登录基础身份验证添加笔记允许用户创建文本内容导出笔记将笔记保存为文件关键设计点在于完全避免使用数据库。整个应用仅通过Session来维持用户状态而笔记内容则直接以文件形式存储在服务器上。这种设计看似简化了系统架构实则埋下了第一个伏笔——Session与用户文件共享同一存储路径。flag.php的实现非常简单?php function is_admin() { return isset($_SESSION[admin]) $_SESSION[admin] true; } if (is_admin()) { echo getenv(FLAG); } ?2. 路径重合与文件名限制的陷阱服务器配置将Session文件存储在/var/www/tmp目录这也是用户笔记的保存位置。这个设计产生了两个关键特性路径重合Session文件和用户笔记文件物理上位于同一目录命名规则笔记文件名必须满足Session文件命名规范具体验证逻辑如下$filename sess_ . preg_replace(/[^a-zA-Z0-9-]/, , $_SESSION[user]); if (isset($_POST[title]) isset($_POST[body])) { file_put_contents(/var/www/tmp/$filename, serialize([ title $_POST[title], body $_POST[body] ])); }这里设置了几个关键限制文件名必须以sess_开头只能包含字母、数字和连字符用户输入中的..会被替换为空防御目录穿越3. PHP Session引擎的特性利用默认PHP配置使用php序列化处理器这个引擎有个鲜为人知的特性它使用|作为键值分隔符。这意味着我们可以构造特殊的输入来污染Session数据。考虑以下攻击链注册用户名为sess_的账户添加笔记时在title字段注入序列化数据|N;admin|b:1;完整Session文件内容将变为title|s:12:|N;admin|b:1;;body|s:5:hello;当PHP解析这个文件时会错误地将admin识别为Session变量4. 文件导出功能的精妙设计导出功能看似无害实则暗藏玄机$type str_replace(.., , $_GET[type]); header(Content-Disposition: attachment; filename . $filename . $type . );当传入type.时首先.不会被str_replace过滤最终文件名变为sess_xxx.其中xxx是随机部分但Linux文件系统会忽略末尾的点实际访问的还是sess_xxx5. 完整攻击链的构建逻辑要让选手发现这个漏洞链我设计了几个引导点信息泄露导出功能会返回完整的文件名路径提示错误信息中会显示/var/www/tmp路径命名限制注册时的用户名限制暗示了Session命名规则预期解题步骤发现导出功能存在文件名拼接通过特殊输入获取Session文件名利用笔记功能污染Session数据伪造PHPSESSID获取管理员权限6. 防御视角的思考这道题展示了几个重要的安全原则最小权限原则Session文件不应与用户上传文件混存输入过滤简单的字符替换往往不够彻底上下文感知序列化处理需要完整上下文验证在真实环境中防御措施应当包括// 安全的Session配置 ini_set(session.serialize_handler, php_serialize); ini_set(session.upload_progress.cleanup, On); ini_set(session.save_path, /var/lib/php/sessions);7. 出题过程中的调试技巧设计这类题目时我常用的调试方法包括日志记录在关键位置添加日志输出差分测试对比正常和攻击请求的服务器状态变化沙盒验证在隔离环境中完整重现攻击链例如可以使用这个命令实时监控Session目录watch -n 0.5 ls -al /var/www/tmp cat /var/www/tmp/sess_*从出题人角度看好的CTF题目应该像侦探小说一样每个线索都精心布置最终引导选手发现真相。这道Easy Notes题目通过多个看似无害的功能点组合创造出了一个有趣的Session反序列化挑战。
CTF出题人视角:我是如何设计‘Easy Notes’这道Session反序列化题的
CTF出题手记构建Easy Notes的Session反序列化陷阱在2019年HarekazeCTF赛事中我设计了一道名为Easy Notes的Web题目这道题后来被收录进BUUCTF题库。与其他CTF题目不同这道题的核心漏洞点是PHP Session反序列化但解题路径需要选手串联多个看似无害的功能点。今天我想从出题人视角分享这道题的设计思路和背后的安全考量。1. 场景设定与核心机制设计任何好的CTF题目都需要一个合理的应用场景作为载体。我选择了一个极简的笔记系统包含三个核心功能用户登录基础身份验证添加笔记允许用户创建文本内容导出笔记将笔记保存为文件关键设计点在于完全避免使用数据库。整个应用仅通过Session来维持用户状态而笔记内容则直接以文件形式存储在服务器上。这种设计看似简化了系统架构实则埋下了第一个伏笔——Session与用户文件共享同一存储路径。flag.php的实现非常简单?php function is_admin() { return isset($_SESSION[admin]) $_SESSION[admin] true; } if (is_admin()) { echo getenv(FLAG); } ?2. 路径重合与文件名限制的陷阱服务器配置将Session文件存储在/var/www/tmp目录这也是用户笔记的保存位置。这个设计产生了两个关键特性路径重合Session文件和用户笔记文件物理上位于同一目录命名规则笔记文件名必须满足Session文件命名规范具体验证逻辑如下$filename sess_ . preg_replace(/[^a-zA-Z0-9-]/, , $_SESSION[user]); if (isset($_POST[title]) isset($_POST[body])) { file_put_contents(/var/www/tmp/$filename, serialize([ title $_POST[title], body $_POST[body] ])); }这里设置了几个关键限制文件名必须以sess_开头只能包含字母、数字和连字符用户输入中的..会被替换为空防御目录穿越3. PHP Session引擎的特性利用默认PHP配置使用php序列化处理器这个引擎有个鲜为人知的特性它使用|作为键值分隔符。这意味着我们可以构造特殊的输入来污染Session数据。考虑以下攻击链注册用户名为sess_的账户添加笔记时在title字段注入序列化数据|N;admin|b:1;完整Session文件内容将变为title|s:12:|N;admin|b:1;;body|s:5:hello;当PHP解析这个文件时会错误地将admin识别为Session变量4. 文件导出功能的精妙设计导出功能看似无害实则暗藏玄机$type str_replace(.., , $_GET[type]); header(Content-Disposition: attachment; filename . $filename . $type . );当传入type.时首先.不会被str_replace过滤最终文件名变为sess_xxx.其中xxx是随机部分但Linux文件系统会忽略末尾的点实际访问的还是sess_xxx5. 完整攻击链的构建逻辑要让选手发现这个漏洞链我设计了几个引导点信息泄露导出功能会返回完整的文件名路径提示错误信息中会显示/var/www/tmp路径命名限制注册时的用户名限制暗示了Session命名规则预期解题步骤发现导出功能存在文件名拼接通过特殊输入获取Session文件名利用笔记功能污染Session数据伪造PHPSESSID获取管理员权限6. 防御视角的思考这道题展示了几个重要的安全原则最小权限原则Session文件不应与用户上传文件混存输入过滤简单的字符替换往往不够彻底上下文感知序列化处理需要完整上下文验证在真实环境中防御措施应当包括// 安全的Session配置 ini_set(session.serialize_handler, php_serialize); ini_set(session.upload_progress.cleanup, On); ini_set(session.save_path, /var/lib/php/sessions);7. 出题过程中的调试技巧设计这类题目时我常用的调试方法包括日志记录在关键位置添加日志输出差分测试对比正常和攻击请求的服务器状态变化沙盒验证在隔离环境中完整重现攻击链例如可以使用这个命令实时监控Session目录watch -n 0.5 ls -al /var/www/tmp cat /var/www/tmp/sess_*从出题人角度看好的CTF题目应该像侦探小说一样每个线索都精心布置最终引导选手发现真相。这道Easy Notes题目通过多个看似无害的功能点组合创造出了一个有趣的Session反序列化挑战。