141 regras OWASP ativas, zero falsos positivos: como configuramos o WAF da OCI para WordPress
Publicado em 24 de março de 2026

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:
!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.