diff --git a/.gemini/TODO.md b/.gemini/TODO.md new file mode 100644 index 0000000..f3616c1 --- /dev/null +++ b/.gemini/TODO.md @@ -0,0 +1,18 @@ +# Tarefas Pendentes e Melhorias Futuras + +## 1. Gestão Dinâmica de DNS +**Origem:** Migração de `legacy/hosts` +- **Problema:** O método atual usa `extra_hosts` no `docker-compose.yml`, que é estático e exige recriação do container para alterações. +- **Objetivo:** Mudar o modo de registro e atualização de DNS para ser mais dinâmico ou simples. +- **Ideias:** DNS containerizado (Bind/CoreDNS) ou Service Discovery. + +## 2. Revisão de Regras ModSecurity +**Origem:** Migração de `legacy/nginx/modsecurity/*.conf` (Regras Antigas) +- **Status:** ⚠️ Parcial (Arquivos em `modsec_rules/`, mas injeção desabilitada). +- **Objetivo:** Rever todas as regras para fazerem sentido no contexto atual (OWASP CRS v4) ou mudar o método de inserção. +- **Ação:** Auditar exceções de Gitea, Grafana, etc., e reativar apenas o necessário. + +## 3. Atualizações Zero-Downtime (Sem Queda) +**Objetivo:** Criar um método para atualizar configurações de sites sem que clientes externos percam a conexão. +- **Cenário Atual:** Restart do container ou reload podem causar breves interrupções se não gerenciados corretamente. +- **Solução Proposta:** Implementar scripts de "Reload Suave" (`nginx -s reload`) com validação prévia (`nginx -t`) automatizada, garantindo que conexões ativas terminem graciosamente. diff --git a/docker-compose.yml b/docker-compose.yml index f8d8d7d..662cf97 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -17,8 +17,22 @@ services: volumes: - ./ssl:/etc/nginx/ssl:ro - modsec_logs:/var/log/modsecurity + # - ./modsec_rules:/etc/nginx/modsecurity.d/custom_rules + # - ./modsec_includes.conf:/etc/nginx/modsecurity.d/modsecurity-override.conf depends_on: - nginx-proxy + extra_hosts: + - "srvproxy001.itguys.com.br:172.16.254.1" + - "srvproxy001:172.16.254.1" + - "git.itguys.com.br:10.10.253.128" + - "git:10.10.253.128" + - "zammad.itguys.com.br:172.16.254.59" + - "zammad:172.16.254.59" + - "cloud.grupopralog.com.br:172.16.253.12" + - "business.itguys.com.br:172.16.121.13" + - "verbocloud.itguys.com.br:172.16.253.13" + - "srvoffice001.itguys.com.br:172.16.253.101" + - "srvoffice001:172.16.253.101" # ============================================ # NGINX Proxy (Backend do ModSecurity) diff --git a/modsec_includes.conf b/modsec_includes.conf new file mode 100644 index 0000000..fa921f3 --- /dev/null +++ b/modsec_includes.conf @@ -0,0 +1,2 @@ +# Include all custom rules form legacy migration +include /etc/nginx/modsecurity.d/custom_rules/*.conf diff --git a/modsec_rules/exchange-rule-exceptions.conf b/modsec_rules/exchange-rule-exceptions.conf new file mode 100644 index 0000000..1014363 --- /dev/null +++ b/modsec_rules/exchange-rule-exceptions.conf @@ -0,0 +1,8 @@ +# Ficheiro de Exceções do ModSecurity para o Microsoft Exchange + +# Desativa completamente o motor de regras do ModSecurity para QUALQUER URL +# que comece com /owa/ ou /ecp/. +# Isto resolve os falsos positivos que bloqueiam a funcionalidade legítima +# do Outlook Web App e do Exchange Admin Center. +SecRule REQUEST_URI "@rx ^/(owa|ecp)/" \ + "id:1003,phase:1,nolog,allow,ctl:ruleEngine=Off" diff --git a/modsec_rules/gitea-rule-exceptions.conf b/modsec_rules/gitea-rule-exceptions.conf new file mode 100644 index 0000000..1bb33f2 --- /dev/null +++ b/modsec_rules/gitea-rule-exceptions.conf @@ -0,0 +1,7 @@ +# Ficheiro de Exceções do ModSecurity para o Gitea (VERSÃO FINAL E COMPLETA) + +# Desativa completamente o motor de regras do ModSecurity para QUALQUER URL +# que envolva a visualização, edição, criação ou visualização de commits de ficheiros no Gitea. +# A expressão regular agora apanha os caminhos "/src/branch/", "/_edit/", "/_new/" e "/commits/branch/". +SecRule REQUEST_URI "@rx ^/.*/(src/branch|_edit|_new|commits/branch)/" \ + "id:1005,phase:1,nolog,allow,ctl:ruleEngine=Off" diff --git a/modsec_rules/global-exceptions.conf b/modsec_rules/global-exceptions.conf new file mode 100644 index 0000000..e54a759 --- /dev/null +++ b/modsec_rules/global-exceptions.conf @@ -0,0 +1,192 @@ +# ========================================================================== +# Arquivo Global de Exceções do ModSecurity +# ========================================================================== +# Este arquivo centraliza todas as regras de exceção para as aplicações. +# Todos os IDs foram reorganizados para serem únicos. +SecRule REMOTE_ADDR "@ipMatch 172.16.0.0/16,10.10.0.0/16,10.11.0.0/16,10.12.0.0/16" \ + "id:10000, \ + phase:1, \ + pass, \ + nolog, \ + ctl:ruleEngine=Off, \ + msg:'WHITELIST: Acesso permitido da rede interna, ModSecurity desativado'" +# -------------------------------------------------------------------------- +# Exceções para o Nextcloud +# -------------------------------------------------------------------------- +# Desliga o motor de regras para as rotas de sincronização (WebDAV). +SecRule REQUEST_URI "@beginsWith /remote.php" "id:10001,phase:1,nolog,pass,ctl:ruleEngine=Off" +SecRule REQUEST_URI "@streq /.well-known/caldav" "id:10002,phase:1,nolog,pass,ctl:ruleEngine=Off" +SecRule REQUEST_URI "@streq /.well-known/carddav" "id:10003,phase:1,nolog,pass,ctl:ruleEngine=Off" +# -------------------------------------------------------------------------- +# Exceções para o Zabbix +# -------------------------------------------------------------------------- +# Desliga o ModSecurity para a API JSON-RPC e zabbix.php. +SecRule REQUEST_URI "@rx (api_jsonrpc\.php|jsrpc\.php|zabbix\.php)" "id:10004,phase:1,nolog,pass,ctl:ruleEngine=Off" +# Desativa regras específicas na página de Descoberta de Hosts. +# Lembre-se de substituir os IDs abaixo pelos que encontrou no seu log. +SecRule REQUEST_URI "@beginsWith /zabbix/host_discovery.php" "id:10005,phase:1,nolog,allow,ctl:ruleRemoveById=9XXXXX,ctl:ruleRemoveById=9YYYYY" +# -------------------------------------------------------------------------- +# Exceções para o Microsoft Exchange +# -------------------------------------------------------------------------- +# Desliga o ModSecurity para o Outlook Web App (OWA) e o Exchange Admin Center (ECP). +SecRule REQUEST_URI "@rx ^/(owa|ecp)/" "id:10006,phase:1,nolog,allow,ctl:ruleEngine=Off" + +# -------------------------------------------------------------------------- +# Exceções para o Zammad +# -------------------------------------------------------------------------- +# Desativa regra de falso positivo para a API do Zammad. +# Lembre-se de substituir '9XXXXX' pelo ID da regra real. +SecRule REQUEST_URI "@beginsWith /api/v1/" "id:10007,phase:1,nolog,allow,ctl:ruleRemoveById=9XXXXX" + +# -------------------------------------------------------------------------- +# Exceções para o Gitea +# -------------------------------------------------------------------------- +# Desliga o motor de regras para operações de ficheiros no Gitea. +SecRule REQUEST_URI "@rx ^/.*/(src/branch|_edit|_new|commits/branch)/" "id:10008,phase:1,nolog,allow,ctl:ruleEngine=Off" +SecRule REQUEST_URI "@rx ^/.*/.*(raw|assets)/" "id:10011,phase:1,nolog,pass,ctl:ruleEngine=Off" +SecRule REQUEST_FILENAME "@rx \.conf$" "id:10013,phase:1,nolog,pass,chain,msg:'[CUSTOM] Whitelist .conf files for Git server'" + SecRule SERVER_NAME "@streq git.itguys.com.br" "ctl:ruleRemoveById=930120" +SecRule REQUEST_URI "@rx ^/[^/]+/[^/]+/upload-file$" \ + "id:10025, \ + phase:1, \ + pass, \ + nolog, \ + ctl:ruleEngine=Off, \ + msg:'TUNING: ModSecurity desativado para a rota de upload de arquivos do Gitea'" +SecRule REQUEST_URI "@rx ^/[^/]+/[^/]+/wiki$" \ + "id:10026, \ + phase:1, \ + pass, \ + nolog, \ + ctl:ruleEngine=Off, \ + msg:'TUNING: ModSecurity desativado para a rota de wiki do Gitea'" +# -------------------------------------------------------------------------- +# Exceções para o Grafana +# -------------------------------------------------------------------------- +# Desativa a regra de falso positivo para a API de dashboards. +# Lembre-se de substituir '9XXXXX' pelo ID da regra real. +SecRule REQUEST_URI "@beginsWith /api/dashboards/" "id:10009,phase:1,nolog,allow,ctl:ruleRemoveById=9XXXXX" + +# -------------------------------------------------------------------------- +# Exceções para a Geração de Prévias (Thumbnails) do Nextcloud +# -------------------------------------------------------------------------- +# Desativa a regra de falso positivo que bloqueia a criação de miniaturas. +# Substitua '9XXXXX' pelo ID real encontrado no log de auditoria. +SecRule REQUEST_URI "@beginsWith /index.php/core/preview" "id:10010,phase:1,nolog,pass,ctl:ruleRemoveById=9XXXXX + +# -------------------------------------------------------------------------- +# Exceções para o Nextcloud Office Online +# -------------------------------------------------------------------------- +# Desliga completamente o motor de regras para as rotas de comunicação do +# Office Online, que geram muitos falsos positivos. +# As rotas são /hosting/discovery, /hosting/wopi/ e /op/. +SecRule REQUEST_URI "@rx ^/(hosting|op|we|wv|p|x|lo|m|o)/" "id:10014,phase:1,nolog,pass,ctl:ruleEngine=Off" +SecRule REQUEST_URI "@streq /index.php/apps/officeonline/ajax/admin.php" "id:10015,phase:1,nolog,pass,ctl:ruleEngine=Off" + +# Exceções para a API do UniFi Controller +# -------------------------------------------------------------------------- +# Desativa a regra que bloqueia o método 'PUT' para a API. +SecRule REQUEST_URI "@beginsWith /api/" "id:10012,phase:1,nolog,pass,ctl:ruleEngine=Off" + +# Exceção para o Editor de Texto (Nextcloud Text) +# -------------------------------------------------------------------------- +# Desliga o motor de regras para a criação de sessão do editor de texto, +# que é bloqueada por regras de segurança (falso positivo). +SecRule REQUEST_URI "@beginsWith /apps/text/session" "id:10016,phase:1,nolog,pass,ctl:ruleEngine=Off" +SecRule REQUEST_URI "@streq /apps/logreader/api/settings" "id:10020,phase:1,nolog,pass,ctl:ruleEngine=Off" +# ========================================================================================== +# NOVAS EXCEÇÕES - AJUSTADAS EM 2025-09-25 22:24 +# ------------------------------------------------------------------------------------------ +# MOTIVO: Corrige erros 403 (falsos positivos) em rotas da app "External Sites" do Nextcloud. +# MÉTODO: Em vez de desligar o motor, desabilita apenas as regras específicas que +# contribuem para o score de anomalia, mantendo as demais proteções. +# AÇÃO: Substitua 9XXXXX e 9YYYYY pelos IDs de regras encontrados no modsec_audit.log. + +# Exceção para a API de "sites externos". Bloqueava requisições PUT. +SecRule REQUEST_URI "@beginsWith /ocs/v2.php/apps/external/api/v1/sites" "id:10017,phase:1,nolog,pass,ctl:ruleEngine=Off" + +# Exceção para os ícones da app "sites externos". Bloqueava requisições DELETE. +SecRule REQUEST_URI "@beginsWith /apps/external/icons" "id:10018,phase:1,pass,nolog,ctl:ruleEngine=Off" +# ========================================================================================== +SecRule REQUEST_URI "@rx ^/(ocs/v2\.php/apps/user_status/api/v1/heartbeat|apps/files/api/v1/config/(sort_favorites_first|show_hidden|grid_view|folder_tree|sort_folders_first|crop_image_previews|show_dialog_file_extension))" \ + "id:10022, \ + phase:1, \ + pass, \ + nolog, \ + ctl:ruleEngine=Off, \ + msg:'TUNING: ModSecurity desativado para APIs de configuracao de UI do Nextcloud'" +SecRule REQUEST_URI "@rx ^/ocs/v2\.php/cloud/users|profile/.*" \ + "id:10023, \ + phase:1, \ + pass, \ + nolog, \ + ctl:ruleEngine=Off, \ + msg:'TUNING: ModSecurity desativado para a API de atualizacao de perfil de usuario do Nextcloud'" +SecRule REQUEST_URI "@streq /apps/files/api/v1/views" \ + "id:10024, \ + phase:1, \ + pass, \ + nolog, \ + ctl:ruleEngine=Off, \ + msg:'TUNING: ModSecurity desativado para a API de views de arquivos do Nextcloud'" +SecRule REQUEST_URI "@rx ^/(index\.php/core/preview|ocs/v2\.php/apps/user_status/api/v1/user_status)" \ + "id:10027, \ + phase:1, \ + pass, \ + nolog, \ + ctl:ruleEngine=Off, \ + msg:'TUNING: ModSecurity desativado para as APIs de Preview e User Status do Nextcloud'" +SecRule REQUEST_URI "@streq /ocs/v2.php/cloud/groups/details" \ + "id:10028, \ + phase:1, \ + pass, \ + nolog, \ + ctl:ruleEngine=Off, \ + msg:'TUNING: ModSecurity desativado para a API de busca de grupos do Nextcloud'" +SecRule REQUEST_URI "@beginsWith /ocs/v2.php/apps/forms/api/" \ + "id:10031, \ + phase:1, \ + pass, \ + nolog, \ + ctl:ruleEngine=Off, \ + msg:'TUNING: ModSecurity desativado para a API do Nextcloud Forms'" +SecRule REQUEST_METHOD "@streq PUT" "phase:1,id:1001,chain,nolog,pass" + SecRule REQUEST_URI "@rx ^/apps/integration_onedrive/(?:admin-config|sensitive-admin-config)$" \ + "t:none,ctl:ruleRemoveById=949110" +SecRule REQUEST_URI "@rx ^/(apps/tables/|ocs/v2\.php/apps/tables/)" \ + "id:10032, \ + phase:1, \ + pass, \ + nolog, \ + ctl:ruleEngine=Off, \ + msg:'TUNING: (Nuke) ModSecurity DESATIVADO para Nextcloud Tables'" +SecRule REQUEST_URI "@beginsWith /ocs/v2.php/apps/notifications/api/v2/notifications" \ + "id:10019, \ + phase:1, \ + nolog, \ + pass, \ + ctl:ruleEngine=Off, \ + msg:'TUNING: (Corrigido) ModSecurity DESATIVADO para API de Notificações'" +SecRule REQUEST_URI "@beginsWith /apps/files_pdfviewer/" \ + "id:10033, \ + phase:1, \ + pass, \ + nolog, \ + ctl:ruleRemoveById=949110, \ + msg:'TUNING: Remove bloqueio por Anomaly Score (949110) para Nextcloud PDF Viewer'" +SecRule REMOTE_ADDR "@ipMatch 172.16.254.1" \ + "id:10034, \ + phase:1, \ + pass, \ + nolog, \ + chain, \ + msg:'WHITELIST: [Proxy 172.16.254.1] Desativa WAF para Office Online (WOPI)'" + SecRule REQUEST_URI "@beginsWith /index.php/apps/officeonline/wopi/files/" \ + "ctl:ruleEngine=Off" +SecRule REQUEST_URI "@streq /apps/officeonline/index" \ + "id:10035, \ + phase:1, \ + pass, \ + nolog, \ + ctl:ruleEngine=Off, \ + msg:'TUNING: Desativa WAF para a pagina de indice do Office Online (falso positivo em GET)'" diff --git a/modsec_rules/grafana-rule-exceptions.conf b/modsec_rules/grafana-rule-exceptions.conf new file mode 100644 index 0000000..7e08f55 --- /dev/null +++ b/modsec_rules/grafana-rule-exceptions.conf @@ -0,0 +1,7 @@ +# Ficheiro de Exceções do ModSecurity para o Grafana + +# Desativa a regra 9XXXXX (que estava a causar um falso positivo com o método DELETE) +# APENAS para as requisições que começam com /api/dashboards/. +# Isto mantém a regra ativa para o resto do site. +SecRule REQUEST_URI "@beginsWith /api/dashboards/" \ + "id:1007,phase:1,nolog,allow,ctl:ruleRemoveById=9XXXXX" diff --git a/modsec_rules/nextcloud-rule-exceptions.conf b/modsec_rules/nextcloud-rule-exceptions.conf new file mode 100644 index 0000000..968d20b --- /dev/null +++ b/modsec_rules/nextcloud-rule-exceptions.conf @@ -0,0 +1,14 @@ +# -------------------------------------------------------------------------- +# Nextcloud: Exceções para o Nextcloud (Sintaxe para Nginx) +# -------------------------------------------------------------------------- +# Este arquivo contém regras de exclusão para o Nextcloud. +# A ação aqui desliga completamente o motor do ModSecurity para as rotas +# de sincronização (WebDAV), o que é funcional mas menos seguro. + +# Desliga o motor de regras para qualquer URL que comece com /remote.php +# Isso cobre o WebDAV e outras operações do cliente. +SecRule REQUEST_URI "@beginsWith /remote.php" "id:1001,phase:1,nolog,pass,ctl:ruleEngine=Off" + +# Desliga o motor de regras para as rotas de descoberta de CalDAV e CardDAV. +SecRule REQUEST_URI "@streq /.well-known/caldav" "id:1002,phase:1,nolog,pass,ctl:ruleEngine=Off" +SecRule REQUEST_URI "@streq /.well-known/carddav" "id:1003,phase:1,nolog,pass,ctl:ruleEngine=Off" diff --git a/modsec_rules/zabbix-rule-exceptions.conf b/modsec_rules/zabbix-rule-exceptions.conf new file mode 100644 index 0000000..9e8842f --- /dev/null +++ b/modsec_rules/zabbix-rule-exceptions.conf @@ -0,0 +1,11 @@ +# Ficheiro de Exceções do ModSecurity para o Zabbix (VERSÃO CORRIGIDA) + +# Regra 1: Desativa completamente o ModSecurity para a API JSON-RPC e zabbix.php. +# Esta regra continua a ser útil e está correta. +SecRule REQUEST_URI "@rx (jsrpc\.php|zabbix\.php)" \ + "id:1001,phase:1,nolog,allow,ctl:ruleEngine=Off" + +# Regra 2: Desativa as regras específicas que causam falsos positivos na página de Descoberta de Hosts. +# Lembre-se de substituir os IDs abaixo pelos que encontrou no seu log de auditoria. +SecRule REQUEST_URI "@beginsWith /zabbix/host_discovery.php" \ + "id:1002,phase:1,nolog,allow,ctl:ruleRemoveById=9XXXXX,ctl:ruleRemoveById=9YYYYY" diff --git a/modsec_rules/zammad-rule-exceptions.conf b/modsec_rules/zammad-rule-exceptions.conf new file mode 100644 index 0000000..0f61de6 --- /dev/null +++ b/modsec_rules/zammad-rule-exceptions.conf @@ -0,0 +1,7 @@ +# Ficheiro de Exceções do ModSecurity para o Zammad + +# Desativa a regra de falso positivo para toda a API do Zammad (/api/v1/). +# Isto previne que o WAF bloqueie as ações legítimas da interface. +# Lembre-se de substituir '9XXXXX' pelo ID da regra que encontrou no seu log de auditoria. +SecRule REQUEST_URI "@beginsWith /api/v1/" \ + "id:1004,phase:1,nolog,allow,ctl:ruleRemoveById=9XXXXX"