Cross-Site Scripting (XSS): Vetores de Ataque e Defesas
Por que o XSS ainda assombra aplicações web
Cross-site scripting (XSS) continua sendo uma das vulnerabilidades web mais prevalentes. Apesar da ampla conscientização, aparece consistentemente no OWASP Top 10. A questão central: as aplicações confiam na entrada do usuário e a renderizam sem o tratamento adequado. Atacantes injetam scripts maliciosos que são executados nos navegadores das vítimas, levando ao sequestro de sessão, roubo de dados e desfiguração.
Este artigo detalha os vetores de ataque XSS e fornece defesas práticas que você pode implementar hoje.
O que é XSS e como funciona?
XSS ocorre quando uma aplicação inclui dados não confiáveis em uma página web sem validação ou codificação. O navegador então executa o script injetado como se fizesse parte do site legítimo. Como o script é executado no contexto do site vulnerável, ele pode acessar cookies, armazenamento local e fazer requisições em nome do usuário.
Considere uma página de busca simples que reflete a consulta:
<?php echo 'Você pesquisou por: ' . $_GET['q']; ?>
Se um atacante criar uma URL como search.php?q=<script>alert('XSS')</script>, o script é executado quando a vítima visita o link.
Três principais tipos de XSS
1. XSS Refletido
O script malicioso faz parte da requisição (por exemplo, parâmetro de URL) e é imediatamente refletido na resposta. As vítimas precisam ser induzidas a clicar em um link ou enviar um formulário. Isso é frequentemente usado em campanhas de phishing.
2. XSS Armazenado
O script é armazenado permanentemente no servidor (por exemplo, em um banco de dados, campo de comentário ou perfil de usuário). Todo visitante da página afetada executa o script. O XSS armazenado é mais perigoso porque não requer interação além de visualizar a página.
3. XSS Baseado em DOM
A vulnerabilidade existe no JavaScript do lado do cliente que lê dados de uma fonte não confiável (como location.hash) e os grava no DOM sem tratamento seguro. O servidor pode nunca ver o payload malicioso.
document.getElementById('output').innerHTML = location.hash.substring(1);
Se o hash contiver <img src=x>, o script é executado.
Vetores de ataque comuns
- Entrada de usuário não escapada em HTML: Injeção direta em conteúdo HTML, atributos ou JavaScript.
- Uso inadequado de sinks perigosos: Funções como
innerHTML,document.write,evalesetTimeoutcom argumentos de string. - Injeções baseadas em URL: Manipulação de atributos
href,srcoustylecom URIsjavascript:. - Componentes de terceiros: Bibliotecas ou widgets vulneráveis que renderizam dados não confiáveis.
Defesas contra XSS
1. Codificação de Saída (Escape Contextual)
Codifique todos os dados não confiáveis antes de renderizá-los em HTML, atributos, JavaScript, CSS ou URLs. Use codificação apropriada ao contexto:
- Codificação de entidades HTML: Converta
&,<,>,",'em entidades. - Codificação JavaScript: Escape caracteres não alfanuméricos para Unicode.
- Codificação de URL: Use
encodeURIComponent()para parâmetros de consulta.
A maioria dos frameworks modernos (React, Angular, Vue) faz escape automático por padrão, mas tenha cuidado ao usar dangerouslySetInnerHTML ou mecanismos similares.
2. Validação e Sanitização de Entrada
Valide a entrada no lado do servidor usando listas de permissões. Para texto rico, use uma biblioteca como DOMPurify para sanitizar HTML, removendo tags e atributos perigosos.
const clean = DOMPurify.sanitize(userInput);
Nunca confie apenas na validação do lado do cliente.
3. Content Security Policy (CSP)
CSP é um poderoso mecanismo de defesa em profundidade. Restringe fontes de scripts executáveis, scripts inline e outros recursos. Uma CSP estrita pode bloquear XSS mesmo se uma injeção ocorrer.
Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com; object-src 'none';
Evite unsafe-inline e unsafe-eval. Use nonces ou hashes para scripts inline legítimos.
4. Atributos Seguros de Cookies
Defina cookies com HttpOnly (impede acesso via JavaScript) e Secure (apenas HTTPS). Isso mitiga o sequestro de sessão via XSS.
5. Use Frameworks Modernos e Evite APIs Perigosas
Frameworks como React, Angular e Vue fazem escape automático de dados. Evite manipulação direta do DOM com innerHTML. Se precisar inserir HTML, sanitize primeiro.
6. Testes de Segurança Regulares
Incorpore SAST, DAST e testes de penetração manuais. Ferramentas como OWASP ZAP podem ajudar a identificar vulnerabilidades XSS.
Comparação dos Tipos de XSS e Defesas Primárias
| Tipo de XSS | Descrição | Defesa Primária |
|---|---|---|
| Refletido | Payload na requisição, refletido na resposta | Codificação de saída, validação de entrada |
| Armazenado | Payload armazenado no servidor, servido a todos os usuários | Sanitização, codificação de saída, CSP |
| Baseado em DOM | Injeção no lado do cliente via APIs DOM inseguras | APIs DOM seguras, CSP, evitar eval |
Passo a Passo: Implementando Defesas contra XSS
- Identifique todos os pontos de entrada: Formulários, parâmetros de URL, cabeçalhos, cookies.
- Aplique codificação de saída contextual: Use funções integradas ou bibliotecas como OWASP Java Encoder.
- Sanitize texto rico: Use DOMPurify ou similar.
- Implante CSP: Comece com modo somente relatório, depois imponha.
- Defina cookies HttpOnly e Secure.
- Eduque desenvolvedores: Treine em práticas seguras de codificação.
- Teste regularmente: Integre testes de segurança no CI/CD.
FAQ
Qual a diferença entre XSS e CSRF?
XSS executa scripts maliciosos no navegador da vítima, enquanto CSRF engana o navegador para enviar requisições não autorizadas a um site onde o usuário está autenticado. XSS pode ser usado para contornar proteções CSRF.
A Content Security Policy pode prevenir completamente o XSS?
Não, CSP é uma medida de defesa em profundidade. Ela reduz significativamente o risco, mas não substitui a codificação de saída e a validação de entrada adequadas. Uma CSP mal configurada ainda pode permitir alguns ataques.
A validação do lado do cliente é suficiente para prevenir XSS?
Não. A validação do lado do cliente pode ser facilmente contornada. Sempre valide e codifique no lado do servidor, e trate todos os dados do cliente como não confiáveis.
Conclusão
XSS é uma ameaça persistente, mas com uma estratégia de defesa em camadas—codificação de saída, validação de entrada, CSP e cookies seguros—você pode mitigá-la efetivamente. Mantenha-se vigilante, mantenha os frameworks atualizados e teste continuamente.
Para ferramentas adicionais de segurança, confira nosso Analisador de Logs Nginx para detectar padrões suspeitos em seus logs de servidor.