
CTF圈里有句老话信息收集做得好漏洞利用不用愁。我刷 CTFHUB 的时候信息泄露这个模块最初是被我跳过的——总觉得备份文件下载不就是下载个文件嘛能有什么技术含量。直到后来在一次线上赛里一道最简单的签到题卡了我半小时目标目录里明晃晃躺着一个.DS_Store我压根没认出来最后只能看着别人几分钟拿 flag。从那以后我才老老实实回头把备份文件下载这组题目完整过了一遍。今天这篇文章就把这个模块彻底拆开聊网站源码、bak文件、vim缓存、.DS_Store 这四类备份文件分别是什么、为什么会存在、做题时怎么发现以及从开发运维角度怎么避免这类问题。既适合刚开始接触 CTF 的选手也适合想自查站点有没有备份残留的开发和运维朋友。1. 信息泄露为什么被放在技能树最前面1.1 信息收集是所有漏洞利用的前置条件在 CTF 的 Web 方向不管题目多难第一步永远是看。看响应头、看页面源码、看目录结构、看请求参数。信息泄露题就是把这件看的训练单独放大。备份文件下载这个考点核心训练目标有两个一个是目录探测能力一个是对文件痕迹的敏感度。目录探测说白了就是猜路径。很多人觉得猜这个动作不专业——好像高端渗透都是用 0day 打进去的。但实际不管是 CTF 还是授权测试路径枚举永远是最基础也最有效的手段。区别只在于有经验的人会从站点返回的状态码、内容长度、报错信息里快速判断下一步该猜什么没经验的人只会盲目跑完一个字典然后不知所措。CTFHUB 把这四类备份文件单独做成一个模块本质上就是在帮你训练这种看到文件名就能想到它背后可能有什么的能力。你探测到一个/public/目录存在能不能立刻想到里面可能有/public/backup.zip你看到页面是index.php能不能想到去访问index.php.bak或者.index.php.swp这些不是玄学完全可以系统训练出来。1.2 四类文件泄露背后的共同逻辑网站源码、bak文件、vim缓存、.DS_Store 这四个考点背后对应的是四种完全不同的产生源网站源码压缩包开发或运维人员的备份行为bak文件编辑器或开发者手动备份的习惯vim缓存vim 编辑器崩溃或异常退出留下的临时文件.DS_StoremacOS Finder 自动生成的文件虽然题目模块叫备份文件下载但考题重点并不是下载这个动作而是发现这一步。前面两类相对容易用字典扫出来后面两类则更考验知识面——你不知道 vim 交换文件的命名规则或者不知道 .DS_Store 的存在那就算文件真的放在眼前也发现不了。这正是这类题目设计得有意思的地方。另外得说一句这组题不只是用来刷分的。真实世界里因为一个备份文件导致站点泄露的案例非常多。很多中小型网站的维护者习惯把整站打包放根目录文件名就叫backup.zip或者www.zip传上去就忘了删。攻击者只要扫一下常见路径整站源码甚至数据库配置就可能直接到手。理解这些泄露路径不管站在攻击队思路还是防守队视角都是必修课。2. 网站源码压缩包泄露范围最大也最直白2.1 压缩包备份为什么屡禁不止网站源码这道题考的是最直白的一类泄露整个项目被人打成压缩包放在了 Web 目录下。常见格式有 zip、tar.gz、rar、7z文件名虽然五花八门但核心命名规律就那几种按关键词命名www、web、site、html、code、src、backup、bak、temp、old、test、wwwroot带版本号或日期www_2020.zip、site_v1.2.tar.gz、backup_20240101.zip直接用数字1.zip、2.zip、666.zip或者拼接成 web1.zip与目录同名目录名是 admin 就可能存在 admin.zip域名是 example.com 也可能有 example.com.zip为什么这类泄露屡禁不止因为把代码打成压缩包这个操作本身太顺手了。从服务器迁移、下载本地备份、发给同事调试随手 zip 一下放在网站目录然后忘了删是很多非专业运维都干过的事。CTF 题目不过是把这个常见的现实问题浓缩成了一道题。2.2 做题时的探测流程CTFHUB网站源码这道题直接访问根目录时页面内容非常简单正常浏览没有任何提示。这时候要做的是先手工试最可能的几个路径/www.zip、/web.zip、/backup.zip、/域名.zip手工不行就上字典工具dirsearch、7kbscan、御剑都可以也可以写个简单的爆破脚本只跑文件名字典重点关注 HTTP 状态码和响应头里的 Content-Length。如果访问/backup.zip返回 200且 Content-Length 明显比普通页面大一个数量级那基本就是它了这里有个细节值得注意不要只扫根目录。有些题目会把压缩包放在某个子目录下比如/upload/backup.zip或者/admin/www.zip。所以扫描时记得带上递归深度或者根据页面里其他线索去猜子目录。2.3 下载解压之后别急着找 flag压缩包拿到手第一件事不是急着解压找 flag而是先看压缩包里的目录结构。我见过不少人拿到压缩包立刻全部解压然后漫无目的地翻效率其实很低。正确做法是用unzip -l或tar -tf先列一遍压缩包里有哪些文件重点关注SQL 文件、配置文件config.php、settings.py、application.properties、README、隐藏文件解压后全局搜索Linux 下直接grep -r flag .或者用find把全部文件列出来人工扫一遍有些题目还会把 flag 藏在文件名里或者藏在被注释掉的代码里所以别只看 PHP 文件CSS、JS、HTML 都要扫一眼。我做题时发现flag 直接写在模板注释里的出题率还挺高这个习惯值得保留。3. bak文件一个后缀名暴露编辑习惯3.1 bak文件到底是怎么来的bakbackup文件是开发过程中最容易留在服务器上的文件之一。它的产生场景通常有两种。第一种是手动备份开发人员改文件之前担心改坏了于是执行cp index.php index.php.bak或者干脆复制一份改名成带 .bak 的文件。这种备份往往和原文件放在同一个目录里一放就是几个月甚至几年。第二种是编辑器自动生成某些编辑器或者 IDE 在保存文件时默认把上一次版本另存为后缀带 .bak 的文件。老版本的 EditPlus、UltraEdit 都干过这种事部分 FTP 工具在下载覆盖前也会生成临时备份。这里要理解一个关键技术点当你访问/flag.php时Web 服务器会通过 PHP 解析器执行它你只能看到渲染后的 HTML 输出但当你访问/flag.php.bak时绝大多数服务器不认识 .bak 这个后缀不会调用 PHP 解析器而是直接把文件内容当普通文本返回。这样一来原本只在服务端执行的代码就以源码形式交到了你手里。3.2 经典路径组合与枚举方法CTFHUB bak文件这道题解法其实很固定先访问主页判断它是用什么语言写的推测可能存在哪些源文件枚举常见备份名index.php.bak、flag.php.bak、config.php.bak、admin.php.bak如果页面里给了你某些线索——比如报错信息、注释里出现的路径优先试对应的 .bak这里整理了一些常见的备份组合原文件备份文件访问结果index.phpindex.php.bak直接看到 PHP 源码flag.phpflag.php.bak获取 flag 逻辑config.phpconfig.php.bak数据库账号密码等配置function.phpfunction.php.bak后台业务逻辑不要只试 php 后缀txt、html、sql 也都值得考虑。备份文件的后缀不一定是 .bak也可能有 .bak1、.old、.save 这类变体。做题时如果字典里没有这几个后缀手动加上再跑一轮。3.3 下载到bak之后怎么还原拿到 .bak 文件后如果内容是文本直接用代码编辑器打开即可。注意编码问题老项目经常出现 GB2312 乱码这时候可以用iconv -f GBK -t UTF-8转一下再读。如果拿到的是二进制文件先用file命令判断类型再决定用对应工具处理。还有一个我经常用的招如果题目给的是flag.php.bak下载后内容里有大量特殊字符不要硬读。先跑strings提取可打印字符串再正则匹配 flag 相关关键词。有时候整个文件被某种混淆手法处理过直接盯着看反而容易漏掉关键信息。顺带提一个真实环境里的例子。之前做授权测试时我在目标站点的/editor/目录下发现了一个编辑器残留文件夹顺手试了试/editor/connector.php.bak结果直接拿到了连接器的源码。这个文件本身没泄露敏感数据但通过阅读源码我找到了它的上传校验逻辑对后续构造请求帮助很大。所以说bak 文件的价值往往不只是直接读源码它更像一个引子能带你进入目标系统的内部逻辑。4. vim缓存文件藏在隐藏点号后面的编辑器现场4.1 vim交换文件的生成机制用 vim 编辑文件时vim 会在同目录下创建一个隐藏的交换文件用来保存尚未写入磁盘的修改内容防止断电或断网导致数据丢失。文件名的规则是在原文件名前面加点后面加.swp打开index.php编辑就会生成.index.php.swp如果交换文件已经存在比如另一个 vim 会话正在编辑同一个文件就会生成.index.php.swo再往后依次是 .swn、.swm后缀字母往下推正常使用 vim 并退出时交换文件会被自动删除。但 vim 进程被强制结束——ssh 掉线、终端被直接关闭、系统崩溃——交换文件就会残留在目录里。关键问题就在这里残留的交换文件保存着上次编辑时缓冲区的内容其中很可能包含完整的源码。4.2 做题怎么发现 vim 交换文件CTFHUB vim缓存这道题最关键的技能就是知道要去访问以点号开头的隐藏文件。很多人扫目录时字典里没有包含点号开头的文件或者工具默认过滤了隐藏文件导致这道题怎么都找不到入口。正确思路先确认站点当前页面对应的文件一般是/index.php直接尝试访问/.index.php.swp返回 200 说明交换文件存在如果 .swp 不行就试 .swo、.swn如果 index 不行就试试 flag、admin、config 这些名字还有一点值得注意vim 的残留文件不只有 swp 后缀某些配置下还会生成.viminfo或叫index.php~的备份文件。做的时候多试几种后缀不要在一棵树上吊死。事实上这也不是 CTF 里才有的问题。很多开发习惯直接在服务器上用 vim 改线上配置改到一半终端会话超时断开swap 文件就留在了 Web 目录。扫描器扫到之后下载下来nginx 配置、PHP 源码、甚至密码哈希都可能被翻出来。所以这道题也是在提醒别在生产环境直接用 vim 改代码改完也要确认没有残留 swap 文件。4.3 从交换文件恢复源码的实操下载到 .swp 文件之后恢复源码有两条路。第一条是用 vim 自带的恢复功能。把文件放到本地比如index.php.swp然后执行vim -r index.php.swpvim 会提示恢复未保存的更改确认后就能看到编辑器崩溃前缓冲区里的内容。如果这个交换文件是别人编辑时留下的看到的往往是源文件完整内容或者未保存修改的版本。第二条是用 strings 工具提取。在没有安装 vim 的机器上直接执行strings .index.php.swp | grep -i flag很多 CTF 题的 flag 或关键代码就藏在交换文件的字符串碎片里这种方法往往比vim -r更直接。这里有个踩坑提示vim -r恢复时要注意交换文件格式兼容性新版 vim 打开旧版交换文件通常会提示版本不匹配或者需要手动指定编码。这种情况下用strings提取反而更加稳妥。5. .DS_StoremacOS用户的目录地图5.1 一个埋藏极深的系统文件.DS_StoreDesktop Services Store是 macOS Finder 自动生成的隐藏文件作用是记录文件夹的显示设置——图标位置、窗口大小、背景图、排序方式等。只要你用 Finder 打开过一个文件夹macOS 就会在里面生成一个 .DS_Store 文件。这个文件本身不是备份但它有一个很危险的特性它会记录该目录下所有文件和子目录的文件名。换句话说一个 .DS_Store 就相当于当前目录的一张地图。你不需要暴力枚举这个目录有哪些文件只要解析出 .DS_Store 里的文件名列表就能直接定位到目标。更棘手的是很多开发者在 Mac 上打包上传整个项目文件夹时会把目录里隐藏的 .DS_Store 一并传上去于是这张地图就被带到了 Web 服务器上。5.2 解析思路与工具选择.DS_Store 是二进制格式直接打开就是一堆乱码。解析的大致思路是读取文件头部的 Bud1 标记然后逐个解析后面的记录项。每个记录项里保存了文件名和坐标编码我们要提取的就是这些文件名。这里不需要从零写解析器三种现成方案在 macOS 上直接看用 Finder 打开目录或者在终端用ls -la查看隐藏文件再配合第三方工具导出文件名列表使用 Python 的 dsstore 库pip install dsstore之后几行代码就能解析用 Hex 编辑器手动分析不太推荐效率太低我在做题时比较喜欢用 Python 脚本因为可以批量处理多个 .DS_Store把解析出的文件名列表直接存成字典下一步再拿这个字典去请求服务器效率很高。简单示例from dsstore import DSStore store DSStore.open(.DS_Store) for entry in store: if entry.filename: print(entry.filename)5.3 拿到目录列表之后如何顺藤摸瓜解析出文件名列表之后题目才刚刚开始。常见情况是.DS_Store 在站点根目录下解析出来能看到 admin、upload、flag.php 之类的名字但光有文件名还不够你还得猜出对应的完整路径。所以下一步是把文件名列表作为字典逐一请求服务器上的路径。这里我建议多探测几层根目录有 .DS_Storeadmin 子目录下很可能也有一个 .DS_Store层层解析、层层探测能画出一棵完整的网站目录树。CTFHUB 的 .DS_Store 题目一般就是考到这个层面解析根目录文件找到隐藏的 flag 路径访问并获取 flag。有一个坑必须提醒.DS_Store 文件可能不在根目录也可能经过某种编码或截断导致文件名列表不完整。做题时不要只下载一次就完事多几个目录都探测一下。遇到解析不出来的用strings硬核提取字符串往往也有意外收获。6. CTFHUB实战复盘四道题的完整通关流程6.1 网站源码题的标准操作流CTFHUB网站源码这道题整体流程非常清晰。我当时三步走第一步确认目标站点技术栈。访问首页看响应头里的 Server 字段、Set-Cookie、页面生成特征判断是 PHP、Java 还是 Python。第二步扫描备份压缩包。我用 dirsearch 带上常见 zip、tar.gz 字典扫到/website.zip之后先看响应包的 Content-Length确认是个压缩包不是 404 跳转到自定义页面。第三步下载解压。解压后整个项目源码铺在眼前直接全局搜索 flag 关键词最后在一个配置文件里找到了明文 flag。整个过程没用到任何复杂漏洞纯粹是信息收集做到位了。6.2 bak文件题的细节与坑CTFHUBbak文件这道题入口其实非常直白直接访问/index.php.bak就能下载源码。但有几个坑值得说一下。第一个坑下载后直接用浏览器打开浏览器会把 PHP 代码当纯文本显示部分内容可能被折叠或者显示不完整。正确做法是先用 curl 下载到本地再用代码编辑器打开curl http://目标地址/index.php.bak -o index.php.bak第二个坑很多人分不清访问/index.php和/index.php.bak的区别。访问前者时永远看不到源码只有访问后者才能看到纯文本内容因为服务器不会把 .bak 当 PHP 执行而是直接返回文件本体。第三个坑编码问题。如果源文件里混着 BOM 头或者中文注释直接看可能乱码。建议先用file index.php.bak确认格式再用合适的编码打开。6.3 vim缓存题从 .swp 到 flag 的一步之遥CTFHUBvim缓存这道题关键动作是访问/.index.php.swp——注意带点号的隐藏文件。下载下来是个二进制文件。我当时先用vim -r恢复因为交换文件版本兼容问题没成功随后改用 strings 直接提取在输出里看到了完整 PHP 代码以及一个注释掉的 flag 内容。做题技巧如果找到的交换文件后缀是 .swo 而不是 .swp恢复方法完全一样。另外多试几个可能被编辑过的文件比如 flag.php、config.php不要只盯着 index.php。题目既然叫vim缓存说明出题人模拟的就是一个真实开发者在服务器上编辑代码后异常退出的场景顺着这个思路去猜文件名命中率会高很多。6.4 .DS_Store题解析后看到一张完整目录树CTFHUB.DS_Store这道题下载根目录下的/.DS_Store文件用 Python 解析之后能看到里面记录了若干文件条目其中就包括目标 flag 文件的文件名。顺着这个文件名去访问对应路径flag 直接到手。我当时犯过一个有意思的错误第一次解析时程序输出乱码还以为 .DS_Store 文件损坏了后来才发现是自己的解析脚本没处理编码。换成库自带的编码处理逻辑之后文件名列表就清爽了。这个坑提前帮你踩了。6.5 四类文件联动思考做完这四道题再回头看能发现一个一致的内在逻辑猜路径、用对工具、识别格式。猜路径靠经验和字典用对工具靠的是知道什么场景配什么工具识别格式靠的是知识面广度和对二进制文件的敏感度。这四个考点难度是递进的压缩包考扫目录bak 考猜后缀vim 缓存考隐藏文件意识.DS_Store 考系统生态知识。刷完这组题再去看信息泄露模块里其他类型的题目比如 Git 泄露、SVN 泄露思路会顺畅很多因为它们本质上都在做同一件事从被忽略的文件痕迹里还原目标系统的结构。7. 防守视角如何从源头掐断备份文件泄露7.1 服务器配置层面的拦截做过几年运维之后我强烈建议不管你的站点规模多小Web 服务器配置里都应该加一层针对备份文件的拦截规则。Nginx 可以这样加location ~* \.(bak|swp|swo|swn|old|save|orig|~)$ { deny all; } location ~ /\.DS_Store$ { deny all; }Apache 的 .htaccess 也类似FilesMatch \.(bak|swp|old|save|orig|~)$ Require all denied /FilesMatch FilesMatch ^\.DS_Store$ Require all denied /FilesMatch加完之后访问这些路径会直接返回 403。就算线上误留了备份文件外部也看不到内容算是最后一层兜底。但这只能算止血真正的根治还得靠流程。7.2 开发与发布流程规范比服务器拦截更有效的是从流程上杜绝备份文件上线禁止在服务器上直接编辑代码所有改动走测试环境验证后再通过 CI/CD 发布备份不要放在 Web 目录下统一放到对象存储或者内网备份机每次上线前跑一个静态检查脚本自动扫描 Web 目录下的常见备份文件名发现后自动告警给团队定好代码管理规范源码必须进版本库不要用 zip 互相传我见过不少团队开发规范写得像模像样但生产服务器上依旧躺着几个旧 zip。大部分情况不是大家不想遵守而是根本不知道有哪些文件被遗留下来了。所以放一个自动巡检脚本比贴一百遍规定都管用。7.3 定期巡检与检测思路防守不能总是被动得定期用攻击者视角去检查自己的站。思路和做题时完全一样维护一份常见备份文件名列表定期用脚本请求自己的域名比如/www.zip、/backup.tar.gz、/index.php.bak、/.index.php.swp、/.DS_Store任何一个路径返回 200立刻排查是谁上传的、什么时候上传的对返回 200 的文件做内容安全检查确认里面没有泄露敏感配置这种巡检本质上就是在重复 CTF 题目的操作只不过目标换成了自己家的站点。把你自己当成攻击者扫一遍往往比任何安全报告都直观。最后再分享一个做题之外的体会。刷 CTF 题很容易陷入为了刷题而刷题的状态但信息泄露这个模块我始终把它的价值看得很高它培养的是一种好奇心加验证力的习惯。看到一个路径不直接略过而是下意识想后面还有没有东西这种习惯在做开发、做测试、做运维时都会持续受益。如果你正准备按这个思路去挨个刷 CTFHUB 的备份文件下载题建议过程中把每个路径的返回状态和判断记录一下刷完你收获的绝对不只是四道题的分值。