# Como corrigir vulnerabilidade XSS no WordPress

Uma vulnerabilidade XSS (cross-site scripting) no WordPress permite que um invasor injete JavaScript malicioso nas suas páginas, que então roda no navegador de quem visita. Corrigir significa achar a entrada não sanitizada, escapar a saída e atualizar o plugin ou tema que abriu a brecha.

## O que é a vulnerabilidade XSS no WordPress?

XSS (cross-site scripting) é uma falha em que dados controlados pelo atacante são exibidos numa página sem sanitização nem escape, fazendo o navegador da vítima executar um script injetado. No WordPress, costuma vir de um plugin ou tema que grava e mostra entradas de formulário, comentários ou parâmetros de URL sem tratar. O script roubado pode capturar cookies de sessão, redirecionar visitantes ou criar um admin oculto. Existem três tipos: refletido (via URL), armazenado (gravado no banco, o mais grave) e baseado em DOM. A correção real é tapar a entrada vulnerável, não só limpar o sintoma.

## Como identificar

- O scanner de segurança ou o WPScan aponta "Cross-Site Scripting (XSS)" em um plugin ou tema instalado.
- Aparecem pop-ups inesperados ou redirecionamentos ao abrir uma página cujo parâmetro de URL carrega uma tag de script injetada.
- Comentários, campos de perfil ou formulários executam uma tag de script em vez de mostrá-la como texto.
- No console do navegador surgem scripts de domínios estranhos carregando junto com a sua página.

**Antes de começar:** Faça backup do banco antes de remover injeções gravadas. Apagar conteúdo de wp_posts ou wp_options às cegas pode quebrar o site; salve uma cópia para conseguir reverter se remover algo legítimo por engano.

## Como prevenir

- Escape toda saída de dado do usuário com esc_html(), esc_attr() ou esc_url() conforme o contexto
- Mantenha plugins e temas atualizados e remova os abandonados sem correção de segurança
- Use um WAF e uma Content-Security-Policy para bloquear scripts inline e de origens não autorizadas

Erros relacionados

- [Como corrigir vulnerabilidade SQL Injection no WordPress](https://full.services/wp-fixer/corrigir-sql-injection-wordpress/)
- [Como remover malware de um site WordPress](https://full.services/wp-fixer/remover-malware-wordpress/)
- [Como corrigir API REST do WordPress exposta](https://full.services/wp-fixer/corrigir-api-rest-exposta-wordpress/)

## Causa

- Plugin ou tema que exibe entrada do usuário (comentário, formulário, parâmetro de URL) sem escapar a saída.
- Uso de echo direto de $_GET ou $_POST no código sem passar por esc_html() ou esc_attr().
- Plugin desatualizado com uma vulnerabilidade XSS conhecida e já catalogada (CVE/WPScan) ainda não corrigida.
- Campo que aceita HTML sem filtrar por wp_kses(), permitindo a passagem de tags de script.
- Falta de Content-Security-Policy, deixando o navegador executar scripts inline injetados.

## Como resolver

1. Identifique a origem da falha: rode um scanner (WPScan ou plugin de segurança) para descobrir qual plugin/tema tem a vulnerabilidade XSS reportada e em qual versão ela foi corrigida.
2. Atualize o plugin ou tema vulnerável: na maioria dos casos a brecha já tem correção. Atualize para a versão que fecha o XSS; se o componente foi abandonado, substitua-o por uma alternativa mantida.
3. Sanitize a entrada e escape a saída no seu código: se a falha está em código próprio, limpe o dado ao receber e escape ao exibir. Nunca dê echo de entrada do usuário sem tratar.
4. Adicione um cabeçalho Content-Security-Policy: configure uma CSP que restrinja a execução de scripts inline e de origens externas, reduzindo o impacto de qualquer injeção que escape.
5. Limpe injeções já gravadas e troque as chaves: procure scripts salvos em posts, comentários e wp_options, remova-os, regenere as SALT keys do wp-config.php e troque as senhas de admin para invalidar sessões roubadas.

## Código

```php
// Errado: exibe a entrada do usuario direto, abrindo XSS refletido
echo $_GET['nome'];

// Certo: escapa a saida conforme o contexto (texto, atributo, URL)
echo esc_html( $_GET['nome'] );                 // dentro de texto/HTML
echo '<input value="' . esc_attr( $_GET['nome'] ) . '">'; // dentro de atributo
echo '<a href="' . esc_url( $_GET['link'] ) . '">';      // dentro de href

// Para salvar conteudo que aceita HTML limitado, filtre com wp_kses
$permitido = array( 'a' => array( 'href' => array() ), 'strong' => array(), 'em' => array() );
$conteudo_seguro = wp_kses( $_POST['bio'], $permitido );
update_user_meta( $user_id, 'bio', $conteudo_seguro );
```

## Perguntas frequentes

### Qual a diferença entre XSS refletido e XSS armazenado?

No refletido, o script vem na URL e só afeta quem clica no link malicioso. No armazenado, o código fica salvo no banco (um comentário, por exemplo) e dispara para todo visitante da página. O armazenado é mais grave porque atinge qualquer um sem ação extra.

### Um plugin de segurança corrige o XSS sozinho?

Ele detecta e pode bloquear tentativas via WAF, mas não conserta o código vulnerável. A correção real é atualizar o plugin/tema com a falha ou escapar a saída no seu próprio código. O firewall é uma camada de defesa, não a solução de raiz.

### Como descubro qual plugin tem a vulnerabilidade XSS?

Rode o WPScan ou um scanner de segurança: ele cruza seus plugins com bancos de vulnerabilidades conhecidas e aponta o componente, a versão afetada e a versão que corrige. A partir daí, basta atualizar ou substituir.

### Escapar a saída ou sanitizar a entrada: qual é o certo?

Os dois, mas escapar a saída é a defesa principal contra XSS. Sanitize ao gravar para guardar dado limpo, e escape ao exibir conforme o contexto (esc_html, esc_attr, esc_url). Escapar na saída garante que nada injetado vire script executável.

### A Content-Security-Policy resolve o XSS por si só?

Não resolve, mas reduz muito o estrago. Uma CSP bem configurada impede o navegador de executar scripts inline e de origens não autorizadas, então mesmo que uma injeção passe, o script tende a não rodar. É uma camada extra sobre o escape correto.

### Removi o plugin vulnerável mas o site ainda redireciona. E agora?

O XSS pode ter deixado scripts gravados no banco. Procure código injetado em posts, comentários e wp_options, remova-o, regenere as SALT keys e troque as senhas de admin. Sem limpar o que ficou salvo, o redirecionamento persiste mesmo sem o plugin.

**Fonte:** [CVE-2023-2745 — WordPress XSS (block themes preview)](https://www.cve.org/CVERecord?id=CVE-2023-2745)
