未命名
PHP 代码审计题解题思路
代码结构分析
这道题是一个多层条件绕过的CTF题目,需要依次绕过三层条件才能获取 $flag。
┌─────────────────────────────────────────┐
│ 第一层:变量 a 的校验 │
├─────────────────────────────────────────┤
│ 第二层:b1/b2 MD5绕过 │
├─────────────────────────────────────────┤
│ 第三层:c1/c2 MD5绕过 │
├─────────────────────────────────────────┤
│ 拿到 flag │
└─────────────────────────────────────────┘
第一层:$_POST['a'] 的绕过
原始条件:
!preg_match('/[0-9]/', $_POST['a']) && intval($_POST['a'])要求:
a中不能包含数字0-9intval(a)必须为真(非零)
绕过方法:使用小数
a = 0.1
没有数字字符 →
preg_match不匹配intval("0.1")→0(PHP会截断小数点前的部分)
第二层:b1/b2 MD5 强等于绕过
原始条件:
$_POST['b1'] != $_POST['b2'] && md5($_POST['b1']) === md5($_POST['b2'])
要求:
两个不同的字符串,它们的 MD5 值必须完全相等(强类型比较)
绕过方法:利用 MD5 碰撞(0e开头的字符串)
b1 = 240610708 b2 = QNKCDZO
| 字符串 | MD5 值 |
|---|---|
240610708 | 0e462097431906509019562988736854 |
QNKCDZO | 0e830400451993494058024219903391 |
都以
0e开头 → PHP 视为科学计数法0 × 10^n = 00 === 0→ 严格比较通过且两个原字符串不相等
第三层:c1/c2 MD5 弱等于绕过
原始条件:
$_POST['c1'] != $_POST['c2'] && is_string($_POST['c1']) && is_string($_POST['c2']) && md5($_POST['c1']) == md5($_POST['c2'])
要求:
两个不同的字符串,MD5 值弱相等即可
绕过方法:使用字符串形式 0e 开头的 MD5
c1 = 0e215962017 c2 = 0e2912424762227764
| 字符串 | MD5 值 |
|---|---|
0e215962017 | 0e934533575974867840142512.... |
0e2912424762227764 | 0e077632083503616920639.... |
PHP 的
==比较会自动将0e数字转换为0两个 MD5 值都被转为
0 == 0→ 通过
最终 Payload
| 参数 | 值 |
|---|---|
a | 0.1 |
b1 | 240610708 |
b2 | QNKCDZO |
c1 | 0e215962017 |
c2 | 0e2912424762227764 |
请求方式: POST 请求
核心考点总结
| 层级 | 考点 | PHP 特性 |
|---|---|---|
| 第一层 | 正则绕过 + intval 特性 | 小数点不影响 intval();正则 /\d/ 只匹配数字 |
| 第二层 | MD5 强类型比较 | === 会比较类型,0e... 和 0e... 都转为 float 0 才相等 |
| 第三层 | MD5 弱类型比较 | == 会类型转换,0e数字 自动转为科学计数法 0 |
暂无评论
发表评论