[RoarCTF 2019]Easy Calc-3.23BUUCTF练习day5(2)
解题过程
查看源码
发现calc.php页面,访问一下
分析代码
首先获取$_GET['num']
的值并赋给变量$str
。然后定义了一个黑名单数组$blacklist
,包含了一系列被禁止的字符或转义字符,如空格、制表符、换行符、单引号、双引号、反引号、方括号、美元符号、反斜杠和脱字符号
接下来是一个foreach循环,遍历黑名单中的每一个元素。对于每个被禁止的字符$blackitem
,使用preg_match
函数和正则表达式来检查$str
中是否包含该字符。正则表达式中的/m
修饰符表示多行模式,如果发现任何黑名单中的字符存在,就会调用die("what are you want to do?");
终止脚本执行,并显示提示信息
如果通过了所有黑名单检查,最后一行代码是eval('echo '.$str.';');
,这里将输入的$str
拼接到echo
语句中,并通过eval()
函数执行
思路
通过多次尝试,发现一输入字符,就会被禁止访问
而输入数字,却可以正常回显
那么想起刚刚查看源码信息却没有使用的waf防火墙,应该是waf的原因不能输入字符
用于我们需要输入字符构造命令,所以必须想要绕过waf
PHP字符串解析特性绕过WAF
PHP需要将所有参数转换为有效变量名,因此在解析查询字符串时,它会做两件事:1,删除空白字符;2,将某些字符转换为下划线(包括空格)
因为num不可以传入字母,但是我们在num参数之前添加一个空格(? num=),这样在PHP的语言特性下会默认删除这个空格,但是WAF会因为这个空格导致检测不到num这个参数,最终导致WAF被绕过。
绕过了waf,那么就剩下构造payload找出flag了
在此过程中需要三个函数
- scandir()列出 参数目录 中的文件和目录,从而找到flag在哪里
- var_dump()输出一个或多个表达式的结构信息,包括表达式的类型与值(反正输出的信息很详细)
- file_get_contents()输出文件的具体内容,把整个文件读入一个字符串中,确实也可以用include()函数绕过
步骤
在刚刚的代码中知道过滤了/(反斜杠)需要使用chr绕过(chr是什么?chr()里头是1-255的整数数字,其是对应ascii码值。也就是说chr(47)也就是等价于 /)
payload是? num=var_dump(scandir(chr(47)))
列出根目录下所有信息
找到flag的具体名称f1agg
payload是? num=var_dump(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)))
也就是?num=var_dump(file_get_concents(/f1agg))其中.是PHP中的字符拼接符号,目的将/f1agg拼接起来