FlawOpen

flawopen.com/XSS/Tipos de XSS

XSS refletido, armazenado e baseado em DOM: quais são as diferenças?

Página de referência
Resposta curta

XSS refletido, armazenado e baseado em DOM descrevem caminhos diferentes entre dados não confiáveis e um contexto inseguro no navegador. Eles podem se sobrepor: identifique a origem do valor, se ele persiste, qual código o renderiza e quem o recebe.

Os três tipos

XSS refletido — o valor vem da requisição

Um valor da requisição é incluído na resposta sem codificação adequada ao contexto, e o navegador o interpreta como marcação ou script. Um invasor pode enviar um link criado para a vítima, mas a falha é a renderização insegura dos dados da requisição. Corrija o contexto de saída no ponto de renderização.

XSS armazenado — o valor persiste

Conteúdo não confiável é armazenado e depois renderizado de forma insegura para outros usuários, por exemplo em um comentário ou campo de perfil. Cada visitante que carrega o conteúdo afetado pode receber o mesmo contexto inseguro até que o valor armazenado ou o caminho de renderização seja corrigido.

XSS baseado em DOM — código no cliente envia dados a um sink inseguro

JavaScript no cliente lê uma origem não confiável (como location.hash, um parâmetro de consulta ou dados retornados pelo servidor) e a envia a um sink DOM inseguro, como innerHTML. O valor pode não chegar ao servidor, mas isso não é necessário: XSS baseado em DOM descreve o caminho fonte-sink no cliente e pode se sobrepor à entrega refletida ou armazenada. Corrija o fluxo de dados no cliente.

Por que a distinção importa para corrigir

Corrija XSS no ponto de renderização usando codificação de saída adequada ao contexto ou uma API DOM segura. XSS refletido e armazenado frequentemente envolvem saída renderizada no servidor, mas a renderização no cliente também pode criar o sink inseguro. Para XSS baseado em DOM, prefira textContent a innerHTML para texto; se HTML rico for necessário, use um sanitizador mantido com política explícita. Codificação no servidor não substitui a revisão dos fluxos fonte-sink do cliente.

Essas categorias podem se sobrepor

XSS refletido e armazenado descrevem como a entrada chega à página e se ela persiste. DOM-based descreve um fluxo de origem até sink no cliente. As categorias não são mutuamente exclusivas: um texto de perfil persistido e inserido pelo código do cliente em innerHTML pode ser XSS armazenado e DOM-based ao mesmo tempo.

XSS baseado em DOM: sink inseguro e renderização somente de texto

INSEGURO — interpretar texto não confiável como HTML
const value = new URLSearchParams(location.search).get("q") ?? "";
target.innerHTML = value;
MAIS SEGURO PARA TEXTO — renderizar como texto
const value = new URLSearchParams(location.search).get("q") ?? "";
target.textContent = value;

Referências

Veja também Cross-Site Scripting (XSS, CWE-79): como funciona e como evitar em todas as linguagens — flawopen.com Riscos de segurança do addJavascriptInterface no Android Proteção XSS do Angular: padrões seguros e APIs de bypass XSS por MIME sniffing: Content-Type e nosniff CSP e escape de saída: você precisa dos dois? dangerouslySetInnerHTML do React é seguro? DOMPurify basta para proteger innerHTML?