如何利用PHP类型混淆绕过校验
TOPIC SOURCE
Bugku-前女友(SKCTF)
在 PHP 的弱类型体系里,变量的实际类型往往会在运行时被隐式转换,这种“类型混淆”恰是攻击者绕过业务校验的突破口。只要能够让目标函数接受与预期不同的值,却仍然满足比较逻辑,就能在不触发异常的前提下取得非法权限。
类型混淆的原理
PHP 在比较运算符(==、!=)以及字符串函数(strcmp、md5)上会执行自动类型转换。例如,数组在参与字符串拼接时会被强制转为字符串“Array”,而数值型字符串在与整数比较时会被当作整数处理。这种行为让原本看似严密的校验在特定输入下产生歧义。
利用数组与标量的自动转换
最常见的手段是把标量参数伪装成数组,或让数组元素携带特定的子值。因为 PHP 在 $_GET、$_POST 等全局数组中会自动把相同键名的多值解析为数组形式,而后端代码若直接使用 $var 而未做类型检测,就会触发混淆。
<?php
if (isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])) {
$v1 = $_GET['v1']; // 可能是数组
$v2 = $_GET['v2']; // 可能是数组
$v3 = $_GET['v3']; // 可能是数组
// $v1 != $v2 在数组情况下会比较引用,而非内容
if ($v1 != $v2 && md5($v1) == md5($v2)) {
// strcmp 返回 0 表示相等,!0 为 true
if (!strcmp($v3, $flag)) {
echo $flag;
}
}
}
?>
绕过 MD5 相等校验的技巧
MD5 本身是对二进制数据做散列,但在 PHP 中对数组调用 md5 时会先将数组转为字符串“Array”。因此只要让 $v1 与 $v2 同时是数组,即使内部元素完全不同,md5($v1) 与 md5($v2) 仍会得到相同的散列值,从而满足相等检查。
- 将标量参数改写为
param[]=value形式,强制生成数组。 - 利用
==与!=的宽松比较,制造“相等但不相同”的情形。 - 在
strcmp前加入!,把返回 0(相等)转为布尔 true。
防御建议
面对类型混淆的风险,代码审计应从两方面入手:一是对所有外部输入执行显式类型校验,使用 is_string()、is_int() 等函数拒绝数组;二是避免在安全关键路径直接使用宽松比较,改用全等运算符 === 并对比前统一强制类型。

参与讨论
暂无评论,快来发表你的观点吧!