有关php伪协议的一些特性
php://filter
read和write
读文件时触发read
1 | php://filter/read=convert.base64-encode/resource=xxx |
写文件时触发write
1 | php://filter/write=convert.base64-decode/resource=xxx |
向xxx写入base64解码的内容
同时,下面的写法也是合法的:
1 | pHp://filter/read=convert.base64-encode/resource=xxx |
这说明伪协议不区分大小写
如果使用的不是read或者write
,则会报错:
1 | php://filter/abcs=convert.base64-decode/resource=xxx |
如果没有写,则会自动推导是write
还是read
:
1 | php://filter/convert.base64-encode/resource=xxx |
可以使用多个过滤器:
1 | php://filter/read=A|B/resource= |
1 | php://filter/read=A/write=B/resource= |
绕过死亡exit
谈一谈php://filter的妙用 | 离别歌 (leavesongs.com)
1 | php://filter/read=convert.base64-decode/resource=xxx |
这两种协议都会先对内容进行处理,再进行base64的解码
其实就是在解码的过程中,字符<、?、;、>、空格、单双引号
等会被忽略
假如我有一个file_put_contents
1 | $filename = $_GET['filename']; |
此时它会把我们的恶意代码提前写入<?php die("nononon");?>
,导致我们的恶意代码被提前结束
此时我们可以利用php伪协议的特性:
1 | php://filter/write=convert.base64-decode/resource=shell.php |
此时会向shell.php写入伪协议处理后的decode的内容
经过处理后就会变成phpdienononon
加上我们的内容
此时由于base64解码是4字节一组的解码方式,我们需要在前面加上任意字符使得xxxphpdienononon
刚好是四的倍数个长度
此时前面就会被解码成乱码,后面会被正常解码成我们的shell
其他的过滤器:
convert.quoted-printable-encode
打印不可见字符convert.iconv.utf-8.utf-16be
uft8 -> utf16convert.iconv.utf8.utf-7
(可去除等号) utf8 -> utf7convert.iconv.ASCII.UCS-2BE
ascii -> UCS-2BEstring.strip_tags
去除html和php的标签
…
url编码
php会对过滤器decode
多一次,所以可以用url编码绕过(?)
1 | php://filter/read=conv%65rt.b%61se64-encode/resource=flag.php |