本文仅用于网络安全技术学习与授权测试交流。任何未经授权使用文中技术的行为均与作者无关,请务必遵守法律法规,获得许可后方可进行渗透测试。
目录
[1. 路径穿越读取系统文件](#1. 路径穿越读取系统文件)
[2. 读取 PHP 源码](#2. 读取 PHP 源码)
[3. 使用编码绕过过滤](#3. 使用编码绕过过滤)
[4. 利用空字节截断(旧版 PHP)](#4. 利用空字节截断(旧版 PHP))
[5. 利用 ZIP 或 Phar 协议(某些语言)](#5. 利用 ZIP 或 Phar 协议(某些语言))
[1. 白名单限制](#1. 白名单限制)
[2. 路径过滤与规范化](#2. 路径过滤与规范化)
[3. 隐藏真实路径](#3. 隐藏真实路径)
[4. 文件权限最小化](#4. 文件权限最小化)
[5. 禁用危险函数或协议](#5. 禁用危险函数或协议)
[6. 输出强制下载](#6. 输出强制下载)
[八、实战 CTF 常用 Payload](#八、实战 CTF 常用 Payload)
[一、CTFHub 相关题目](#一、CTFHub 相关题目)
[二、BUUCTF 相关题目](#二、BUUCTF 相关题目)
一、什么是文件下载漏洞
文件下载漏洞 是指 Web 应用程序在实现文件下载功能时,对用户传入的文件路径参数未进行严格过滤 ,导致攻击者可以任意下载服务器上的敏感文件(如源代码、配置文件、数据库备份、系统密码文件等)。
这类漏洞常出现在提供文件下载的页面,例如:
-
download.php?filename=report.pdf -
file.jsp?path=/uploads/guide.doc
攻击者通过修改 filename 或 path 参数,尝试读取服务器任意位置的文件。
二、漏洞产生的原因
典型的不安全代码(PHP 示例):
$filename = $_GET['filename']; $filepath = "/var/www/downloads/" . $filename; header('Content-Type: application/octet-stream'); readfile($filepath);
-
直接拼接用户输入 :未过滤
..、/、\等路径穿越字符。 -
未限制基础目录 :没有使用
realpath()或open_basedir限制可访问范围。 -
未进行白名单校验:允许用户任意指定文件名。
三、漏洞危害
| 文件类型 | 典型路径 | 泄露信息 |
|---|---|---|
| 源代码 | index.php、config.php、inc/*.inc |
数据库密码、API密钥、业务逻辑漏洞 |
| 配置文件 | /etc/passwd、/etc/shadow(需root)、web.config、.htaccess |
系统用户、服务器配置 |
| 日志文件 | /var/log/apache2/access.log、error.log |
访问记录、错误信息、后台路径 |
| 数据库备份 | backup.sql、*.sql、*.dump |
用户数据、管理员密码哈希 |
| 敏感数据 | /proc/self/environ、/proc/net/arp、/root/.bash_history |
环境变量、内网信息、命令历史 |
| 其他 Web 应用文件 | ../其他目录/file.txt |
跨目录读取 |
四、典型攻击示例
1. 路径穿越读取系统文件
http://target.com/download.php?file=../../../../etc/passwd
如果服务器为 Linux 且 Web 用户有读取权限,则返回 /etc/passwd。
2. 读取 PHP 源码
http://target.com/download.php?file=../config.php
直接下载 config.php,获取数据库账号密码。
3. 使用编码绕过过滤
-
URL 编码:
%2e%2e%2f→../ -
双写绕过:
....//→ 过滤后剩../ -
绝对路径:
/etc/passwd(若未过滤斜杠)
4. 利用空字节截断(旧版 PHP)
download.php?file=../../etc/passwd%00.jpg
如果后端强制添加 .jpg,%00 可截断后缀。
5. 利用 ZIP 或 Phar 协议(某些语言)
// 如果允许 zip:// 或 phar:// download.php?file=zip://uploads/evil.zip%23shell.php
五、漏洞检测方法
-
手工测试 :修改下载参数为
../../etc/passwd,观察返回内容。 -
模糊测试:使用 Burp Intruder 批量尝试常见敏感文件路径。
-
代码审计 :搜索文件读取函数(
readfile、file_get_contents、fopen、File.ReadAllText等),检查参数是否用户可控。
六、防御措施
1. 白名单限制
$allow_files = ['report.pdf', 'guide.doc', 'manual.txt']; if(!in_array($_GET['file'], $allow_files)) { die('非法文件'); }
2. 路径过滤与规范化
$base = '/var/www/downloads/'; $file = realpath($base . $_GET['file']); if($file === false || strpos($file, $base) !== 0) { die('非法路径'); } readfile($file);
3. 隐藏真实路径
-
将文件 ID 映射到真实路径(如数据库存储
id->path)。 -
使用随机化文件名存储(如 UUID),对外只暴露 ID。
4. 文件权限最小化
-
Web 用户不应有读取非 Web 目录文件的权限(如通过
open_basedir限制)。 -
敏感文件(如配置文件)应设置仅应用账户可读,Web 用户不可读。
5. 禁用危险函数或协议
-
PHP 中禁用
zip://、phar://等(非必要)。 -
设置
allow_url_fopen = Off(如果不需要远程读取)。
6. 输出强制下载
- 设置正确的
Content-Type和Content-Disposition: attachment,避免文件内容直接在浏览器显示(但不能阻止路径遍历)。
七、与文件包含漏洞的区别
| 对比 | 文件下载漏洞 | 文件包含漏洞 |
|---|---|---|
| 目的 | 读取文件内容(下载) | 将文件内容作为脚本执行 |
| 函数 | readfile、file_get_contents、fopen |
include、require |
| 后果 | 信息泄露(源码、配置、数据) | 代码执行(Getshell) |
| 典型防御 | 白名单、路径限制、权限最小化 | 白名单、禁用远程包含、路径限制 |
八、实战 CTF 常用 Payload
| 目标 | Payload 示例 |
|---|---|
读取 /etc/passwd |
?file=../../../../etc/passwd |
读取 index.php 源码 |
?file=index.php(直接下载) |
读取 config.php(上级目录) |
?file=../config.php |
| 使用编码绕过 | ?file=%2e%2e%2f%2e%2e%2fetc/passwd |
| 绝对路径(Linux) | ?file=/etc/passwd |
| 绝对路径(Windows) | ?file=C:\Windows\win.ini |
| 读取 Web 日志 | ?file=../../../../var/log/apache2/access.log |
| 读取进程环境变量 | ?file=../../../../proc/self/environ |
九、总结
文件下载漏洞本质是 路径遍历(Path Traversal)+ 文件读取 的组合。开发者在实现下载功能时,必须对用户输入进行严格限制,永远不要直接拼接文件路径。采用白名单、映射 ID、路径规范化是最有效的防御手段。
十、靶场演示推荐
下面罗列了一些靶场示例,可以去我的ctf解题专栏查看解题思路
一、CTFHub 相关题目
CTFHub 技能树中明确划分了 "备份文件下载" 和 "目录遍历" 两个章节,专门考察文件下载漏洞。
| 题目分类 | 题目名称(考点) | 简要说明 |
|---|---|---|
| 备份文件下载 | 网站源码 (/www.zip 等) |
访问常见备份文件(.zip、.tar、.rar)下载源码。 |
bak 文件 (index.php.bak) |
通过访问 index.php.bak 等备份文件获得源码。 |
|
vim 缓存 (index.php.swp) |
vim 意外退出留下的缓存文件,下载后可恢复源码。 | |
.DS_Store |
macOS 目录文件泄露,可获取文件列表。 | |
| 目录遍历 | 任意文件读取 | 通过 ?file=../../../../etc/passwd 等参数读取系统文件。 |
| 信息泄露 | 其他信息泄露(如 .git、.svn) |
虽然属于信息泄露,但也常通过文件下载方式获取。 |
二、BUUCTF 相关题目
BUUCTF 中没有独立的"文件下载"分类,但以下题目涉及下载备份文件、读取源码或任意文件读取。
| 题目名称 | 考点(文件下载相关) | 利用方式简述 |
|---|---|---|
[极客大挑战 2019]Secret File |
文件包含 + php://filter 读取源码 |
通过 php://filter 伪协议读取 flag.php 的 Base64 编码内容。 |
[极客大挑战 2019]PHP |
/www.zip 备份文件泄露 |
访问 /www.zip 下载网站全部源码,审计后反序列化获取 flag。 |
[ACTF2020 新生赛]BackupFile |
index.php.bak 备份文件 |
访问 /index.php.bak 获得源码,发现弱比较漏洞。 |
[护网杯 2018]easy_tornado |
任意文件读取(结合 SSTI) | 通过模板注入获取 cookie_secret,然后构造 filehash 读取 /fllllllllllag。 |
[BJDCTF2020]EasySearch |
.swp 缓存文件泄露 |
访问 index.php.swp 恢复源码,获得后台密码。 |
[GXYCTF2019]禁止套娃 |
.git 源码泄露 |
使用 git restore 或工具下载源码,审计发现 RCE 漏洞。 |
[RoarCTF 2019]Easy Java |
任意文件读取(Java Web) | 通过 filename=/WEB-INF/web.xml 读取配置文件,进一步下载 classes 下的 class 文件。 |
[BSidesCF 2020]Had a bad day |
文件包含 + 伪协议读取 | 利用 php://filter 读取 index.php 源码。 |