Buzeli
buzeliSoluções Digitais
Segurança

141 regras OWASP ativas, zero falsos positivos: como configuramos o WAF da OCI para WordPress

Publicado em 24 de março de 2026

141 regras OWASP ativas, zero falsos positivos — WAF OCI para WordPress de alto tráfego

O ponto de partida

Durante a migração de um portal WordPress de alto tráfego de AWS para OCI, uma das primeiras tarefas foi recriar a proteção WAF que existia na AWS (WebACL com regras OWASP + custom rules). A OCI oferece um WAF integrado ao Load Balancer sem custo adicional no tier básico — o que seria uma economia de $271/mês comparado à AWS.

O desafio não é ativar o WAF. É ativar as 141 regras OWASP e não quebrar nada em produção.

Regras OWASP bloqueiam padrões. Sites WordPress de alto tráfego geram padrões que parecem ataques — cookies de analytics, parâmetros de URL com caracteres especiais, headers de autenticação. Sem ajuste fino, a taxa de falsos positivos é alta.

A estrutura do OCI WAF

O WAF da OCI funciona em dois pipelines independentes, e entender isso é fundamental para não errar na configuração:

Request Access Control: regras que permitem (ALLOW) ou bloqueiam (BLOCK) com base em condições como IP, geo, headers, cookies. Avaliadas primeiro.

Request Protection (OWASP): as 141 capabilities que inspecionam o conteúdo da requisição em busca de SQLi, XSS, LFI, RFI e outros padrões maliciosos. Avaliadas independentemente do Access Control.

Uma regra ALLOW no Access Control não impede as Protection Rules de inspecionarem o request. Os dois pipelines são independentes.

Essa foi a descoberta mais importante da configuração: Access Control ALLOW não faz bypass do OWASP. Para bypass condicional, a condição deve estar na própria Protection Rule.

As 141 regras OWASP

As capabilities OWASP do OCI WAF cobrem as principais categorias de ataque:

942xxx — SQL Injection (SQLi): detecção de payloads SQL em args, headers e cookies.

941xxx — Cross-Site Scripting (XSS): detecção de scripts injetados em qualquer parte do request.

930xxx — Local File Inclusion (LFI): detecção de path traversal e acesso a arquivos locais.

931xxx — Remote File Inclusion (RFI): detecção de inclusão de arquivos remotos via URL em parâmetros.

Todas as 141 capabilities foram ativadas no modo BLOCK desde o início. Em seguida começou o trabalho real: identificar e resolver os falsos positivos antes de apontar o tráfego real.

Os falsos positivos que encontramos

1. Cookies de analytics disparando SQLi

O maior problema foi imediato: cookies de ferramentas de analytics (Google Analytics, Facebook Pixel, TikTok Ads e outras) contêm valores com padrões de caracteres especiais — cifrões, hifens, números em sequência — que o OWASP CRS classifica como possível SQL Injection.

Um cookie com valor no formato `-1234-5678.90-` parece, para as regras 942xxx, um fragmento de SQLi com operadores numéricos. Mesma lógica para JSON encodado em cookies de ferramentas de consentimento (Privaci, OneTrust e similares).

Solução: 42 cookies foram adicionados à lista de exclusões em todas as 141 capabilities. Isso instrui o WAF a não inspecionar o valor desses cookies específicos, mantendo a proteção para todos os outros campos.

2. O parâmetro url do Next.js Image

O endpoint `/_next/image?url=https://...` usa um parâmetro chamado `url` que contém uma URL completa. As regras 931xxx (RFI) e 930xxx (LFI) detectam URLs em parâmetros como indicativo de inclusão remota de arquivos — tecnicamente correto como padrão, mas falso positivo para esse endpoint legítimo.

Solução: O argumento `url` foi excluído das regras SQLi (942xxx), RFI (931xxx) e LFI (930xxx). Risco aceito e documentado: se um atacante enviar payload SQLi especificamente no parâmetro `url`, o WAF não bloquearia.

3. Usuários logados no WordPress

Administradores e editores do WordPress carregam cookies de autenticação (`wordpress_logged_in_*` e `wordpress_sec_*`) cujos valores são hashes base64 contendo caracteres que as regras OWASP interpretam como potencial ataque. Resultado: usuários logados eram bloqueados ao navegar no wp-admin.

A solução correta não é excluir os cookies — é fazer bypass condicional do OWASP inteiro quando o usuário está autenticado. E aqui surgiu a armadilha mais sutil do OCI WAF.

A armadilha: como fazer bypass condicional do OWASP

A abordagem intuitiva é criar uma regra ALLOW no Access Control para quando o cookie `wordpress_logged_in_*` estiver presente. Isso não funciona — os pipelines são independentes, conforme explicado acima.

A abordagem correta é adicionar uma condição diretamente na Protection Rule do OWASP, instruindo o WAF a só aplicar as regras quando a condição for verdadeira (usuário não autenticado).

A condição que funciona:

Copiar
!contains(to_string(keys(http.request.cookies)), 'wordpress_logged_in_')

Tradução: aplique o OWASP somente quando a lista de nomes de cookies NÃO contiver o prefixo `wordpress_logged_in_`. Como o sufixo hash do cookie varia por instalação, o match por prefixo via `contains()` na string concatenada dos nomes é a única forma portável.

Atenção: `http.request.headers.cookie` não funciona como string no runtime do OCI WAF, mesmo que a API aceite a configuração. Use sempre `http.request.cookies` (mapa de cookies parseados) com `keys()` para acessar os nomes.

Integração com o Load Balancer do OKE

No OCI, quando o cluster OKE provisiona um Load Balancer via Cloud Controller Manager (CCM), o WAF Policy deve ser anexado a esse LB — não a um LB criado manualmente. Tentativas de criar um LB separado para o WAF e colocar o LB do CCM atrás resultam em complexidade desnecessária e problemas de roteamento.

Fluxo correto: Internet → OCI WAF Policy (anexada ao LB do CCM) → Nodes OKE → Pods.

Um detalhe importante ao usar Nginx dentro dos pods atrás desse LB: o `$binary_remote_addr` passa a ser o IP do Load Balancer, não o IP real do cliente. Isso quebra qualquer rate limiting baseado em IP.

Correção no Nginx: adicionar `set_real_ip_from` com os CIDRs das subnets do LB e `real_ip_header X-Forwarded-For`. Sem isso, todos os clientes compartilham o mesmo bucket de rate limit.

Paridade com o WAF da AWS

Após toda a configuração, comparamos o OCI WAF com o WebACL que existia na AWS. O resultado foi paridade total nas proteções que importavam:

OWASP Core Rule Set: equivalente em ambas as plataformas.

Bypass para usuários autenticados: implementado via condição no OCI, via custom rule na AWS.

IP Reputation List: ausente no tier gratuito OCI, compensada pelo CrowdSec instalado na VM WordPress — que bloqueia IPs maliciosos com base em inteligência coletiva.

O resultado

141 regras OWASP ativas em produção, zero falsos positivos para usuários finais, zero para editores e administradores WordPress. SQLi, XSS, LFI e RFI bloqueados. Custo: $0/mês (incluso no Flexible Load Balancer da OCI).

O trabalho de ajuste fino levou cerca de dois dias. É um investimento que vale: WAF com regras agressivas mal calibradas é pior do que WAF desligado — bloqueia usuários legítimos e gera desconfiança na ferramenta.

WAF não é ligar um interruptor. É calibração contínua entre proteção e usabilidade. Feito certo, é invisível para o usuário e intransponível para o atacante.