Background
Kit师傅发了我一道web题 但是据我开始调到结束就不到半小时 环境就关了,还好存了份本地,看了看发现解法有很多
Source-code
<?php
highlight_file(__FILE__);
error_reporting(0);
if (isset($_GET['print'])) {
if (!empty($_GET['print'])){
$printValue= strtolower($_GET['print']);
$blocked = array("cat", "more" ,"readfile", "fopen", "file_get_contents", "file", "SplFileObject" );
$special_block= "nc";
$$special_block= "./flag.txt";
foreach ($blocked as $value) {
if (strpos($printValue, $value) || preg_match('/\bsystem|\bexec|\bbin2hex|\bassert|\bpassthru|\bshell_exec|\bescapeshellcmd| \bescapeshellarg|\bpcntl_exec|\busort|\bpopen|\bflag\.txt|\bspecial_block|\brequire|\bscandir|\binclude|\bhex2bin|\$[a-zA-Z]|[#!%^&*_+=\-,\.:`|<>?~\\\\]/i', $printValue)) {
$printValue="";
echo "<script>alert('Bad character/word ditected!');</script>";
break;
}
}
eval($printValue . ";");
}
}
?>
分析与调试分析
ban了好多函数 甚至连scandir这种无参数rce 和异或取反号都ban了 但比较有意思的点是这个$$可变变量表示flag.txt
调试方法 在命令行 执行php -S 0:8001
solve 1
因为有eval方法可以执行 他虽然ban掉关键字样 但我们可以考虑以前python沙盒逃逸的思路 切片或者reverse
php里面可以用strreverse 来执行
payload:eval(strrev(";)sl(metsys"));
即可执行列目录等操作
solve 2
我们知道 php是支持动态执行代码的
就像这样 但是正则里$[a-zA-Z] 防止我们直接对变量进行操作
但实际上 在php5.x以上
就可以支持${}这种花括号调用
可以看到虽然报错了 但还是成功执行了命令
那我们可以看到$blocked变量里面是一个数组形式的读文件的函数列表
如果我们选择正确的函数 然后再用$nc这个变量
经过查看只有readfile能读取并回显'./flag.txt'文件
最终payload ${blocked}[2](${nc})
solve 3
是我在一个微信公众号上看到的思路
end(getallheaders())
用这种无参数的方式 然后在头里面执行函数也是可以的
后记
作为一个ctfer,还是要思路灵活 多看多审多写代码