Se a SQL Injection ataca o banco de dados no servidor, o Cross-Site Scripting (XSS) ataca o navegador de outros usuários. É uma das vulnerabilidades web mais prevalentes, e sua natureza é distinta e engenhosa: o atacante consegue que a aplicação sirva seu código JavaScript para as vítimas, e esse código executa no navegador delas, dentro do contexto do site confiável — podendo roubar sessões, capturar credenciais, ou agir como o usuário. Entender XSS é entender uma classe inteira de ataques que exploram a confiança do navegador. Pratique no DVWA e no Juice Shop.

A fronteira entre dado e código, de novo

O mecanismo, na essência: a aplicação recebe entrada do usuário e a exibe de volta numa página sem sanitizá-la. Se essa entrada contém código (JavaScript), e a aplicação a insere na página como se fosse conteúdo confiável, o navegador da vítima executa esse código. É a mesma raiz da SQLi — misturar dados e código, deixar a fronteira se apagar — mas o "código" aqui é JavaScript executando no navegador, e a vítima é outro usuário, não o servidor. O JavaScript injetado roda com todos os privilégios daquela página no navegador da vítima: pode ler cookies, modificar a página, fazer requisições em nome do usuário.

Refletido, armazenado e baseado em DOM

Existem três tipos de XSS, distinguidos por como o código malicioso chega à vítima. O XSS refletido (reflected): o código vai numa requisição (tipicamente na URL) e é "refletido" de volta na resposta imediatamente. O atacante cria um link malicioso e engana a vítima a clicá-lo (via phishing, Bloco XIV) — o código na URL é refletido na página e executa. É "não persistente": afeta só quem clica no link específico. O XSS armazenado (stored): o código é salvo no servidor (num comentário, num perfil, numa mensagem) e servido a todos que visualizam aquela página. É o mais perigoso, porque não requer enganar cada vítima individualmente — qualquer um que veja o comentário malicioso é afetado, potencialmente milhares de usuários, incluindo administradores. E o XSS baseado em DOM: a vulnerabilidade está no próprio JavaScript do front-end, que manipula a página de forma insegura com dados controláveis pelo atacante, sem que o servidor sequer processe o payload.

Do alert ao roubo de sessão

A prova de conceito clássica é inofensiva, mas ilustra o problema:

<script>alert('XSS')</script>

Se você insere isso num campo e a página exibe um pop-up de alerta, ela é vulnerável — porque executou o seu script. Mas o alert é só a demonstração; o impacto real vem do que um atacante faria com essa execução. O ataque mais emblemático é o roubo de cookie de sessão (lembra da aula Arquitetura web e HTTP: entendendo o terreno — o cookie é a identidade da vítima). Um payload que envia o cookie da vítima para o atacante permite que ele sequestre a sessão — assuma a identidade da vítima sem senha. Outros impactos: capturar tudo que a vítima digita (keylogging via JS), modificar a página para exibir um formulário de login falso (phishing dentro do site real), realizar ações em nome da vítima (fazer transferências, mudar configurações), e até propagar-se (um XSS armazenado numa rede social pode virar um "worm" que se espalha entre usuários).

Subverter a confiança do navegador no site

O que torna o XSS conceitualmente importante é que ele explora a confiança do navegador no site. Seu navegador confia no código que vem de um site legítimo e o executa com acesso aos dados daquele site (cookies, conteúdo). O XSS subverte isso: faz o site legítimo servir código do atacante, que herda essa confiança. É um ataque que atravessa a fronteira cliente-servidor de um jeito diferente da SQLi — o servidor é o veículo, mas o alvo é o usuário. Isso o conecta intimamente com a engenharia social (o XSS refletido precisa de um clique) e com o comprometimento de sessões.

Tratar a saída: encoding e CSP

Do lado defensivo, o XSS tem defesas bem estabelecidas, todas girando em torno de tratar a saída corretamente. A defesa central é o output encoding / escaping: ao exibir qualquer dado que veio do usuário, a aplicação deve codificá-lo de forma que o navegador o trate como texto, não como código — de modo que <script> apareça literalmente como o texto "<script>" em vez de ser executado. Complementarmente: validação e sanitização de entrada (rejeitar ou limpar entrada perigosa); a Content Security Policy (CSP) — um cabeçalho poderoso que instrui o navegador a só executar scripts de fontes confiáveis, mitigando XSS mesmo se um payload passar; o atributo HttpOnly nos cookies de sessão (que impede o JavaScript de lê-los, frustrando o roubo de cookie via XSS — uma defesa simples e eficaz); e o uso de frameworks modernos (React, Angular) que escapam saída por padrão. A lição, ecoando a SQLi: a falha nasce de tratar entrada do usuário como código confiável, e a defesa é impor rigorosamente a fronteira entre dado e código — no XSS, ao escrever na página.

Fontes e leituras recomendadas

Exercícios

  1. Qual a diferença fundamental entre o alvo da SQL Injection e o do XSS?

    ✓ Resposta:

    A SQL Injection ataca o banco de dados no servidor (manipulando consultas SQL); o XSS ataca o navegador de outros usuários, fazendo a aplicação servir código JavaScript do atacante que executa no navegador das vítimas, no contexto do site confiável.

  2. Diferencie XSS refletido, armazenado e baseado em DOM quanto a como o código chega à vítima, e por que o armazenado é o mais perigoso.

    ✓ Resposta:

    No refletido, o código vai numa requisição (ex.: URL) e é refletido de volta na resposta imediata, afetando só quem clica no link malicioso. No armazenado, o código é salvo no servidor e servido a todos que veem a página. No DOM, a falha está no JavaScript do front-end que manipula dados de forma insegura. O armazenado é mais perigoso porque afeta todos os visitantes automaticamente, sem precisar enganar cada vítima.

  3. Por que o alert('XSS') é apenas uma prova de conceito? Cite dois impactos reais de um XSS explorado.

    ✓ Resposta:

    Porque o alert apenas demonstra que um script arbitrário executa, sem causar dano. Impactos reais: roubo do cookie de sessão (sequestro de sessão), keylogging, exibição de formulário de login falso (phishing no site real), ações em nome da vítima. (Dois quaisquer.)

  4. Explique como o XSS "explora a confiança do navegador no site".

    ✓ Resposta:

    O navegador confia no código servido por um site legítimo e o executa com acesso aos dados daquele site (cookies, conteúdo). O XSS subverte essa confiança ao fazer o site legítimo servir código do atacante, que herda os privilégios e o acesso concedidos ao site — executando como se fosse parte dele.

  5. Cite três defesas contra XSS e explique como o atributo HttpOnly frustra o roubo de cookie.

    ✓ Resposta:

    Defesas: output encoding/escaping, validação/sanitização de entrada, Content Security Policy (CSP), HttpOnly nos cookies, frameworks que escapam por padrão. O HttpOnly impede que o JavaScript acesse o cookie de sessão; assim, mesmo que um XSS execute, o script não consegue ler o cookie para exfiltrá-lo, frustrando o roubo de sessão.