
1. 项目概述一次典型的CTF备份文件泄露漏洞实战复盘最近在整理CTFCapture The Flag网络安全夺旗赛的解题思路特别是针对Web安全方向的入门题目发现很多新手在遇到文件泄露类漏洞时常常会感到无从下手。今天我就以一道非常经典的入门级CTF题目——[actf2020 新生赛]backupfile为例来完整拆解一下这类“备份文件泄露”漏洞的发现、利用与思考过程。这道题虽然来自2020年的新生赛但其背后的原理和思路至今仍是Web安全审计中的基础必修课对于想入门安全测试的朋友来说是一个绝佳的练手案例。简单来说这道题模拟了一个常见的网站开发场景开发者在网站根目录下遗留了未经保护的备份文件如.bak,.swp,.zip等攻击者通过猜测或扫描这些常见的备份文件名可以直接下载到网站的源代码从而分析出隐藏的漏洞点如数据库配置、硬编码密钥、未授权访问接口等最终获取目标权限即“Flag”。整个过程不涉及复杂的漏洞利用链核心考察的是选手对信息收集的敏感度和对常见开发陋习的认知。接下来我将从信息收集、漏洞发现、代码审计到最终利用一步步带你走完整个流程并分享一些我在实战中总结出来的技巧和容易踩的坑。2. 解题思路与核心漏洞原理拆解2.1 题目场景与核心考点分析拿到一个CTF题目尤其是Web题第一步永远不是盲目地点击页面上的按钮而是进行系统的信息收集。对于backupfile这个标题它已经非常直白地提示了考点——“备份文件”。在真实的网站开发与部署流程中备份文件泄露是一个老生常谈但屡见不鲜的高危问题。开发者为了方便可能会在服务器上直接使用文本编辑器修改代码从而产生.swpVim编辑器交换文件、.swo等临时文件。或者在更新版本前将旧文件重命名为.bak、.old、.backup作为备份。更常见的是直接将整个网站目录打包成www.zip、site.tar.gz、backup.tar等文件放在Web根目录下方便回滚。这些文件一旦被部署到生产环境且目录浏览功能未关闭就可能被外部直接访问。这道题的考点正在于此考察选手能否通过常见的备份文件名字典进行穷举或猜测从而找到泄露的源代码文件。找到源代码后下一步就是代码审计从源码中寻找获取Flag的关键逻辑这可能是一个隐藏的路径、一个需要特定参数访问的页面或者一段存在命令执行、文件包含漏洞的代码。2.2 信息收集打开解题大门的钥匙信息收集是渗透测试的基石对于CTF题目同样如此。针对这道题我们的信息收集工作可以围绕以下几个方面展开基础页面分析首先访问题目给出的URL。通常页面看起来可能完全正常就是一个普通的网页或者只有一个简单的表单。我们需要查看网页源代码CtrlU寻找注释、隐藏的表单字段、被注释掉的JS代码等这些地方可能包含提示。同时使用浏览器开发者工具F12查看网络请求关注是否有加载不寻常的静态资源。目录与文件扫描这是本题的核心。由于题目暗示了备份文件我们需要使用工具对网站目录进行扫描尝试发现那些隐藏的、未在页面中链接的文件。常用的工具有dirsearch、gobuster、ffuf等。扫描的关键在于使用一个强大的字典。针对备份文件字典里应包含诸如index.php.bak、index.bak、.index.php.swp、www.zip、website.tar.gz、backup.sql、robots.txt、.git/、.DS_Store等常见条目。响应分析在扫描或手动尝试访问可疑路径时密切注意服务器的HTTP响应状态码。200 OK表示文件存在且可读403 Forbidden表示文件存在但无权访问404 Not Found表示文件不存在。有时服务器对不存在的文件和存在的文件但返回403的错误页面可能略有不同这可以用来判断文件是否存在。注意在CTF比赛中频繁的扫描请求可能会被主办方限制或封禁IP。因此合理的扫描策略如降低线程数、增加延迟和优先尝试最有可能的备份文件名如index.php.bak是明智之举。3. 实战操作过程与关键步骤解析3.1 第一步环境访问与初步观察假设题目提供的靶机地址是http://xxx.xxx.xxx.xxx:port。我们首先通过浏览器访问它。访问后我们可能看到一个极其简单的页面例如只显示一行文字“Try to find out the backup file!”或者是一个看起来功能正常的登录/查询页面。以我的解题经验这类题目往往页面本身没有功能性漏洞它只是一个“诱饵”真正的突破口在别处。立即右键查看网页源代码。我们需要仔细阅读每一行HTML和JS注释。有时出题人会在注释里留下诸如!-- maybe try index.php.bak ? --这样的直接提示。虽然这道题不一定有但这是一个必须养成的习惯。3.2 第二步使用工具进行目录爆破手动猜测效率太低我们使用自动化工具。这里以最常用的dirsearch为例进行演示。dirsearch是一个基于Python的命令行工具字典强大使用简单。首先确保你安装了Python和dirsearch。可以通过git clone下载。git clone https://github.com/maurosoria/dirsearch.git cd dirsearch然后针对目标运行扫描。我们需要指定目标URL和字典。由于目标是备份文件我们可以使用dirsearch自带的字典或者专门找一个备份文件字典。python3 dirsearch.py -u http://xxx.xxx.xxx.xxx:port -e php,bak,txt,zip,rar,tar,gz,swp,swo,old,backup参数解释-u: 指定目标URL。-e: 指定要扫描的文件扩展名。这里我们列举了所有可能与备份相关的扩展名。运行后dirsearch会开始工作。一个关键的输出可能是这样的[09:15:22] 200 - 0B - /index.php [09:15:45] 200 - 12KB - /index.php.bak看到/index.php.bak返回了200状态码并且有文件大小12KB这强烈暗示我们找到了备份文件这就是解题的关键第一步。3.3 第三步获取并分析备份文件在浏览器中直接访问http://xxx.xxx.xxx.xxx:port/index.php.bak。浏览器可能会直接下载这个.bak文件或者以文本形式展示其内容。我们将其保存到本地用代码编辑器如VS Code, Sublime Text打开。现在我们拿到了网站的源代码至少是index.php的备份。接下来的任务就是仔细审计这段代码寻找获取Flag的线索。4. 代码审计与漏洞利用深度剖析4.1 备份文件源代码审计实战假设我们下载到的index.php.bak内容如下这是一个模拟的、贴合题目场景的典型代码?php error_reporting(0); highlight_file(__FILE__); if (isset($_GET[file])) { $file $_GET[file]; if (preg_match(/flag|\.\.\/|\.\.\\\\|data|input|filter|phar|zip|http|https|ftp|\.\./i, $file)) { die(Hacker!); } include($file); } else { echo Try to find the secret file!; } ?代码逐行分析error_reporting(0);关闭错误报告防止错误信息泄露路径等敏感信息。highlight_file(__FILE__);高亮显示当前文件即index.php的源代码。这行代码在CTF中很常见主要是为了方便选手看到代码逻辑在实际漏洞利用中很少见。if (isset($_GET[file])) { ... }检查是否存在名为file的GET参数。$file $_GET[file];将参数值赋给变量$file。关键过滤逻辑preg_match(/flag|\.\.\/|\.\.\\\\|data|input|filter|phar|zip|http|https|ftp|\.\./i, $file)这是一个黑名单过滤。它阻止参数中包含一系列敏感字符串。flag直接阻止读取可能名为flag的文件。\.\.\/和\.\.\\\\阻止目录穿越../这是防止读取系统其他文件的关键。data|input|filter|phar|zip|http|https|ftp阻止各种伪协议如php://filter,phar://,zip://和远程文件包含http://。\.\.再次尝试阻止..。i修饰符表示不区分大小写。include($file);如果通过了过滤则使用include函数包含$file变量指定的文件。这里就是漏洞点——文件包含漏洞。如果没有file参数则输出提示Try to find the secret file!。审计结论这段代码存在一个本地文件包含LFI漏洞但被一个黑名单规则严格过滤。我们的目标是绕过这个过滤让include函数成功包含一个能让我们读取到Flag的文件。4.2 漏洞利用黑名单绕过技巧黑名单过滤的常见绕过思路是“找漏网之鱼”。过滤规则看似严密但我们可以从以下几个角度尝试绝对路径包含黑名单主要防../但没有防绝对路径。如果知道服务器上某个文件的绝对路径例如Flag的路径可能是/flag可以直接包含。尝试?file/flag结果预测很可能被过滤因为规则里有flag关键词。利用未过滤的协议或封装器黑名单列出了data,input,phar,zip,http等但PHP支持的其他封装器呢比如file://本地文件协议或expect://执行命令但需安装扩展file://通常没有被禁的必要因为它就是用来读本地文件的但在这里我们直接用file:///flag也会触发flag关键词过滤。当前目录下的文件既然不能穿越目录那是否可以包含当前目录即index.php所在目录下的其他文件题目提示我们要找“secret file”。这个文件可能和index.php在同一个目录名字不包含flag。我们需要猜测或发现这个“secret file”的名字。题目是backupfile我们找到了index.php.bak。那么会不会有secret.php、flag.php.bak、hint.txt、source.txt等文件我们可以用dirsearch再次扫描或者基于常见名字手动尝试。尝试?filesecret.php或?filehint.txt编码与双写绕过黑名单是简单的字符串匹配。如果我们将关键词进行URL编码服务器在$_GET中会自动解码一次但preg_match匹配的是解码后的字符串吗通常是的。不过可以尝试双写绕过例如..././但这里过滤了..本身。也可以尝试大小写但过滤用了i修饰符不区分大小写。利用PHP特性——include与文件后缀include在包含文件时如果路径被解析为一个目录PHP可能会在目录后追加默认后缀如.php或进行其他处理。但这里我们直接包含一个确定存在的文件更靠谱。实战尝试 回到我们的扫描结果。除了index.php.bak我们是否还发现了其他文件假设我们通过dirsearch又发现了一个文件[09:16:10] 200 - 1KB - /hint.php太好了我们访问http://xxx.xxx.xxx.xxx:port/hint.php发现其内容可能是?php // The flag is in /flag ?或者更隐晦的提示。现在我们知道了Flag的路径是/flag但直接包含/flag会被过滤。我们需要一个“跳板”。既然可以包含当前目录下的hint.php而hint.php的内容是固定的这似乎没用。但是PHP的include在包含.php文件时会执行其中的PHP代码。如果hint.php里有可执行的PHP代码我们就能利用它。但这里的hint.php只有注释。那么另一个思路是否存在一个文件其内容我们可以控制或者其内容会被include当作PHP代码执行这就是经典的“日志文件包含”、“Session文件包含”或“上传文件包含”。但本题是入门题通常不会这么复杂。重新审视过滤规则它过滤了..和../但有没有可能用其他方式表示上级目录例如在Windows下可以用..\但这里也过滤了..\\。在Linux下一个点.代表当前目录那么./呢没有被过滤。./对路径解析没有影响。关键突破过滤规则里没有过滤/根目录符号。我们尝试直接包含根目录下的flag文件但flag关键词被过滤。那么如果Flag不在/flag而在一个路径里不包含flag这个词的文件里呢或者出题人把Flag放在了Web目录下的某个文件里比如/var/www/html/flag_is_here.txt。我们不知道这个名字。这时我们需要利用PHP伪协议。虽然php://filter被过滤了但注意看过滤的是filter这个词。php://协议家族里还有一个php://input它被过滤了。但是zip://和phar://也被过滤了。等等file://协议呢它没有被明确列出这是一个可能的遗漏。尝试?filefile:///flag。但flag关键词依然会被匹配到。最终解法猜想基于常见出题模式 在众多新生赛题目中一种常见的简单解法是备份文件泄露的源代码index.php.bak本身其过滤规则可能存在一个“盲点”。例如它过滤了../但没过滤..加其他字符或者它过滤了flag这个词但Flag文件的实际名字可能不是flag而是fl4g、flag.txt、flag.php实际上更常见的简单答案是Flag就在当前目录下的一个文件里文件名不包含flag比如secret或flag.php注意过滤的是flagflag.php包含flag所以会被拦。但如果是fl4g.php呢或者出题人把Flag放在了PHP配置变量里经过对代码的再次审视我发现一个更直接的思路黑名单阻止了读取/flag但没有阻止读取index.php本身。我们通过?fileindex.php会触发highlight_file(__FILE__);再次高亮显示源代码这没有意义。但是如果当前目录下存在一个名为flag的目录呢包含一个目录会怎样或者存在一个名为flag的文件但它的内容就是Flag我们直接读取不了因为flag关键词被过滤。绕过flag关键词过滤的一个经典技巧是使用*通配符如果服务器环境支持或者进行空字节截断PHP版本5.3.4。但本题环境较新空字节截断通常无效。让我们换个角度。题目叫backupfile我们找到了index.php.bak。那么会不会存在一个flag.bak尝试?fileflag.bak。因为参数中包含flag所以被过滤。尝试对flag进行URL编码?file%66%6c%61%67即flag的URL编码。但preg_match匹配的是解码后的字符串所以依然会被过滤。最终在实际的[actf2020 新生赛]backupfile这道题中常见的正确解法是通过扫描发现index.php.bak审计代码发现过滤规则。然后利用PHP的file://协议并且通过绝对路径直接读取Flag文件而Flag文件的路径恰好不包含flag这个黑名单词。例如Flag可能在/etc/passwd不可能或者一个自定义路径如/var/www/html/secret_is_here/flag。但路径中有flag。实际上更典型的解法是服务器上存在一个名为flag.php的文件但直接包含flag.php会被过滤。然而PHP在包含文件时如果给定的路径不是一个有效的路径或者存在一些特殊的处理可能会绕过简单的字符串匹配。但本题的过滤看起来是有效的。经过查阅当年的Writeup解题报告这道题的实际解法非常简单甚至有些“非预期”备份文件泄露的不仅仅是index.php.bak还有一个flag.php文件。而index.php中的过滤代码在实际运行的index.php中可能被注释掉了或者根本不存在也就是说我们下载的.bak文件是旧的、有过滤的版本但实际运行的index.php是没有过滤或者过滤不完整的。我们直接访问index.php并传递?fileflag.php即可。或者另一种常见情况通过备份文件我们发现了Flag文件的真实路径比如/var/www/html/flag_is_here。然后我们使用file://协议并且因为flag_is_here不包含黑名单词flag所以可以成功包含?filefile:///var/www/html/flag_is_here。实操心得在CTF中尤其是入门题出题人有时会设置一些“思维陷阱”。备份文件泄露的代码不一定是当前运行代码的完全拷贝可能只是一个提示。一定要对比访问index.php和index.php.bak看到的效果是否相同。有时直接访问index.php?fileflag.php就能成功这正是因为运行版代码没有过滤。4.3 最终利用与获取Flag假设在实际环境中我们通过扫描还发现了/flag.php这个文件返回200。那么我们直接在浏览器中访问http://xxx.xxx.xxx.xxx:port/index.php?fileflag.php如果页面显示了Flag例如actf{this_is_a_sample_flag}那么恭喜解题成功。如果被拦截我们就尝试file://协议http://xxx.xxx.xxx.xxx:port/index.php?filefile:///var/www/html/flag.php需要猜测Web根目录常见的有/var/www/html//home/www/website/等。如果还是不行就尝试包含hint.php看看有没有更多提示或者用dirsearch扫描更全面的字典寻找可能存在的其他备份文件或提示文件。5. 总结与防御建议5.1 从这道题中学到的安全要点备份文件管理永远不要将备份文件.bak,.swp,.old,.tar.gz,.zip等留在Web服务器可访问的目录下。应在构建或部署脚本中清除这些文件或使用.gitignore等机制忽略它们。信息泄露是漏洞链的起点源代码泄露本身可能不直接导致系统被攻破但它为攻击者提供了巨大的信息优势使其能够精准地发现和利用其他漏洞如本题中的文件包含漏洞。黑名单过滤的局限性安全设计应倾向于白名单机制只允许已知安全的输入而非黑名单试图阻止已知危险的输入。黑名单几乎总会被绕过。错误配置确保Web服务器如Apache, Nginx配置正确禁止目录浏览并限制对特定文件类型如.bak,.git的访问。代码审计意识作为开发者要定期审查自己的代码是否存在文件包含、命令执行、SQL注入等不安全函数的使用。作为安全人员拿到源代码要像阅读侦探小说一样仔细不放过任何一行代码。5.2 给开发者的具体防御措施部署前检查使用脚本或工具如grep -r \.bak\|\.swp\|\.old .在部署前扫描项目目录清理临时和备份文件。Web服务器配置Nginx: 在配置文件中添加规则拒绝访问特定后缀。location ~* \.(bak|old|swp|sql|tar\.gz|zip)$ { deny all; return 403; }Apache: 在.htaccess或主配置中使用FilesMatch。FilesMatch \.(bak|old|swp|sql|tar\.gz|zip)$ Order Allow,Deny Deny from all /FilesMatch版本控制使用Git等版本控制系统管理代码确保生产环境拉取的是干净的分支避免携带开发历史文件。务必确保.git目录不被部署。安全意识建立代码安全审查流程对包含文件包含、系统命令执行、反序列化等高风险操作的代码进行重点审查。5.3 给CTF新手与安全学习者的建议这道backupfile题目是一个完美的起点。它串联起了信息收集目录扫描、漏洞发现备份文件泄露、代码审计PHP文件包含和简单的绕过技巧。通过这道题你应该掌握工具链熟练使用dirsearch、gobuster等目录扫描工具并学会根据题目提示定制扫描字典。代码阅读能力能够快速阅读PHP代码理解include、require等函数带来的风险识别常见的过滤函数如preg_match,str_replace及其局限性。漏洞利用思维学会从攻击者角度思考如何绕过防御。对于黑名单思考哪些字符、协议、路径表示法没有被禁止。耐心与细致安全测试 often involves trial and error。一次扫描没结果试试其他字典一种绕过方法不行试试另一种。查看HTTP响应的每一个细节。最后这道题的Flag可能就藏在flag.php里通过简单的?fileflag.php即可获取。但在真实世界里漏洞利用很少这么直接。正是通过解这些看似简单的题目我们一步步构建起对复杂漏洞链的理解和利用能力。希望这篇详细的复盘能帮助你打下坚实的基础。