1.这题看前端js代码可以发现:
$('#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;
})
首先看见calc.php,我们可以发现能打开爆出源码:
看wp时发现还有另一种http走私的方法爆源码:
http走私:
我们要做的就是首先绕过黑名单,只要eval命令执行可以执行我们的的输入,我们就能通过读函数来获取flag了。
先看黑名单(就是源码里提示的waf):
/i (忽略大小写)
/g (全文查找出现的所有匹配字符)
/m (多行查找)
/gi(全文查找、忽略大小写)
/ig(全文查找、忽略大小写)
这个怎么绕过?答案是php的字符串解析特性。
PHP的字符串解析特性是什么?
答: PHP需要将所有参数转换为有效的变量名,因此在解析查询字符串时,它会做两件事:1.删除空白符 2.将某些字符转换为下划线(包括空格)
可以构造payload:
? num=1;var_dump(scandir(chr(47)))
为什么要在num前加一个空格?
答:因为看正则匹配规则,waf不允许num变量传递字母,可以在num前加个空格,这样waf就找不到num这个变量了,因为现在的变量叫“(空格)num”,而不是“num”。(又学到一种绕waf手段)但php在解析的时候,会先把空格给去掉,仍旧是num参数,这样我们的代码还能正常运行,还上传了非法字符。
总而言之:
当waf拦截你变量的内容的时候,你构造了一个不是num的变量绕过了waf,但php因为解析特性却可以将这个变量当成num变量执行,导致命令执行。不过这样好像并不是waf读取不了该变量了,仍然需要绕过其规则中对字符的过滤,即通过char()函数转ascii码构造命令来命令执行了。
payload:
?%20num=1;var_dump(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)))
可以学习这篇文章,就php函数解析剖析研究的很深:
https://www.freebuf.com/articles/web/213359.html
其他参考wp:
https://www.cnblogs.com/yunqian2017/p/13306348.html
https://www.cnblogs.com/chrysanthemum/p/11757363.html