php类型juggling漏洞源于弱比较(==)引发的隐式类型转换,可绕过身份校验、权限判断等逻辑,需定位可控输入与硬编码/数据库值的比较点,结合科学计数法、前导空格、数组等构造触发路径,并验证后续权限提升或敏感操作是否被执行。

在PHP框架审计中发现类型 juggling 漏洞,意味着你已定位到一处使用弱比较(==)而非严格比较(===)的关键逻辑点,该点可能被用于绕过身份校验、权限判断或输入过滤。这类漏洞不依赖外部函数调用,而是利用PHP底层类型转换规则实现逻辑偏差,必须结合具体上下文反推触发路径。
确认是否存在可利用的弱比较链
打开目标框架的认证/校验模块(如LoginController、AuthMiddleware、UserValidator等),全局搜索==、!=、strcasecmp(注意:它返回0表示相等,但参数若为数组会返回NULL)、in_array()(未设第三个参数时默认弱比较)。特别关注用户输入经$_GET、$_POST、$_REQUEST进入后直接参与比较的位置。
找到类似if ($input == $expected)的语句后,立即检查左右两侧变量是否都可控:左侧通常来自用户输入(如$_POST['token']),右侧若是硬编码字符串(如'admin')或数据库查出的字段(如$user['role']),则具备分析基础。
【关键前提】必须确保比较前双方未被强制类型转换(如(string)$input或intval($expected)),否则juggling行为被提前截断。
构造能触发类型转换的输入组合
方法一:科学计数法绕过数字校验
当代码写成if ($_POST['id'] == 0)且$id来自URL参数时,提交id=0e123即可使表达式为true——因为PHP将"0e123"解析为浮点数0,与整数0弱比较相等。同理,"0e999999999"也成立。
方法二:前导空格+数字字符串绕过白名单
若校验逻辑为if (in_array($_POST['type'], ['1', '2', '3']))且未启用strict模式,传入type= 1(带空格)仍会命中——in_array在弱比较下会把" 1"转为整数1再匹配。
方法三:数组绕过字符串等值判断
当代码写成if ($_POST['key'] == 'secret123')时,传入key[]=1会使$_POST['key']变为数组,而数组与字符串比较结果恒为false;但若后续逻辑存在if (!$_POST['key'])或empty($_POST['key']),数组会被判为非空,从而跳过错误分支——这种“误判”常出现在防御性校验的else缺失处。
注意:is_numeric("404a")返回false,但"404a" == 404却为true,这种不一致性正是juggling漏洞的温床。
验证漏洞实际影响范围
第一步:定位校验失败后的代码流向
跟踪if ($input == $expected)所在分支,看其后是否直接控制权限提升(如$_SESSION['is_admin'] = true)、跳转(header('Location: /admin'))或执行敏感操作(eval()、file_put_contents())。
第二步:确认输入无二次过滤
检查从接收输入到执行比较之间,是否经过trim()、filter_var()、正则替换等清洗操作。若中间存在$input = preg_replace('/\s+/', '', $_POST['x']),则空格类payload失效。
第三步:测试真实请求响应
用curl发送构造好的payload,观察HTTP状态码、响应体关键词(如"welcome admin"、"access denied"、重定向Location头)是否发生预期外变化。例如:curl -X POST http://target/login -d "password=0e123456789" 若返回200且进入后台首页,即确认绕过成功。
【不可逆风险】若目标环境启用了display_errors=On,部分类型转换错误会直接输出Warning信息(如"Array to string conversion"),暴露内部结构,但切勿在生产环境反复试探。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











