[PHP底层]关于php://filter的分析

Posted Y4tacker

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[PHP底层]关于php://filter的分析相关的知识,希望对你有一定的参考价值。

写在前面

慢慢不太想写博客了,很多东西都忙不过来,学的很多,今天抽出空来还是督促自己写一篇,灵感来源于刚刚在网上看到的一篇wp,https://xz.aliyun.com/t/10446,不得不说现在比赛可真多哈,小伙伴们也别太经常打,多做点实际的东西

关于php://filter的处理的一些简单解释

这里面呢,有几个比较关键的,一个是需要能获取到文件流(也就是我们后面常常写的resource=xxx.txt),另一个是可选的,就是是否使用其他的编码过滤器,有了这两个东西我们就能配合伪协议去做一些神奇的东西了

php://filter常规流程分析

大家在网上看的最多的也是php://filter/read=convert.base64-encode/resource=1.php
那它发生了什么,我们具体来看看,在ext\\standard\\php_fopen_wrapper.c#php_stream_url_wrap_php下一个断点
前六个是php://没毛病,指针移六位

接下来,由于是filter我们进入分支

给pathdup赋值,内容是指针向右移动六位后,也就是/read=convert.base64-decode/resource=1.php

接下来开始准备获取文件流了,上图可以看到获取从/resource开始的字符串,因此p就是/resource=1.php
接下来比较重要的地方是从指针+10的地方,也就是1.php当中获取文件流(至于为什么加10,那是因为/resource=长度是10)

跟进去,这里有一个zend_resolve_path的函数,这个支持用目录穿越的方式进行拼接组合路径,如这个函数名所说,会重新连接返回你一个绝对路径,这里就不带大家更深入为什么了,简单来说会获取你当前的目录路径再与1.php拼接后返回一个绝对路径,当然记住我说的支持路径穿越这很重要,这很重要

之后让*p值为\\0,也就是当前指针指向位置赋值为\\0,我们知道c中字符串结尾是\\0,因此不难想到这就是简单的清空字符串,接着对其重新赋值

因为这个php_strtok_r函数跟进去以后比较复杂,那我简单搜索一下php_strtok_r,虽然没搜到但看这个能猜到意思是用于分割字符串,结合后面的while可以看出,是一个不断遍历分割后字符串的过程

接下来,由于是read=开头进入下面php_stream_apply_filter_list函数,当然说一个题外话,这里不需要read=或者write=都行,php自己会判断,也就是为什么有第三个分支else

进去后又是这个函数,但结合后面不难猜到,这按照|分隔符创建多个过滤器

现在整个流程也清楚了

关于exp的分析

可以看到exp为php://filter/resource=./convert.base64-decode/../1.php,理解了我上面的过程,这个exp其实都不需要跟入动态调试分析了,这里直接简单说一下
首先是必须要能获取到文件流,还记得我说的吗这个函数中使用了zend_resolve_path去重新连接路径,我们现在resource=后面是./convert.base64-decode/../1.php,连接后也就是当前运行文件路径/./convert.base64-decode/../1.php,最终就是当前运行文件路径/1.php

第二部分就是是否有过滤器,有就添加上去了,记得怎么获取的吗,filter字符后面的部分用/分割
也就是/resource=./convert.base64-decode/../1.php
因此就是遍历寻找正确的过滤器进行添加

resource=.
convert.base64-decode
..
1.php

整个流程结束

题外话

多提一句,至于是怎么判断有没有这个过滤器的,我的版本是php7.2.9,这里面是靠hash去判断的,还有就是之前很多时候我们对过滤器进行二次编码也是有原因的,如图所示

以上是关于[PHP底层]关于php://filter的分析的主要内容,如果未能解决你的问题,请参考以下文章

Web安全php://filter 的浅略底层分析

安全-php://filter文件包含分析(bugku)

php协议流分析

PHP Filter 函数

雷林鹏分享:PHP Filter 函数

php meta_filter.php