新手也能看懂的PHP文件包含漏洞实战:手把手带你复现BUUCTF‘Had a bad day’
从零攻破PHP文件包含漏洞BUUCTF实战手记第一次接触CTF时看到文件包含漏洞这个术语就头皮发麻——直到我亲手用伪协议读到第一个flag。那次心跳加速的体验让我决定用最直白的方式记录这个经典漏洞的完整利用过程。今天我们就以BUUCTF平台上的Had a bad day为例用开发者熟悉的语言拆解每个技术细节。1. 环境观察与参数发现打开靶场首先看到的是个温馨的宠物图片站页面上两个按钮分别显示猫狗图片。这种看似无害的界面往往藏着最有趣的漏洞线索。关键操作步骤点击Woofers按钮观察地址栏变为index.php?categorywoofers点击Meowers按钮地址变为index.php?categorymeowers手动修改category参数为任意值如test页面返回错误Sorry, we currently only support woofers and meowers.此时我们已经确认网站通过GET参数category动态加载内容参数值存在某种过滤机制常规文件包含测试如../../etc/passwd被拦截2. 代码审计与过滤逻辑分析通过伪协议读取index.php源码是突破的关键。这里有个易错点直接尝试php://filter/convert.base64-encode/resourceindex.php会失败因为后端会自动添加.php后缀。正确操作流程# 第一次尝试错误 /index.php?categoryphp://filter/convert.base64-encode/resourceindex.php # 观察报错信息 include(php://filter/convert.base64-encode/resourceindex.php.php) # 修正尝试正确 /index.php?categoryphp://filter/convert.base64-encode/resourceindex解码后的源码揭示过滤逻辑$file $_GET[category]; if(isset($file)) { if( strpos( $file, woofers ) ! false || strpos( $file, meowers ) ! false || strpos( $file, index)){ include ($file . .php); } else{ echo Sorry, we currently only support woofers and meowers.; } }strpos函数要点返回子字符串首次出现位置从0开始计数未找到时返回false使用! false判断是安全写法避免0被误判为false3. 绕过策略设计与实战过滤规则要求参数必须包含woofers、meowers或index之一。我们有两种主流绕过方案方案A路径穿越法/index.php?categoryphp://filter/convert.base64-encode/resourceindex/../flag方案B伪协议嵌套法/index.php?categoryphp://filter/convert.base64-encode/index/resourceflag为什么这两种方式能生效路径中的index满足strpos检查伪协议中的index同样会被识别最终解析时会忽略这些中间路径直接定位到flag文件4. 进阶利用与防御思考成功获取flag后我们可以进一步分析漏洞成因。这个案例展示了几个典型问题漏洞根源未限制包含文件的路径范围过滤规则可被轻易绕过开启allow_url_include配置伪协议依赖此配置防御方案对比防护措施实现方式防护效果白名单校验只允许包含指定目录文件★★★★★后缀强制校验必须匹配.php后缀★★☆☆☆关键字过滤拦截../等特殊字符★★★☆☆关闭远程包含allow_url_includeOff★★★★☆实际开发中建议组合使用多种防护措施特别是白名单目录限制的组合5. 漏洞利用的创造性思维这个简单的CTF题目教会我们几个重要原则报错信息即线索自动补全.php后缀的提示就藏在报错中协议即武器php://filter不仅能读文件还能用于XSS等攻击路径即突破口../这种简单的穿越符号仍是现代系统的软肋在最近的一次渗透测试中我就遇到类似场景某CMS的插件系统通过?loadplugin_name加载模块最终用php://input配合POST数据实现了RCE。这再次证明文件包含漏洞的杀伤力往往超乎想象。