1. 从“备份是个好习惯”这个标题说起
“备份是个好习惯”这个说法,放在日常运维里确实没毛病——定期备份数据库、备份站点文件、备份配置文件,出了事故能快速回滚。但放到Web安全攻防的语境下,这句话就变成了一句反讽:开发者的备份习惯,恰恰是攻击者最爱的突破口之一。
这道题属于典型的Web信息泄露类题目,核心考点就一个:备份文件泄露。题目给了一个看似平平无奇的页面,没有明显的注入点、没有上传入口、没有花哨的前端逻辑,但只要你意识到“备份文件可能被放在了Web目录下”,整道题就迎刃而解。
我写这篇复盘的目的,不是单纯给一个flag,而是想把这类题背后的通用排查思路讲透。因为备份文件泄露在真实渗透测试中出现的频率极高,很多企业的运维人员会把www.zip、index.php.bak、web.rar这类文件直接丢在网站根目录,攻击者用几个常见的字典就能扫出来。这道题就是把这个真实场景浓缩成了一个CTF关卡。
适合阅读这篇内容的人:刚接触CTF Web方向的新手、对目录扫描和源码审计还不熟悉的安全爱好者、以及想系统梳理“信息收集阶段该做什么”的从业者。下面我会从题目入口分析、备份文件命名规律、源码审计、参数绕过逻辑、以及实战中容易踩的坑这几个维度,把这道题彻底拆开。
2. 题目入口的初步判断与信息收集方向
2.1 页面表现与第一反应
打开题目给定的URL,页面内容通常非常简洁,可能只有一行文字或者一个空白页面。这种“什么都没有”的页面,恰恰是最需要警惕的。很多新手看到空白页就不知道下一步该干什么,其实这时候应该立刻切换到信息收集思维。
我拿到这类题目的第一反应是:先看页面源代码,再看HTTP响应头,最后做目录扫描。这三步是固定的肌肉记忆。页面源代码里可能藏着注释、隐藏表单、JS文件路径;响应头里可能暴露服务器类型、框架版本、Cookie特征;目录扫描则是找那些“不该被访问到”的文件。
这道题的关键线索不在页面本身,而在于题目名称给出的暗示——“备份是个好习惯”。出题人已经把答案的方向写在标题里了,就是在告诉你:去找备份文件。
2.2 常见的备份文件命名规律
备份文件的命名是有套路的,不是随便乱起。根据我这些年做渗透测试和CTF的经验,常见的备份文件命名可以归为以下几类:
| 类型 | 常见命名 | 说明 |
|---|---|---|
| 源码压缩包 | www.zip、web.zip、wwwroot.rar、backup.tar.gz | 整站打包备份 |
| 单文件备份 | index.php.bak、index.php~、index.php.swp | 编辑器自动备份 |
| 数据库备份 | db.sql、database.sql、backup.sql | 数据库导出文件 |
| 配置文件备份 | config.php.bak、.env.bak | 配置类文件副本 |
| 版本控制残留 | .git/、.svn/ | 版本控制目录泄露 |
这道题最可能的方向是源码压缩包或者单文件备份。因为题目没有给出任何其他线索,出题人大概率是把一个备份文件放在了Web根目录下,等着你去发现。
提示:在实际测试中,目录扫描工具(如dirsearch、gobuster)配合一份好的字典,能在几秒内发现这类文件。但在CTF中,有时候需要你手动猜测文件名,因为出题人可能用了非常规命名。
2.3 目录扫描的实操要点
如果你用工具扫描,建议字典里至少包含以下条目:
www.zip web.zip backup.zip wwwroot.zip html.zip index.php.bak index.php~ index.php.swp .bak .zip .rar .tar.gz扫描的时候注意状态码:200表示文件存在且可访问,403表示存在但禁止访问,301/302表示重定向。这道题里,备份文件应该是可以直接下载的,所以关注200的条目。
我个人的习惯是先用小字典快速扫一遍,找到可疑文件后再用大字典深挖。因为大字典跑起来慢,先缩小范围效率更高。
3. 备份文件到手后的源码审计重点
3.1 下载与解压
假设你已经找到了备份文件,比如www.zip,下载下来解压,会得到网站的源码。这时候不要急着乱翻,要有条理地看。我通常按照以下顺序审计:
- 入口文件:
index.php、index.html,看整体逻辑 - 配置文件:
config.php、db.php,看数据库连接、密钥等 - 功能文件:根据入口文件引用的文件逐个查看
- 工具函数:
functions.php、common.php,看有没有危险函数
这道题的源码结构应该比较简单,核心逻辑就在一两个文件里。
3.2 关键代码的识别
在审计过程中,要特别关注以下几类代码特征:
- 文件包含:
include、require、include_once,如果参数可控,就是文件包含漏洞 - 命令执行:
system、exec、shell_exec、passthru,参数可控就是命令执行 - 代码执行:
eval、assert、preg_replace的/e修饰符 - SQL查询:拼接式SQL语句,可能存在注入
- 反序列化:
unserialize,配合魔术方法可能触发漏洞
这道题的核心应该是一个变量覆盖或者参数绕过的逻辑。因为题目名称强调的是“备份”,而备份文件泄露后,源码里通常会有一个判断逻辑,比如检查某个参数是否等于特定值,或者检查请求来源。
3.3 一个典型的源码逻辑还原
根据这类题目的常见套路,源码里大概率有这样一段逻辑:
<?php include 'flag.php'; $key = $_GET['key']; if ($key == 'backup') { echo $flag; } else { echo "备份是个好习惯"; } ?>或者更复杂一点,涉及到MD5碰撞、弱类型比较、数组绕过等。但结合“备份”这个主题,最可能的还是变量覆盖或者直接比较绕过。
还有一种可能是源码里有一个extract()函数,把GET或POST的参数直接提取为变量,导致可以覆盖原有的变量值。比如:
<?php $flag = 'flag{xxxxx}'; extract($_GET); if ($backup == 'yes') { echo $flag; } ?>这种情况下,你只需要传?backup=yes就能拿到flag。
4. 参数构造与绕过的完整推演
4.1 从源码到Payload的推导
假设你审计源码后发现,逻辑是这样的:
<?php $file = $_GET['file']; if (isset($file)) { if (strstr($file, '..') || strstr($file, 'flag')) { die('禁止访问'); } include $file; } ?>这是一个典型的文件包含题目,但加了过滤。过滤了..和flag。这时候你需要绕过过滤。绕过方式有很多:
- 使用绝对路径:
/var/www/html/flag.php - 使用编码绕过:
%2e%2e代替.. - 使用PHP伪协议:
php://filter/convert.base64-encode/resource=flag.php
但注意,如果过滤了flag这个字符串,伪协议里的flag.php也会被拦截。这时候可以用php://filter/convert.base64-encode/resource=fla"."g.php这种方式拼接,或者用大小写绕过(如果过滤不严格)。
4.2 弱类型比较的经典绕过
如果源码里是比较逻辑,比如:
<?php $password = $_GET['password']; if ($password == 'admin') { echo $flag; } ?>这种弱类型比较,可以用?password=0或者?password=admin之外的任何在PHP弱类型比较下等于'admin'的值。但更常见的是MD5比较:
<?php if ($_GET['a'] != $_GET['b'] && md5($_GET['a']) == md5($_GET['b'])) { echo $flag; } ?>这时候可以用数组绕过:?a[]=1&b[]=2,因为md5()函数不能处理数组,会返回null,而null == null为真。
4.3 本题最可能的Payload形式
结合“备份”这个主题,我推测本题的Payload可能是以下几种之一:
- 直接访问备份文件:
http://target/www.zip,下载后审计源码,找到flag - 变量覆盖:
?backup=1或?key=backup - 文件包含:
?file=flag.php配合某种绕过
如果是第一种,那flag可能直接写在源码的注释里,或者在一个被包含的flag.php文件里。如果是第二种,那就是一个简单的参数判断。如果是第三种,就需要结合过滤规则来构造。
注意:在实际操作中,不要一上来就尝试复杂的Payload。先把简单的情况试一遍:直接访问常见备份文件名、传最简单的参数、看页面回显变化。很多时候答案比你想的简单。
5. 实战中容易踩的坑与排查经验
5.1 备份文件找不到怎么办
这是新手最常遇到的问题:知道要找备份文件,但扫不出来。原因可能有几个:
- 字典不够全:你用的字典里没有出题人设定的文件名。这时候需要根据题目名称、页面特征去猜。比如题目叫“备份是个好习惯”,那文件名可能是
backup.zip、www.zip、web.rar。 - 路径不对:备份文件可能不在根目录,而在某个子目录下。比如
/admin/backup.zip、/data/www.zip。 - 需要特定请求头:有些题目会检查
Referer或User-Agent,不满足条件就返回404。 - 文件扩展名被改:比如
www.zip.bak、www_zip.txt。
我的经验是:先用常见字典扫一遍,如果没有结果,就根据题目名称手动构造几个候选文件名,逐个尝试。同时注意观察响应状态码和响应长度,有时候文件存在但返回的是302跳转。
5.2 源码审计时容易忽略的细节
拿到源码后,很多人只看主逻辑,忽略了注释和次要文件。我踩过的坑包括:
- flag藏在注释里:
<!-- flag{xxxxx} -->,这种最气人,但也最常见 - flag在图片的EXIF里:备份包里有一张图片,flag写在EXIF信息中
- flag在数据库导出文件里:
backup.sql里有一条insert语句包含flag - flag需要二次解码:源码里看到的flag是base64编码的,需要解码
所以审计的时候,不要只盯着PHP代码,HTML注释、SQL文件、图片、文本文件都要看一遍。
5.3 参数传递方式的坑
有时候源码里用的是$_POST,你却一直在用GET传参;或者源码里用的是$_REQUEST,但你只试了GET没试POST。这些细节会导致你明明构造对了Payload却拿不到flag。
还有一种情况是参数名大小写敏感。PHP的变量名是区分大小写的,$Key和$key是两个不同的变量。如果源码里写的是$Key,你传key是没用的。
另外,注意参数传递的编码问题。比如你传?file=flag.php,但服务器可能对URL进行了二次解码,导致你的Payload被改变。这时候需要用%00截断或者双重编码。
6. 从这道题延伸出的通用排查方法论
6.1 信息收集阶段的检查清单
这道题虽然简单,但它代表了一类非常常见的漏洞。我把这类题目的排查流程整理成一个清单,以后遇到类似场景可以直接套用:
- 查看页面源代码:找注释、隐藏字段、JS文件路径
- 查看HTTP响应头:找Server、X-Powered-By、Set-Cookie等
- 查看robots.txt:可能泄露敏感路径
- 目录扫描:用常见字典扫备份文件、敏感目录
- 尝试常见备份文件名:
www.zip、backup.zip、index.php.bak等 - 检查版本控制残留:
.git/、.svn/ - 检查编辑器临时文件:
.swp、~、.bak
这个清单不仅适用于CTF,也适用于真实的渗透测试。很多企业的网站就是因为运维人员把备份文件放在了Web目录下,导致源码泄露,进而被攻击者发现更多漏洞。
6.2 备份文件泄露的真实危害
在真实环境中,备份文件泄露的危害远不止拿到一个flag。攻击者可以通过源码审计发现:
- 数据库连接信息:直接连上数据库,拖走所有数据
- API密钥:调用内部接口,获取敏感信息
- 硬编码的后门:开发者留下的调试入口
- 框架版本:根据版本号查找已知漏洞
- 业务逻辑漏洞:比如支付逻辑、权限校验逻辑
所以“备份是个好习惯”这句话,对开发者来说是提醒,对攻击者来说是机会。正确的做法是:备份文件不要放在Web目录下,如果必须放,要加访问控制,并且定期清理。
6.3 防御视角的思考
从防御的角度看,这道题给我们的启示是:
- Web目录下不要放任何备份文件:包括压缩包、SQL文件、编辑器临时文件
- 配置Web服务器禁止访问特定扩展名:比如在Nginx里配置
location ~* \.(zip|rar|bak|sql|swp)$ { deny all; } - 定期做安全扫描:用工具扫描自己的站点,看看有没有意外的文件暴露
- 版本控制目录要正确配置:
.git目录不能被外部访问
这些措施成本很低,但能挡住大部分自动化扫描工具。安全这件事,很多时候就是比谁少犯低级错误。
7. 我在这道题上花时间最多的环节
说实话,这道题的技术难度不高,但我第一次做的时候还是卡了一会儿。卡住的点不是技术问题,而是思维定势。我一开始一直在找注入点、找上传点,完全忽略了题目名称给出的提示。后来是队友提醒了一句“备份是个好习惯”,我才反应过来应该去找备份文件。
这个经历让我意识到:CTF题目里的每一句话都可能是线索,尤其是题目名称。出题人不会无缘无故起一个名字,名字本身就是提示。后来我做题的习惯就变了:先读三遍题目名称,把每个词都拆开想一遍,再开始动手。
另一个花时间的点是字典的选择。我一开始用的字典里没有www.zip这个条目,扫了半天没结果。后来换了一个专门针对备份文件的字典,才扫出来。所以工具和字典的准备很重要,平时要积累一份好用的字典,关键时刻能省很多时间。
最后拿到flag的时候,其实flag本身很简单,但整个排查过程让我对“信息收集”这个阶段有了更深的理解。很多新手觉得信息收集枯燥,不如直接上Payload来得爽,但实际上,信息收集决定了你后续攻击的上限。收集得越充分,攻击路径越清晰。
8. 给刚入门的朋友几点实在建议
如果你刚开始接触CTF Web方向,这道题是一个很好的练手素材。我的建议是:
第一,不要急着看Writeup。先自己动手试,哪怕试不出来,也要把尝试的过程记录下来。你试过的每一个文件名、每一个参数,都是经验积累。
第二,建立自己的字典库。把每次遇到的新文件名、新路径记下来,慢慢你的字典就会越来越全。我现在的字典里有一千多条备份文件相关的条目,都是这些年一点点攒的。
第三,学会看源码。不要只依赖工具,工具扫不出来的东西,往往需要你手动审计源码才能发现。PHP的基本语法、常见危险函数、弱类型比较规则,这些都要熟悉。
第四,多总结套路。CTF题目千变万化,但底层套路是有限的。备份文件泄露、文件包含、SQL注入、反序列化、SSRF,把这些核心套路吃透,遇到新题就能快速定位方向。
这道题虽然简单,但它背后的“备份文件泄露”这个知识点,在真实场景中非常实用。希望这篇复盘能帮你把这类题彻底搞明白,下次遇到类似题目能秒出思路。