Ataques XSS permitem a execução de código malicioso no navegador do usuário, mesmo em sites legítimos. Entenda os tipos, riscos e as melhores práticas para proteger sua aplicação web contra Cross-Site Scripting e evitar roubo de dados e ações indevidas.
Ataque XSS é uma vulnerabilidade em aplicações web que permite que um invasor execute seu próprio código JavaScript no navegador de outro usuário. O servidor do site pode continuar funcionando normalmente, mas o problema surge porque a aplicação processa dados de forma inadequada, permitindo que o navegador interprete informações maliciosas como parte da página ou como código executável.
Por meio de um ataque XSS, é possível modificar o conteúdo do site, exibir formulários falsos, executar ações em nome do usuário e acessar informações disponíveis na página. O risco é ampliado porque o código malicioso é executado dentro do próprio site legítimo, tendo os mesmos privilégios que scripts normais da página.
Cross-Site Scripting (XSS) ocorre quando um site insere dados não confiáveis do usuário em uma página HTML sem a devida sanitização ou escape. Assim, uma string que deveria ser exibida como texto pode ser interpretada pelo navegador como parte do HTML ou como código JavaScript.
Um exemplo simples é um site de comentários: ao inserir uma mensagem, o servidor a salva e exibe para outros visitantes. Se a aplicação inserir esses dados diretamente no HTML sem validação, um invasor pode tentar incluir comandos que forcem o navegador a executar JavaScript em vez de mostrar apenas texto.
De forma simplificada, XSS mistura dados e comandos. O usuário deveria poder enviar apenas informações como nome, comentário ou busca. Porém, devido a erros de programação, o navegador interpreta parte desses dados como instruções executáveis.
O nome Cross-Site Scripting é histórico e pode causar confusão: não é necessário transferir scripts de um site para outro literalmente. O principal sinal do XSS é a execução de código não confiável no contexto de uma página legítima e confiável pelo usuário.
Em ataques convencionais, o invasor tenta acessar o servidor, o banco de dados, o painel administrativo ou o sistema de arquivos. O XSS é diferente: o alvo é o navegador do visitante.
O atacante não precisa de controle total do servidor, bastando encontrar um ponto onde dados externos são inseridos de forma insegura na página. Quando a vítima acessa essa página, o código malicioso é executado no navegador dela.
Por isso, o XSS é diferente, por exemplo, de uma injeção SQL. Na injeção SQL, dados mal processados entram em comandos do banco de dados; já no XSS, eles se tornam código executável no navegador. Ambos se relacionam à manipulação insegura de dados, mas afetam partes distintas da aplicação web.
Saiba mais sobre injeção SQL, como funciona e como proteger seu site.
Um ataque XSS começa quando a aplicação web recebe dados de uma fonte não confiável, como comentários, buscas, parâmetros de URL ou nomes de usuário. Se o site insere esses dados na página sem sanitização, o navegador pode interpretá-los como HTML ou JavaScript.
O erro ocorre ao criar a página: o servidor ou o JavaScript do cliente insere o valor recebido em locais onde o navegador espera marcação ou código. Assim, dados especialmente preparados podem alterar a estrutura do documento e forçar a execução de comandos não planejados.
O navegador não diferencia o código do desenvolvedor e o do atacante. Se o JavaScript estiver na página e não for bloqueado por mecanismos de segurança, será executado no contexto do site.
A cadeia típica começa com um formulário ou parâmetro de requisição. O usuário envia dados, a aplicação os recebe e devolve em uma página HTML. Com processamento correto, caracteres especiais são exibidos como texto comum.
Sem escape, o conteúdo pode alterar a estrutura do HTML, permitindo que o navegador interprete elementos e manipuladores de eventos inseridos. O problema não está apenas no input do usuário, mas em como e onde ele é exibido.
O cenário pode ocorrer mesmo sem salvar dados no servidor: basta que a aplicação leia valores da URL ou de outras fontes e os insira de forma insegura no DOM. Por isso, XSS aparece tanto em sites tradicionais com renderização no servidor quanto em aplicações modernas baseadas em JavaScript.
As possibilidades do XSS dependem do site e das configurações do navegador. Um script malicioso pode ler o conteúdo da página, modificar elementos da interface, rastrear ações do usuário e enviar requisições em nome da aba aberta.
Por exemplo, o atacante pode substituir parte do site por um formulário de login falso ou outro elemento visualmente similar ao original. Como a substituição ocorre dentro do site legítimo, o usuário pode não perceber que interage com algo fraudulento.
O JavaScript também pode agir com os mesmos privilégios da página. Se o usuário estiver autenticado, o navegador pode incluir dados de sessão automaticamente em requisições. Assim, XSS pode servir não só para leitura de informações, mas também para executar ações em nome da vítima.
Um dos cenários mais conhecidos envolve os cookies de sessão. Após o login, o site entrega um identificador de sessão ao navegador, evitando que o usuário digite a senha a cada requisição.
Se esse cookie for acessível via JavaScript, um ataque XSS pode capturá-lo e enviá-lo ao invasor. O identificador interceptado pode, em alguns casos, permitir que o atacante se passe pelo usuário sem saber sua senha.
Sites modernos reduzem esse risco com o atributo HttpOnly, que impede o acesso ao cookie via JavaScript. Porém, isso não elimina o XSS: o código malicioso ainda pode interagir com a página e executar ações autorizadas pelo navegador do usuário. A proteção da sessão deve complementar a eliminação da vulnerabilidade, não substituí-la.
Os principais tipos de ataques XSS variam conforme a origem do código malicioso e o momento de execução. Os mais comuns são Stored XSS, Reflected XSS e DOM XSS. Para o usuário, o resultado é o mesmo - execução de JavaScript de terceiros -, mas a causa e a entrega do código são diferentes.
No Stored XSS (ou XSS armazenado), os dados maliciosos são salvos no site e exibidos automaticamente para outros usuários. Comentários, mensagens, descrições de perfil, postagens em fóruns ou qualquer campo salvo no banco de dados podem ser fontes dessa vulnerabilidade.
A gravidade desse cenário está no fato de o invasor não precisar enviar um link para cada vítima: basta inserir o script uma vez na área vulnerável e ele será carregado por todos que acessarem a página.
Por isso, o Stored XSS é considerado especialmente perigoso. Em páginas populares, um único script pode afetar muitos usuários.
O Reflected XSS funciona de modo diferente: os dados maliciosos não são salvos no site, mas enviados na requisição e devolvidos imediatamente em uma página gerada.
Por exemplo, se um site exibe o termo de busca no título dos resultados ou mostra um parâmetro da URL em uma mensagem de erro, e se esses valores são inseridos sem escape, um invasor pode criar um link que executa JavaScript ao ser aberto.
Esse tipo de ataque normalmente exige que o usuário acesse um link preparado ou envie uma requisição específica. Por isso, Reflected XSS costuma ser combinado com engenharia social, phishing ou links disfarçados.
O DOM XSS ocorre diretamente no navegador, devido a como o JavaScript do lado do cliente processa dados. O servidor pode enviar uma página completamente segura, mas a vulnerabilidade surge após o carregamento.
Por exemplo, um script pode ler valores da URL, de fragmentos após '#', parâmetros de busca ou outras fontes, inserindo-os de forma insegura na página. Se isso permitir interpretar o valor como HTML, o atacante pode modificar o DOM e executar código.
A principal diferença do DOM XSS é que a falha está na lógica do cliente: a string maliciosa pode nem ser enviada ao servidor, dificultando a detecção apenas com logs do backend.
Resumindo: Stored XSS envolve dados salvos, Reflected XSS reflete o input na resposta do servidor, e DOM XSS surge da manipulação insegura no navegador. Em todos os casos, o problema é permitir que dados não confiáveis sejam tratados como código.
O perigo do XSS está no fato de o código malicioso ser executado dentro do site legítimo, já confiado pelo usuário. Visualmente, a página pode parecer normal, mas o navegador pode executar ações não previstas pelos desenvolvedores.
As consequências vão de simples alterações de interface até a execução de comandos em nome do usuário autenticado ou o acesso a dados sensíveis.
JavaScript malicioso pode ler informações da página, monitorar interações e enviar dados a servidores externos. Páginas de contas pessoais, painéis internos e áreas administrativas são especialmente críticas, pois expõem informações restritas.
Se o usuário estiver autenticado, o navegador continuará tratando o site como confiável e poderá enviar dados de sessão junto com requisições, permitindo que o script execute ações em nome da vítima, mesmo que o cookie de sessão esteja protegido contra leitura direta.
O XSS permite modificar o DOM, possibilitando ao atacante adicionar ou substituir elementos. Por exemplo, pode-se exibir uma janela de login falsa, solicitar o reenvio de senha ou inserir um botão que leva a outro site.
Esse tipo de alteração é particularmente perigoso porque ocorre no domínio legítimo. O usuário vê o endereço correto e pode não notar que parte da interface foi manipulada pelo script malicioso.
Por meio do XSS, também é possível alterar links, ocultar avisos, modificar conteúdos ou redirecionar usuários para outros sites. Em alguns casos, o ataque serve como etapa adicional de phishing.
Ter HTTPS não protege contra XSS. O HTTPS apenas criptografa o tráfego entre o navegador e o servidor, impedindo a leitura ou alteração dos dados em trânsito, mas não garante a segurança do JavaScript inserido na página.
Se o servidor gerar uma página já comprometida ou se o código do cliente criar um DOM vulnerável, o navegador irá receber e executar esses dados via HTTPS normalmente.
A diferença fundamental entre XSS e ataques de interceptação de tráfego é que, no XSS, o código nocivo está dentro da página confiável, enquanto em ataques "man-in-the-middle" (MITM), o invasor tenta interferir na comunicação entre cliente e servidor.
Confira como funciona o ataque Man-in-the-Middle e veja dicas de proteção.
A proteção contra Cross-Site Scripting baseia-se em um princípio: nunca considerar seguros os dados vindos do usuário ou de fontes externas. A aplicação deve controlar onde esses dados vão e como o navegador os interpretará.
Uma única checagem não é suficiente. A defesa eficaz combina escape de saída, manipulação segura do DOM, restrições à execução de scripts e medidas extras para proteger sessões.
A principal defesa contra XSS é exibir dados do usuário como texto, nunca como código HTML. Comentários, nomes ou buscas devem ser tratados para que caracteres especiais apareçam como texto, não como marcação.
O método de escape depende do contexto: dados em HTML, atributos, URLs ou strings JavaScript exigem tratamentos diferentes. O erro acontece quando a aplicação usa uma abordagem única para todos os casos ou insere valores sem processá-los.
Templates modernos e frameworks costumam escapar a saída automaticamente. Porém, a proteção pode ser perdida se o desenvolvedor desativar esse recurso ou inserir HTML bruto manualmente.
A validação limita o formato de entrada permitido. Por exemplo, um campo de idade não deve aceitar HTML, e nomes de arquivos não devem conter comandos de controle.
Quando é necessário aceitar HTML - como em editores de artigos ou comentários com formatação -, não basta proibir caracteres especiais: é preciso limpar o conteúdo, permitindo apenas tags e atributos seguros e removendo elementos perigosos.
A filtragem de entrada não substitui o escape seguro na saída. Mesmo dados validados podem ser usados em contextos diferentes depois; a proteção deve atuar no momento em que a informação é inserida na página.
O Content Security Policy (CSP) adiciona um nível extra de defesa. Ele permite ao site definir de onde o navegador pode carregar e executar JavaScript, restringindo scripts não autorizados.
Um CSP bem configurado reduz o impacto do XSS, mas não substitui a correção da falha. Se a aplicação continuar inserindo dados do usuário de forma insegura, o problema persiste.
O JavaScript do cliente merece atenção especial. Para mostrar texto, prefira textContent em vez de métodos que interpretam strings como HTML. Use innerHTML apenas quando controlar totalmente o conteúdo ou após higienizá-lo.
Mesmo que não seja possível eliminar totalmente o XSS, é possível mitigar danos. Cookies de sessão devem usar o atributo HttpOnly, bloqueando o acesso via JavaScript.
O atributo Secure exige transmissão por HTTPS, enquanto SameSite limita o envio dos cookies em requisições de outros sites. Esses mecanismos não eliminam o XSS, mas dificultam cenários de roubo ou abuso de sessão.
Na prática, a defesa eficiente é multicamada: escape de saída, higienização de HTML, operações seguras no DOM, CSP e cookies protegidos pelo navegador.
O ataque XSS ocorre quando um site permite que dados não confiáveis se transformem em código executável no navegador do usuário. JavaScript malicioso pode chegar à página por meio de dados armazenados, parâmetros de requisição ou manipulação insegura do DOM, exigindo estratégias distintas para Stored XSS, Reflected XSS e DOM XSS.
A principal defesa é nunca misturar dados do usuário com HTML ou JavaScript sem tratamento seguro. Escape de saída, limpeza de HTML permitido, manipulação cautelosa do DOM, políticas CSP e cookies protegidos devem ser usados em conjunto. Quanto antes a aplicação separa dados de código executável, menor o risco de que um campo de input se torne porta de entrada para XSS.