Skip to content

Tudo para WordPress, desenvolvimento web — e não só

💡 Cross-site scripting (XSS): o que é e como proteger o seu site em 2026

💡 Cross-site scripting (XSS): o que é e como proteger o seu site em 2026

Em 2019, quase 75% das grandes empresas sofreram cross-site scripting. Sete anos depois, o XSS continua presente. A Microsoft reportou 970 casos de XSS encerrados apenas desde janeiro de 2024, e uma vulnerabilidade de 2025 no plugin LiteSpeed Cache colocou 7 milhões de sites WordPress em risco.

O problema não é a tecnologia. O JavaScript, a linguagem da web interativa, alimenta cada tema, cada formulário de comentários, cada carrinho de compras. O problema é que um atacante pode forçar o seu site a executar o código dele, e o navegador não consegue distinguir um script malicioso de um legítimo.

Vamos analisar a mecânica do XSS, três tipos de ataques e camadas específicas de proteção que blindam o seu site contra cross-site scripting. Com ferramentas, exemplos de código e casos reais em WordPress.

💡 Visão geral rápida:

  • O que é XSS e como um atacante injeta código malicioso num site confiável
  • Três tipos de cross-site scripting (armazenado, refletido e baseado em DOM) e como se distinguem
  • Configuração passo a passo de três camadas de proteção: WAF, escape de output e Content Security Policy
  • Onde procurar vulnerabilidades XSS no seu site e o que fazer se um ataque já tiver ocorrido

O que é cross-site scripting

Diagrama de um ataque de cross-site scripting num website

Cross-Site Scripting é um ataque de injeção em que um atacante incorpora um script malicioso numa página de um site confiável. O navegador da vítima executa este código porque o trata como parte da página legítima. Daí o nome: o script chega «cruzando a fronteira do site».

Tecnicamente, o vetor de ataque não se limita ao JavaScript. São possíveis vulnerabilidades em HTML, Flash, ActiveX e CSS. Mas, na prática, a esmagadora maioria das explorações visa JS. A razão: o acesso à árvore DOM, cookies, localStorage e a capacidade de fazer pedidos em nome do utilizador.

No WordPress, as vulnerabilidades surgem quase sempre através de plugins e temas que tratam incorretamente o input do utilizador. Formulários de comentários, barras de pesquisa, formulários de contacto, páginas de login: qualquer campo que aceite dados e os devolva sem filtragem torna-se um ponto de entrada. De acordo com a Claranet, foram encontrados 2570 casos de XSS refletido e armazenado em aplicações web testadas em 2024.

Como funciona o XSS

Um atacante precisa de duas condições: um ponto de entrada para o código malicioso e ausência de filtragem no output. Na prática, isto é conseguido de duas formas: através da manipulação do input do utilizador e contornando a política de mesma origem.

Injeção através do input do utilizador

O cenário mais comum. Um campo de utilizador (barra de pesquisa, formulário de comentários, campo de upload de ficheiros) aceita não apenas texto, mas código executável. Se o plugin ou tema não fizer o escape do output, um <script>alert('XSS')</script> inserido será executado no navegador de todos os que abrirem a página.

O problema é mais profundo do que parece. Até programadores experientes deixam escapar vetores de XSS através de campos aparentemente inofensivos: upload de um ficheiro SVG com um script incorporado, introdução de dados no campo «nome de utilizador» durante o registo, parâmetros de URL em redirecionamentos. Basta um campo sem esc_url() ou esc_attr() para o site ficar exposto.

Num mundo ideal, uma barra de pesquisa aceita texto simples e nada mais. No ecossistema real do WordPress, com mais de 60 000 plugins, esta garantia é inatingível: basta um plugin com echo $_GET['q'] sem esc_html().

Contornar a política de mesma origem

Ilustração de como contornar a política de mesma origem do navegador

A política de mesma origem é uma regra de segurança fundamental dos navegadores: scripts de uma origem não podem ler dados de outra. Uma página do Facebook e uma página do banco abertas no mesmo navegador não trocam informações. Mas esta regra tem um calcanhar de Aquiles: os cookies de sessão.

Quando faz login num site, o navegador cria um cookie de sessão que confirma a sua identidade a cada pedido. Sem ele, teria de introduzir a sua palavra-passe ao navegar para cada nova página. O problema é que o navegador anexa este cookie a qualquer pedido ao domínio, incluindo pedidos iniciados por um script malicioso.

Esquema do ataque: um atacante encontra uma vulnerabilidade XSS em example.com → injeta um script que lê document.cookie → envia o cookie de sessão para o seu servidor. Resultado: acesso total à conta da vítima sem saber a palavra-passe. Os cookies de sessão armazenam credenciais, conteúdo do carrinho, informações de envio: todo o contexto do utilizador.

Três tipos de ataques XSS

Captura de ecrã do jogo educativo Google XSS Game para encontrar vulnerabilidades

A classificação de XSS baseia-se no local e na forma como o código malicioso chega à vítima. Existem três tipos, e proteger o seu site exige compreender a mecânica de cada um.

Stored XSS (tipo I)

O tipo mais perigoso. O script malicioso é guardado no servidor (na base de dados, em logs, num campo de comentário) e é executado sempre que a página infetada é aberta. No WordPress, este é um cenário clássico: um atacante deixa um comentário com uma tag <script>, o plugin de comentários não filtra o HTML e o script é executado para cada visitante do artigo.

A particularidade do stored XSS é que o ataque não precisa de ser ativado através de um link de phishing. A vítima simplesmente visita a página. Em 2025, a vulnerabilidade CVE-2025-12709 no plugin Interactions para WordPress foi um stored XSS clássico devido a uma sanitização insuficiente do input nos seletores de eventos.

Reflected XSS (tipo II)

O atacante envia à vítima um link que contém código malicioso nos parâmetros do URL. O servidor «reflete» esse código de volta na resposta, por exemplo, numa mensagem de erro de pesquisa ou numa linha «Pesquisou por: X». O browser executa o script porque este chegou no corpo da resposta a partir de um servidor confiável.

O reflected XSS requer uma ação ativa da vítima: clicar num link. Por isso, o ataque é frequentemente disfarçado como um URL legítimo num email de phishing. No WordPress, um vetor típico são os plugins de pesquisa que exibem o termo pesquisado sem esc_html().

DOM-based XSS (tipo 0)

Ao contrário dos dois primeiros, aqui a vulnerabilidade não está no código do lado do servidor, mas sim no JavaScript do lado do cliente. Os dados maliciosos nunca chegam ao servidor; são processados diretamente no browser através de métodos inseguros da DOM API, como innerHTML, document.write() ou eval().

A fonte dos dados é o URL (via window.location), o document.referrer ou qualquer outra fonte controlável no cliente. Os logs do servidor estão limpos; o ataque é visível apenas no browser. Este XSS é o mais difícil de detetar porque a WAF e os scanners do lado do servidor não o veem.

Porque é que o XSS é especialmente perigoso para o WordPress

O WordPress é o alvo número um para XSS por uma razão: o ecossistema. Dos mais de 60 000 plugins no repositório, nem todos passam por uma revisão rigorosa do escape de output. Um plugin com uma vulnerabilidade compromete todo o site.

Em setembro de 2025, a Microsoft publicou uma análise sobre as razões pelas quais o XSS continua a ser uma ameaça 25 anos após o seu aparecimento. A principal conclusão: a complexidade da stack web moderna torna a eliminação completa do XSS quase impossível, existem demasiadas camadas onde o escape pode ser omitido.

O que um atacante obtém através de XSS no WordPress:

  • Acesso ao painel de administração ao roubar cookies de sessão do administrador
  • Injeção de links ocultos (spam de SEO)
  • Download de malware para os computadores dos visitantes
  • Substituição de detalhes de pagamento no WooCommerce
  • Desfiguração em massa de páginas do site

Combinado com engenharia social, o XSS torna-se um vetor para ataques sofisticados: desde a instalação de keyloggers até à falsificação de pedidos entre sites.

Como proteger o seu site contra XSS: três camadas

Três camadas de proteção do WordPress contra cross-site scripting

A proteção contra XSS não se resolve com uma única configuração. Só a defesa em profundidade funciona: os plugins de segurança bloqueiam ataques grosseiros, o escape de saída fecha os vetores técnicos e a Content Security Policy bloqueia a execução de scripts ao nível do navegador.

Camada 1: plugins de segurança e firewall

A primeira linha de defesa é um plugin WordPress com uma Web Application Firewall. A WAF filtra os pedidos recebidos antes de estes chegarem ao código dos plugins e bloqueia assinaturas conhecidas de ataques XSS.

Ao escolher um plugin de segurança, use esta lista de verificação:

  • Análise regular de malware e CVEs conhecidas nos plugins instalados
  • Firewall com regras para bloquear padrões de XSS nos pedidos
  • Reforço do WordPress: desativar XML-RPC, alterar o prefixo das tabelas, impedir a edição de ficheiros a partir do admin
  • Gestão centralizada de atualizações para todos os plugins e temas
  • Cópias de segurança, para poder restaurar o site se um ataque conseguir passar

Pode encontrar uma seleção de plugins de segurança para WordPress com análises detalhadas das funcionalidades de cada ferramenta em avaliações especializadas no nosso site.

Camada 2: validação e escape de saída

Esta é a principal linha de defesa técnica. A regra é simples e inegociável: nenhum dado do utilizador é enviado para o navegador sem escape. O WordPress fornece funções nativas para isto, e cada uma está ligada a um contexto de saída específico.

Kit básico de ferramentas para programadores WordPress:

1// For output inside HTML tags — between <p> and </p>
2echo esc_html($user_input);
3
4// For HTML attributes — inside value="..."
5echo esc_attr($user_input);
6
7// For URLs in href, src, and other attributes
8echo esc_url($user_url);
9
10// For output inside <textarea>
11echo esc_textarea($user_text);
12
13// For JavaScript variables
14echo esc_js($user_data);
15
16// For allowed HTML tags with dangerous attributes removed
17echo wp_kses_post($user_html);

O ponto essencial: a escolha da função depende do contexto. esc_html() num atributo href não o salvará; o atacante inserirá javascript:alert('XSS'). Inversamente, esc_url() dentro de um parágrafo deixará passar uma tag <script>. O contexto determina a função.

wp_kses() merece uma menção especial: um filtro poderoso que permite apenas as tags e atributos HTML autorizados. Para conteúdo de utilizador (comentários, descrições de perfil, campos personalizados), este é o nível mínimo de filtragem exigido.

Camada 3: Content Security Policy (CSP)

CSP é um cabeçalho HTTP que diz ao navegador: «Execute scripts apenas a partir destas origens.» Esta é a última linha de defesa. Mesmo que um atacante tenha injetado um <script> na página, o navegador não o executará porque os scripts inline não estão na lista de permissões.

Política CSP básica para WordPress:

1// In functions.php or via a plugin
2function add_csp_header() {
3 header("Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:;");
4}
5add_action('send_headers', 'add_csp_header');

Uma política estrita ('strict-dynamic' em vez de 'unsafe-inline') é mais segura, mas requer a configuração de nonce ou hashes para cada script legítimo. Isto é um trabalho substancial num site com uma dúzia de plugins ativos. Comece pelo modo de apenas relatório para recolher registos de violações sem quebrar o frontend:

1Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report-endpoint

A CSP não substitui o escape. Ela mitiga as consequências dos erros quando o escape foi omitido em algum ponto.

Vídeo: XSS do básico à exploração

Para ver XSS em ação e compreender como encontrar vulnerabilidades em sites reais, veja esta análise de 30 minutos:

Depois de ver, regresse às camadas de proteção acima. Agora elas farão sentido ao nível mecânico, e não apenas ao nível dos nomes das funções.

⁉️🤔 Perguntas frequentes

Atualizar o WordPress e os plugins ajuda a proteger contra XSS?

Sim, e este é o passo de proteção mais subestimado. Cada nova versão de um plugin fecha frequentemente CVEs específicas, incluindo vulnerabilidades de XSS. A vulnerabilidade do LiteSpeed Cache CVE-2025-12450 foi corrigida no prazo de uma semana após a descoberta, mas 7 milhões de sites que não atualizaram permaneceram expostos. Ative as atualizações automáticas para todos os plugins; os problemas de compatibilidade são raros, enquanto uma correção não aplicada atinge de forma garantida.

Um único plugin de segurança é suficiente para proteger contra XSS?

Não. Um plugin de segurança com WAF fecha as assinaturas de ataque conhecidas, mas não deteta vulnerabilidades de dia zero nem vetores não padronizados. Deve ser a primeira camada, seguida pelo escape de saída no código do tema e pelos cabeçalhos CSP. As três camadas em conjunto fornecem uma proteção que nenhuma delas pode fornecer isoladamente.

Como verifico se o meu site tem vulnerabilidades de XSS?

Comece com um scanner gratuito: WPScan, Sucuri SiteCheck, Qualys SSL Labs. Para testes mais aprofundados, execute o OWASP ZAP (Zed Attack Proxy), uma ferramenta de código aberto que faz fuzzing automático dos campos de entrada e deteta XSS refletido. Importante: os scanners automáticos não detetam XSS baseado em DOM; isso requer uma auditoria manual do código JavaScript do site.

O XSS pode ser completamente eliminado num site grande?

A eliminação completa do XSS num site com dezenas de plugins e um tema personalizado é uma tarefa próxima do ideal, mas difícil de alcançar totalmente. Cada novo plugin, cada atualização de tema, cada snippet personalizado no functions.php é um potencial ponto de entrada. Um objetivo realista: três camadas de proteção, atualizações automáticas, auditorias trimestrais e CSP em modo de apenas relatório. Desta forma, detetará a grande maioria dos ataques numa fase inicial.

O que devo fazer se o meu site já foi atacado através de XSS?

Altere imediatamente todas as palavras-passe e reponha as chaves de sessão no wp-config.php usando o gerador do WordPress. Depois, restaure o site a partir de uma cópia de segurança limpa. Após a restauração, instale um plugin de segurança, atualize todos os plugins e temas para as versões mais recentes e adicione um cabeçalho CSP no functions.php. As palavras-passe devem ser alteradas porque o XSS frequentemente rouba cookies de sessão do administrador.

XSS e injeção de SQL são a mesma coisa?

Não, embora ambos sejam ataques de injeção. A injeção de SQL tem como alvo a base de dados através de uma consulta SQL; o atacante pode ler, modificar ou eliminar tabelas. O XSS tem como alvo o navegador do utilizador através de JavaScript; o objetivo é roubar sessões, exibir formulários de phishing ou alterar o conteúdo da página. Têm vetores diferentes, funções de proteção diferentes ($wpdb->prepare() para SQL, esc_html() para XSS) e consequências diferentes. Mas, na prática, surgem frequentemente em conjunto: o XSS é usado para realizar injeção de SQL através do painel de administração.

Deve temer o XSS em 2026

O XSS não desapareceu, mas a defesa contra ele tornou-se rotina de engenharia, não magia. Três camadas (um plugin com WAF, escape de saída em todos os pontos de contacto com o utilizador e um cabeçalho CSP) fecham a grande maioria dos vetores. Mais as atualizações automáticas de plugins e temas, para que as correções cheguem antes dos exploits.

Se atualmente não está a usar nenhuma destas camadas, comece por instalar um plugin de segurança e ativar as atualizações automáticas no admin do WordPress. Isto demora 10 minutos e fecha os pontos de entrada mais grosseiros. Depois, regresse a este artigo quando estiver pronto para implementar o escape e a CSP.