O caso: aplicação legítima bloqueada com HTTP 403#
Ambiente: Servidor cPanel/WHM em AlmaLinux/CloudLinux Sintoma: Requisições legítimas retornando HTTP 403 Forbidden para um domínio específico Objetivo: Diagnosticar o bloqueio e desativar o ModSecurity para o domínio específico ou criar uma exceção fina de regra via SSH (sem interface gráfica do WHM)
O diagnóstico do 403 em logs do Apache /usr/local/apache/logs/error_log:
[Wed May 01 21:40:00.123456 2025] [:error] [pid 12345] [client 203.0.113.45:52341]
ModSecurity: Access denied with code 403 (phase 2).
Pattern match "(?i)(?:\\b(?:(?:s(?:elect\\b(?:.{1,100}?\\b(?:(?:length|count|top)\\b.
{1,100}?\\bfrom|from\\b.{1,100}?\\bwhere)|.*?\\b(?:d(?:ump\\b.*\\bfrom|ata_type)|
(?:to_(?:numbe|cha)|inst)r))|p_(?:(?:addextendedpro|sqlexe)c|(?:oacreat|prepar)e|
execute(?:sql)?|makewebtask)|ql_(?:longvarchar|variant))..." at ARGS:description.
[file "/etc/apache2/conf.d/modsec_vendor_configs/OWASP3/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.rlz"]
[line "45"] [id "942100"] [rev ""] [msg "SQL Injection Attack Detected via libinjection"]
[data "Matched Data: ..."] [severity "CRITICAL"] [ver "OWASP_CRS/3.3.4"]
[hostname "meudominio.com.br"] [uri "/admin/api/content"] [unique_id "YzX9..."]
A aplicação usa campos de texto livre que acionam a regra OWASP 942100 (SQL Injection via libinjection). O false-positive é um campo de descrição legítimo com sintaxe SQL em documentação técnica.
O erro: anatomia do falha na whmapi1#
A primeira tentativa foi usar a API administrativa do WHM, conforme intuição natural de quem gerencia via CLI:
whmapi1 toggle_modsec_for_domain domain=meudominio.com.br state=0
Retorno completo da API:
---
metadata:
command: toggle_modsec_for_domain
reason: Unknown app ("toggle_modsec_for_domain") requested for this version (1) of the API.
result: 0
version: 1
O campo reason é explícito: Unknown app ("toggle_modsec_for_domain"). O endpoint não existe na whmapi1.
Análise arquitetural: WHM API vs. UAPI - separação de escopos#
A confusão é compreensível porque tanto o WHM quanto o cPanel gerenciam o ModSecurity, mas em camadas diferentes da hierarquia:
WHM (Web Host Manager) - Escopo: SERVIDOR
│
│ whmapi1 / whm_api2
│ ├── Criar/remover contas cPanel
│ ├── Reiniciar serviços (Apache, MySQL, etc.)
│ ├── Configurar IP addresses
│ ├── Gerenciar ModSecurity GLOBALMENTE (enable/disable no servidor todo)
│ └── ❌ NÃO gerencia configurações por domínio/vhost individual
│
└── cPanel - Escopo: CONTA (usuário/domínio)
│
│ UAPI (uapi) - API v3 atual
│ ├── Gerenciar domínios addon e parked
│ ├── Criar email accounts
│ ├── Gerenciar databases
│ └── ✅ Módulo ModSecurity: enable/disable por domínio
Por que essa separação existe:
O ModSecurity por domínio é implementado através de diretivas no VirtualHost Apache específico de cada conta cPanel. A linha no httpd.conf gerada pelo cPanel/EasyApache é baseada em arquivos de include. A whmapi1 não tem acesso direto para operar em contexto de conta individual - esse é o domínio exclusivo da UAPI.
O protocolo de segurança e solução prática#
Passo 1 - identificar o proprietário do domínio#
/scripts/whoowns meudominio.com.br
Saída: meuusuario
O script /scripts/whoowns consulta o arquivo /etc/userdomains - um mapa plano domínio→usuário mantido pelo cPanel:
# Verificação manual alternativa
grep "meudominio.com.br" /etc/userdomains
# meudominio.com.br: meuusuario
Passo 2 - validação de falso positivo e triagem inicial#
Antes de efetuar alterações, valide se o endpoint realmente aciona o bloqueio com tráfego legítimo utilizando o curl:
curl -X POST https://meudominio.com.br/admin/api/content \
-H "Content-Type: application/json" \
-d '{"description": "teste"}' \
-v 2>&1 | grep -i "403\|modsecurity"
Verifique se a assinatura da regra 942100 é a única ou a principal causadora dos bloqueios no domínio em questão:
grep "meudominio.com.br" /usr/local/apache/logs/error_log | grep "942100" | wc -l
Passo 3 - protocolo de backup pré-configuração#
Nunca altere arquivos de configuração ou rode comandos de rebuild sem antes garantir pontos de restauração:
# Criar backup completo do diretório de userdata
tar czf /root/modsec-backup-$(date +%Y%m%d).tar.gz /etc/apache2/conf.d/userdata/
# Fazer cópia de segurança do arquivo de modsec específico, se ele já existir
cp /etc/apache2/conf.d/userdata/ssl/2/meuusuario/meudominio.com.br/modsec.conf \
/root/modsec.conf.bak.$(date +%Y%m%d) 2>/dev/null || echo "Nenhum arquivo modsec.conf existente para este domínio."
Passo 4 - alternativa recomendada: exceção fina de regra#
Em vez de desabilitar o ModSecurity completamente (o que exporia a aplicação a múltiplos ataques), edite ou crie o arquivo de userdata para aplicar uma exceção apenas para a regra 942100.
Diretório para HTTPS: /etc/apache2/conf.d/userdata/ssl/2/meuusuario/meudominio.com.br/modsec.conf
Diretório para HTTP (opcional, mas recomendado para consistência): /etc/apache2/conf.d/userdata/2/meuusuario/meudominio.com.br/modsec.conf
Exemplo de Exceção para o VHost Inteiro:
<IfModule mod_security2.c>
# Desabilitar apenas a regra 942100 (SQL Injection via libinjection)
SecRuleRemoveById 942100
</IfModule>
Exemplo de Exceção Restrita ao Endpoint Problemático (Ainda Mais Seguro):
<IfModule mod_security2.c>
# Desabilitar a regra apenas no URI correspondente
<LocationMatch "/admin/api/content">
SecRuleRemoveById 942100
</LocationMatch>
</IfModule>
Após editar os arquivos acima, reconstrua as configurações do Apache e recarregue o daemon:
# Validar e reconstruir a configuração do Apache
/scripts/rebuildhttpdconf
# Aplicar as mudanças sem derrubar conexões ativas
/usr/sbin/apachectl graceful
Solução alternativa: UAPI para desativação total (último recurso)#
Caso precise desativar completamente o ModSecurity para este domínio, execute a UAPI no contexto do usuário identificado:
uapi --user=meuusuario ModSecurity disable_domains domains=meudominio.com.br
Retorno completo de sucesso:
---
apiversion: 3
func: disable_domains
module: ModSecurity
result:
data:
-
dependencies: []
domain: meudominio.com.br
enabled: 0
exception: ~
searchhint: ''
type: main
errors: ~
messages: ~
metadata:
transformed: 1
status: 1
warnings: ~
O que acontece internamente após o comando da UAPI#
O cPanel realiza a seguinte sequência automatizada de operações:
1. Valida que meuusuario existe e é dono de meudominio.com.br
2. Cria (ou sobrescreve) o arquivo:
/etc/apache2/conf.d/userdata/ssl/2/meuusuario/meudominio.com.br/modsec.conf
3. Escreve a diretiva SecRuleEngine Off:
<IfModule mod_security2.c>
SecRuleEngine Off
</IfModule>
4. Replica a diretiva para a versão HTTP (non-SSL):
/etc/apache2/conf.d/userdata/2/meuusuario/meudominio.com.br/modsec.conf
5. Executa automaticamente: /scripts/rebuildhttpdconf
6. Executa: /usr/sbin/apachectl graceful ← reload sem quedas de conexões
Verificação pós-configuração e monitoramento#
Após realizar a alteração (seja via exceção fina ou desativação), siga estes passos de validação técnica:
- Testar o endpoint que estava bloqueado:
curl -I https://meudominio.com.br/admin/api/content
# Deve retornar HTTP 200 OK (ou o código esperado pela aplicação, não mais 403)
- Verificar se outras regras de segurança permanecem ativas (Teste de Blindagem):
Se você utilizou a Abordagem de Exceção Fina, envie um payload malicioso alternativo (como uma tag de script XSS) para garantir que o WAF bloqueia tentativas de ataque legítimas:
curl -X POST https://meudominio.com.br/admin/api/content \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "payload=<script>alert(1)</script>" \
-w "%{http_code}\n" -o /dev/null
# Deve retornar 403 (ModSecurity bloqueando o XSS de forma saudável)
- Pesquisar logs por novos erros:
tail -50 /usr/local/apache/logs/error_log | grep "meudominio.com.br"
Triagem sistêmica avançada e módulos complementares#
1. Auditoria de outros domínios com ModSecurity desativado#
Verifique se há outras brechas de segurança de WAF na mesma conta de usuário:
uapi --user=meuusuario ModSecurity list_domains | grep -B1 -A2 "enabled: 0"
Verifique estatísticas das regras mais acionadas no servidor para entender o impacto global das regras do CRS:
grep "id \"" /usr/local/apache/logs/error_log | awk -F'id "' '{print $2}' | awk -F'"' '{print $1}' | sort | uniq -c | sort -rn | head -15
2. Verificação de módulos Apache adicionais#
Às vezes o cliente continua recebendo erros HTTP 403 ou timeouts devido a outros módulos de segurança ativos no Apache que também policiam conexões. Audite quais módulos estão ativos:
apachectl -M | grep -E "evasive|limitipconn|reqtimeout"
- mod_evasive: Limita acessos por IP e URI para evitar DoS/DDoS.
- mod_limitipconn: Limita conexões simultâneas por IP.
- mod_reqtimeout: Gerencia tempos limite de cabeçalho e corpo da requisição.
3. Configuração de logging de auditoria do ModSecurity#
Se os logs do Apache não mostrarem detalhes suficientes para diagnosticar falsos positivos complexos, garanta que a auditoria detalhada do ModSecurity esteja ativa para a requisição:
# No arquivo /etc/apache2/conf.d/modsec2.conf ou WHM ModSecurity Configure
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogParts ABIJDEFHX
SecAuditLog /var/log/apache2/modsec_audit.log
SecAuditLogType Serial
4. Verificação de versão#
Sempre documente a versão do ecossistema e das regras CRS instaladas para compatibilidade de sintaxe:
# Versão do cPanel/WHM
cat /usr/local/cpanel/version
# Versão do ModSecurity ativa no daemon
httpd -M | grep -i security
# Ou consulte o log de inicialização do Apache
grep -i "ModSecurity" /usr/local/apache/logs/error_log | head -n 5
Fluxo de decisão visual#
Checklist de troubleshooting ModSecurity#
## Checklist: ModSecurity 403 - diagnóstico e correção
### 1. Diagnóstico e triagem
- [ ] Verificar logs de erro do Apache: `tail -100 /usr/local/apache/logs/error_log | grep 403`
- [ ] Identificar a regra CRS (ID e arquivo correspondente) causadora do bloqueio
- [ ] Validar o falso positivo reproduzindo a requisição via `curl`
- [ ] Verificar se outros domínios da conta estão apresentando o mesmo comportamento
### 2. Solução e modelagem de regras
- [ ] Criar exceção para a regra específica via `SecRuleRemoveById` (preferencial)
- [ ] Restringir a exceção ao endpoint correto utilizando `<LocationMatch>`
- [ ] Desabilitar completamente o ModSecurity para o domínio (apenas como último recurso)
### 3. Implementação segura
- [ ] Gerar backup completo dos diretórios userdata: `tar czf /root/modsec-backup.tar.gz /etc/apache2/conf.d/userdata/`
- [ ] Criar ou modificar o arquivo `modsec.conf` no caminho userdata adequado (SSL e non-SSL)
- [ ] Reconstruir a configuração de vhosts: `/scripts/rebuildhttpdconf`
- [ ] Recarregar o Apache de forma suave: `/usr/sbin/apachectl graceful`
### 4. Validação técnica
- [ ] Testar o URI problemático e certificar o retorno HTTP esperado
- [ ] Auditar logs de erro para garantir a ausência de novos bloqueios na requisição
- [ ] Garantir o bloqueio ativo contra outros vetores (como XSS com `<script>`)
- [ ] Monitorar a estabilidade do domínio por 24h
### 5. Documentação e auditoria pós-configuração
- [ ] Registrar exceção criada, motivo do falso positivo e data de revisão
- [ ] Confirmar o status do domínio via UAPI
- [ ] Testar e documentar o procedimento de rollback
Plano de rollback#
Em caso de instabilidade, erros sintáticos detectados no reinício do serviço Apache, ou novos requisitos de segurança, siga este roteiro de rollback:
Rollback manual (restaurar do backup de userdata)#
Restaure os arquivos a partir da cópia de segurança gerada no início das alterações:
# Restaurar o arquivo individual
cp /root/modsec.conf.bak.YYYYMMDD /etc/apache2/conf.d/userdata/ssl/2/meuusuario/meudominio.com.br/modsec.conf
# Se o arquivo não existia originalmente, exclua o arquivo criado para remover a exceção:
rm -f /etc/apache2/conf.d/userdata/ssl/2/meuusuario/meudominio.com.br/modsec.conf
rm -f /etc/apache2/conf.d/userdata/2/meuusuario/meudominio.com.br/modsec.conf
# Reconstruir e recarregar o Apache
/scripts/rebuildhttpdconf
/usr/sbin/apachectl graceful
Rollback via API cPanel (reabilitar ModSecurity no domínio)#
Se você usou a UAPI para desativar o ModSecurity, você pode reativá-lo com:
uapi --user=meuusuario ModSecurity enable_domains domains=meudominio.com.br
Tabela de referência: whmapi1 vs. UAPI para ModSecurity#
| Ação | Ferramenta correta | Comando |
|---|---|---|
| Desativar para 1 domínio | uapi | uapi --user=X ModSecurity disable_domains domains=Y |
| Reativar para 1 domínio | uapi | uapi --user=X ModSecurity enable_domains domains=Y |
| Listar status por conta | uapi | uapi --user=X ModSecurity list_domains |
| Desativar globalmente | whmapi1 | whmapi1 modsec_disable_all_domains |
| Ver configuração global | whmapi1 | whmapi1 modsec_get_settings |
| Ver log de audits ModSec | whmapi1 | whmapi1 modsec_get_log |
Este artigo foi útil?
Deixe uma reação rápida para apoiar o conteúdo:
Este post está licenciado sob CC BY-NC.



Comentários
Participe da discussão abaixo.
0 comentários