探索php://filter在实战当中的奇技淫巧(上)

摘要: 在渗透测试或漏洞挖掘的过程中,我们经常会遇到php://filter结合其它漏洞比如文件包含、文件读取、反序列化、XXE等进行组合利用,以达到一定的攻击效果,拿到相应的服务器权限

前言

在渗透测试或漏洞挖掘的过程中,我们经常会遇到php://filter结合其它漏洞比如文件包含、文件读取、反序列化、XXE等进行组合利用,以达到一定的攻击效果,拿到相应的服务器权限。

最近看到php://filter在ThinkPHP反序列化中频繁出现利用其相应构造可以RCE,那么下面就来探索一下关于php://filter在漏洞挖掘中的一些奇技淫巧。

php://filter

在探索php://filter在实战当中的奇技淫巧时,一定要先了解关于php://filter的原理和利用。

php://filter是一种元封装器,是PHP中特有的协议流,设计用于数据流打开时的筛选过滤应用,作用是作为一个“中间流”来处理其他流。

php://filter目标使用以下的参数作为它路径的一部分。复合过滤链能够在一个路径上指定。

参数

使用

通过参数去了解php://filter的使用

  • 测试代码

<?php
    $file1 = $_GET['file1'];
    $file2 = $_GET['file2'];
    $txt = $_GET['txt'];    echo file_get_contents($file1);
    file_put_contents($file2,$txt);
?>
  • 读取文件

payload:

index.php?file1=php://filter/resource=file.txt
index.php?file1=php://filter/read=convert.base64-encode/resource=file.txt
测试结果:

  • 写入文件

payload:

index.php?file2=php://filter/resource=test.txt&txt=Qftm
index.php?file2=php://filter/write=convert.base64-encode/resource=test.txt&txt=Qftm
测试结果:

过滤器

String Filters

String Filters(字符串过滤器)每个过滤器都正如其名字暗示的那样工作并与内置的 PHP 字符串函数的行为相对应。

string.rot13

(自 PHP 4.3.0 起)使用此过滤器等同于用 str_rot13()函数处理所有的流数据。

string.rot13对字符串执行 ROT13 转换,ROT13 编码简单地使用字母表中后面第 13 个字母替换当前字母,同时忽略非字母表中的字符。编码和解码都使用相同的函数,传递一个编码过的字符串作为参数,将得到原始字符串。

  • Example #1 string.rot13

<?php
$fp = fopen('php://output', 'w');
stream_filter_append($fp, 'string.rot13');
fwrite($fp, "This is a test.n");
/* Outputs:  Guvf vf n grfg.   */
?>

string.toupper

(自 PHP 5.0.0 起)使用此过滤器等同于用 strtoupper()函数处理所有的流数据。

string.toupper 将字符串转化为大写

  • Example #2 string.toupper

<?php
$fp = fopen('php://output', 'w');
stream_filter_append($fp, 'string.toupper');
fwrite($fp, "This is a test.n");
/* Outputs:  THIS IS A TEST.   */
?>

string.tolower

(自 PHP 5.0.0 起)使用此过滤器等同于用 strtolower()函数处理所有的流数据。

string.toupper 将字符串转化为小写

  • Example #3 string.tolower

<?php
$fp = fopen('php://output', 'w');
stream_filter_append($fp, 'string.tolower');
fwrite($fp, "This is a test.n");
/* Outputs:  this is a test.   */
?>

string.strip_tags

(PHP 4, PHP 5, PHP 7)(自PHP 7.3.0起已弃用此功能。)

使用此过滤器等同于用 strip_tags()函数处理所有的流数据。可以用两种格式接收参数:一种是和 strip_tags()函数第二个参数相似的一个包含有标记列表的字符串,一种是一个包含有标记名的数组。

string.strip_tags从字符串中去除 HTML 和 PHP 标记,尝试返回给定的字符串 str 去除空字符、HTML 和 PHP 标记后的结果。它使用与函数 fgetss() 一样的机制去除标记。

Note:HTML 注释和 PHP 标签也会被去除。这里是硬编码处理的,所以无法通过 allowable_tags 参数进行改变。
  • Example #4 string.strip_tags

<?php
$fp = fopen('php://output', 'w');
stream_filter_append($fp, 'string.strip_tags', STREAM_FILTER_WRITE, "<b><i><u>");
fwrite($fp, "<b>bolded text</b> enlarged to a <h1>level 1 heading</h1>n");
fclose($fp);
/* Outputs:  <b>bolded text</b> enlarged to a level 1 heading   */
$fp = fopen('php://output', 'w');
stream_filter_append($fp, 'string.strip_tags', STREAM_FILTER_WRITE, array('b','i','u'));
fwrite($fp, "<b>bolded text</b> enlarged to a <h1>level 1 heading</h1>n");
fclose($fp);
/* Outputs:  <b>bolded text</b> enlarged to a level 1 heading   */
?>

Conversion Filters

Conversion Filters(转换过滤器)如同 string. 过滤器,convert. 过滤器的作用就和其名字一样。转换过滤器是 PHP 5.0.0 添加的。

convert.base64

convert.base64-encode和 convert.base64-decode使用这两个过滤器等同于分别用 base64_encode()和 base64_decode()函数处理所有的流数据。 convert.base64-encode支持以一个关联数组给出的参数。如果给出了 line-length,base64 输出将被用 line-length个字符为 长度而截成块。如果给出了 line-break-chars,每块将被用给出的字符隔开。这些参数的效果和用 base64_encode()再加上 chunk_split()相同。

  • Example #1 convert.base64-encode & convert.base64-decode

<?php
$fp = fopen('php://output', 'w');
stream_filter_append($fp, 'convert.base64-encode');
fwrite($fp, "This is a test.n");
fclose($fp);
/* Outputs:  VGhpcyBpcyBhIHRlc3QuCg==  */

$param = array('line-length' => 8, 'line-break-chars' => "rn");
$fp = fopen('php://output', 'w');
stream_filter_append($fp, 'convert.base64-encode', STREAM_FILTER_WRITE, $param);
fwrite($fp, "This is a test.n");
fclose($fp);
/* Outputs:  VGhpcyBp
          :  cyBhIHRl
          :  c3QuCg==  */
$fp = fopen('php://output', 'w');
stream_filter_append($fp, 'convert.base64-decode');
fwrite($fp, "VGhpcyBpcyBhIHRlc3QuCg==");
fclose($fp);
/* Outputs:  This is a test.  */
?>

convert.quoted

convert.quoted-printable-encode和 convert.quoted-printable-decode使用此过滤器的 decode 版本等同于用 quoted_printable_decode()函数处理所有的流数据。没有和 convert.quoted-printable-encode相对应的函数。 convert.quoted-printable-encode支持以一个关联数组给出的参数。除了支持和 convert.base64-encode一样的附加参数外, convert.quoted-printable-encode还支持布尔参数 binary和 force-encode-first。 convert.base64-decode只支持 line-break-chars参数作为从编码载荷中剥离的类型提示。

  • Example #2 convert.quoted-printable-encode & convert.quoted-printable-decode

<?php
$fp = fopen('php://output', 'w');
stream_filter_append($fp, 'convert.quoted-printable-encode');
fwrite($fp, "This is a test.n");
/* Outputs:  =This is a test.=0A  */
?>
convert.iconv.*
这个过滤器需要php支持iconv,而iconv是默认编译的。使用convert.iconv.*过滤器等同于用iconv函数处理所有的流数据。
Note 该过滤在PHP中文手册里面没有标注,可查看英文手册

https://www.php.net/manual/en/filters.convert.php

convery.iconv.*的使用有两种方法

convert.iconv.<input-encoding>.<output-encoding> 
or 
convert.iconv.<input-encoding>/<output-encoding>
  • iconv函数

(PHP 4 >= 4.0.5, PHP 5, PHP 7)

iconv — 字符串按要求的字符编码来转换

说明

iconv ( string $in_charset , string $out_charset , string $str ) : string

将字符串 str 从 in_charset 转换编码到 out_charset

参数

in_charset
  输入的字符集。

out_charset
  输出的字符集。如果你在 out_charset 后添加了字符串 //TRANSLIT,将启用转写(transliteration)功能。这个意思是,当一个字符不能被目标字符集所表示时,它可以通过一个或多个形似的字符来近似表达。 如果你添加了字符串 //IGNORE,不能以目标字符集表达的字符将被默默丢弃。 否则,会导致一个 E_NOTICE并返回 FALSE。
 
str
    要转换的字符串。
返回值
返回转换后的字符串, 或者在失败时返回 `FALSE`。

Example #1 iconv

image.png

Example #2 convert.iconv.*

image.png

支持的字符编码有一下几种(详细参考官方手册

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*
、、、、、、、
、、、、、、、

Compression Filters

虽然 压缩封装协议提供了在本地文件系统中 创建 gzip 和 bz2 兼容文件的方法,但不代表可以在网络的流中提供通用压缩的意思,也不代表可以将一个非压缩的流转换成一个压缩流。对此,压缩过滤器可以在任何时候应用于任何流资源。

Note: 压缩过滤器 不产生命令行工具如 gzip的头和尾信息。只是压缩和解压数据流中的有效载荷部分。

zlib. 压缩过滤器自 PHP 版本 5.1.0起可用,在激活 zlib的前提下。也可以通过安装来自 » PECL的 » zlib_filter包作为一个后门在 5.0.x版中使用。此过滤器在 PHP 4 中 不可用*。

bzip2. 压缩过滤器自 PHP 版本 5.1.0起可用,在激活 bz2支持的前提下。也可以通过安装来自 » PECL的 » bz2_filter包作为一个后门在 5.0.x版中使用。此过滤器在 PHP 4 中 不可用*。

详细细节参考官方文档

https://www.php.net/manual/zh/filters.compression.php

Encryption Filters

mcrypt.*和 mdecrypt.*使用 libmcrypt 提供了对称的加密和解密。这两组过滤器都支持 mcrypt 扩展库中相同的算法,格式为 mcrypt.ciphername,其中 ciphername是密码的名字,将被传递给 mcrypt_module_open()。有以下五个过滤器参数可用:

详细细节参考官方文档

https://www.php.net/manual/zh/filters.encryption.php

在了解了有关php://filter的原理和利用之后,下面开始探索php://filter在漏洞挖掘中的奇妙之处。


原文地址:https://www.anquanke.com/post/id/202510

上一篇:探索php://filter...
下一篇:内网渗透之应用层隧道技术(上...