feat(wordpress): EMCP Tools workflow skills + widget catalogs + pending wordpress skills
- emcp-page-building, emcp-content-ops, emcp-site-audit: EMCP Tools MCP workflows verified live (atomic/legacy interplay, apply-template overwrite risk, create-theme-template goes live immediately, false-positive malware pattern in scan-security, change ledger + rollback) - elementor-pro-widgets: 30+5 native Elementor Pro widgets (curated catalog) - elementskit-widgets / powerpack-widgets: 42 + 97 third-party widgets, widgetType extracted from plugin source (not guessed by convention) - plugin.json bumped 1.2.0 -> 1.3.0, keywords + description updated - commits pending wordpress skills already present as untracked files (emcp-tools, wordfence, wp-activity-log, seguranca-descomplicar, webp-express, wp-fastest-cache, wp-font-perf, wp-meteor, wp-activity-log, redis-object-cache, app-for-cloudflare) and pending edits (rank-math, wp-cli, wp-content-seo-gate)
This commit is contained in:
@@ -0,0 +1,492 @@
|
||||
---
|
||||
name: wp-activity-log
|
||||
description: Gestão e auditoria do WP Activity Log (Melapress, slug wp-security-audit-log — rebranding do antigo "WP Security Audit Log") via WP-CLI/SQL em servidores CWP. Cobre consulta ao log de eventos (tabelas wsal_occurrences/wsal_metadata), replicação do padrão stealth mode + log restrito a um único utilizador, confirmação do gotcha "wp-cli bypassa restrições de UI", e gestão de retenção/volume do log. Usar quando "wp activity log", "wsal", "wp security audit log", "log de auditoria wordpress", "quem alterou isto no site", "histórico de acções wordpress", "esconder plugin de auditoria", "stealth mode plugin", "restringir log a um utilizador".
|
||||
---
|
||||
|
||||
# /wp-activity-log — WP Activity Log (Melapress) via WP-CLI/SQL
|
||||
|
||||
Plugin de log de auditoria WordPress (equivalente a Syslog para WP). Nome
|
||||
comercial mudou de "WP Security Audit Log" para **"WP Activity Log"**
|
||||
(rebranding Melapress) mas o **slug mantém-se `wp-security-audit-log`** — usar
|
||||
sempre este slug em `wp plugin get/activate/deactivate`, nunca o nome
|
||||
comercial.
|
||||
|
||||
**Fonte:** `CONFIG-Plugins-Referencia.md` §9 + verificação SSH ao vivo nesta
|
||||
sessão (`emanuelalmeida.pt`, versão `5.6.5`, prefixo de tabelas `wpne_`).
|
||||
|
||||
---
|
||||
|
||||
## Contexto CWP — sempre obrigatório
|
||||
|
||||
```bash
|
||||
PATH=/home/USER/public_html
|
||||
PREFIX=$(wp db prefix --allow-root --path=$PATH) # ex.: wpne_, wp_, wpah_
|
||||
```
|
||||
|
||||
**Acesso via SSH:** `server.descomplicar.pt`, porta 9443. **Existe sim um
|
||||
comando WP-CLI nativo** — corrige o que estava documentado antes: o plugin
|
||||
regista `WP_CLI::add_command( 'wsal_cli_commands', ... )` em
|
||||
`classes/class-wp-security-audit-log.php`. Ver §1.1 para a lista completa
|
||||
de subcomandos. Fora desses 7 comandos, o resto passa por `wp option`,
|
||||
`wp db query` e `wp eval`.
|
||||
|
||||
---
|
||||
|
||||
## 1. Identificação e configuração (18 opções `wp_options`)
|
||||
|
||||
Prefixos: `wsal_*` (config principal), `Wsal*` (raro), `fs_wsalp` (estado
|
||||
Freemius). Ler tudo de uma vez:
|
||||
|
||||
```bash
|
||||
wp option list --search='wsal*' --format=table --fields=option_name,option_value --allow-root --path=$PATH
|
||||
wp option get fs_wsalp --allow-root --path=$PATH
|
||||
wp plugin get wp-security-audit-log --format=json --allow-root --path=$PATH
|
||||
```
|
||||
|
||||
### Tabela de configuração real (`emanuelalmeida.pt`, verificado ao vivo)
|
||||
|
||||
| Opção | Valor | O que faz |
|
||||
|---|---|---|
|
||||
| `wsal_restrict-log-viewer` | `only_me` | Só o utilizador em `only-me-user-id` vê o log no wp-admin |
|
||||
| `wsal_restrict-plugin-settings` | `only_me` | Só esse utilizador altera a configuração do plugin |
|
||||
| `wsal_only-me-user-id` | `17` | ID do utilizador autorizado — confirmar sempre com `wp user get <ID>` que é a conta de IT correcta, não um utilizador órfão/comprometido |
|
||||
| `wsal_hide-plugin` | `yes` | **Stealth mode** — esconde o plugin da lista `wp-admin/plugins.php` (filtro `all_plugins`); um atacante com sessão de browser comprometida não sabe que o site está a ser auditado |
|
||||
| `wsal_mwp-child-stealth-mode` | `yes` | Idem, mas para dashboards multisite externos (ManageWP e similares) |
|
||||
| `wsal_disabled-alerts` | array de IDs (ver §3) | Tipos de evento que NÃO são registados |
|
||||
| `wsal_plugin_version` | `5.6.5` | Versão instalada |
|
||||
| `wsal_freemius_state` / `fs_wsalp` | `skipped` / `no` | Não activou licenciamento Freemius (versão free) |
|
||||
| `wsal_built-in-notifications` | array serializado | Config de e-mail de resumo diário (`daily_summary_notification`, `daily_email_address`) |
|
||||
| `wsal_notified_plugin_updates`, `wsal_notified_theme_updates`, `wsal_notified_wp_core_update` | arrays/strings | Cache interna de versões já notificadas — não é config de segurança, ignorar em auditorias |
|
||||
| `wsal_feature-highlight-notice-show`, `wsal_upgrade-notice-show`, `wsal_notification-modal-dismissed`, `wsal_free-search-try` | flags de UI | Estado de notices dispensados — irrelevante para segurança |
|
||||
|
||||
### 1.1 Comandos WP-CLI nativos (`wp wsal_cli_commands <subcomando>`)
|
||||
|
||||
Confirmado em `classes/Controllers/WP_CLI/class-wp-cli-commands.php`
|
||||
(registados desde a v4.6, `set_retention` inclusive). Todos aceitam
|
||||
`--allow-root --path=$PATH`.
|
||||
|
||||
| Subcomando | Argumentos | O que faz |
|
||||
|---|---|---|
|
||||
| `remove_wizard` | nenhum | Marca o wizard de setup inicial como dispensado (`setup-modal-dismissed=true`) |
|
||||
| `remove_daily_notification` | nenhum | Desactiva o resumo diário por e-mail (`built-in-notifications.daily_summary_notification=false`) — dispara evento `6310` |
|
||||
| `remove_weekly_notification` | nenhum | Desactiva o resumo semanal por e-mail (`weekly_summary_notification=false`) — dispara evento `6319` |
|
||||
| `disable_enable_alert` | `<alert_id>` | Activa/desactiva um `alert_id` específico (alternativa CLI ao array `wsal_disabled-alerts`) |
|
||||
| `set_hide_plugin` | `<1\|true\|0\|false>` | Equivalente CLI a `wp option update wsal_hide-plugin` (stealth mode) |
|
||||
| `login_page_notification` | `--enabled=<bool>` `--text=<html>` | Activa/desactiva o aviso "este site tem log de actividade" na página de login (`wsal_login-page-notification` + `wsal_login-page-notification-text`) — **não confirmado activo em nenhum site auditado**; texto aceita HTML |
|
||||
| `set_retention` | `--enabled=<bool>` `--pruning-value=<int>` `--pruning-unit=<days\|months\|years>` | Configura a purga automática (pruning) — ver §6 |
|
||||
|
||||
```bash
|
||||
wp wsal_cli_commands disable_enable_alert 1002 --allow-root --path=$PATH
|
||||
wp wsal_cli_commands set_hide_plugin 1 --allow-root --path=$PATH
|
||||
wp wsal_cli_commands set_retention --enabled=true --pruning-value=6 --pruning-unit=months --allow-root --path=$PATH
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Consultar o log de eventos (`wsal_occurrences` + `wsal_metadata`)
|
||||
|
||||
O log real vive em **duas tabelas dedicadas** (não em `postmeta`/`options`):
|
||||
|
||||
```bash
|
||||
wp db query "SHOW TABLES LIKE '%wsal%';" --allow-root --path=$PATH
|
||||
```
|
||||
|
||||
### Estrutura de `${PREFIX}wsal_occurrences` (1 linha = 1 evento)
|
||||
|
||||
| Campo | Tipo | Nota |
|
||||
|---|---|---|
|
||||
| `id` | bigint PK | |
|
||||
| `site_id` | bigint | Para multisite |
|
||||
| `alert_id` | bigint | Tipo de evento (ver tabela §3) |
|
||||
| `created_on` | double | Unix timestamp com microssegundos — usar `FROM_UNIXTIME(created_on)` |
|
||||
| `client_ip` | varchar | IP de origem |
|
||||
| `severity` | varchar | Código numérico (ver §3) |
|
||||
| `object` | varchar | Categoria (`user`, `post`, `plugins`, `system`, ...) |
|
||||
| `event_type` | varchar | `created`/`modified`/`deleted`/`login`/... |
|
||||
| `username`, `user_id`, `user_roles` | | Quem fez a acção — `user_id=0` é sistema/anónimo |
|
||||
| `session_id`, `user_agent` | | |
|
||||
| `post_status`, `post_type`, `post_id` | | Preenchido só em eventos de conteúdo |
|
||||
|
||||
Detalhe extra (nome do plugin alterado, ficheiro, etc.) fica em
|
||||
`${PREFIX}wsal_metadata` (`occurrence_id`, `name`, `value` — schema
|
||||
key/value, `LEFT JOIN` por `occurrence_id`).
|
||||
|
||||
### Queries úteis
|
||||
|
||||
```bash
|
||||
PREFIX=$(wp db prefix --allow-root --path=$PATH)
|
||||
|
||||
# Volume total + janela temporal coberta
|
||||
wp db query "SELECT COUNT(*) total, FROM_UNIXTIME(MIN(created_on)) primeiro, FROM_UNIXTIME(MAX(created_on)) ultimo FROM ${PREFIX}wsal_occurrences;" --allow-root --path=$PATH
|
||||
|
||||
# Últimos 50 eventos de um utilizador específico
|
||||
wp db query "SELECT FROM_UNIXTIME(created_on) quando, alert_id, object, event_type, client_ip FROM ${PREFIX}wsal_occurrences WHERE username='it' ORDER BY id DESC LIMIT 50;" --allow-root --path=$PATH
|
||||
|
||||
# Eventos num intervalo de datas
|
||||
wp db query "SELECT FROM_UNIXTIME(created_on) quando, username, object, event_type FROM ${PREFIX}wsal_occurrences WHERE created_on BETWEEN UNIX_TIMESTAMP('2026-08-01') AND UNIX_TIMESTAMP('2026-08-16') ORDER BY id;" --allow-root --path=$PATH
|
||||
|
||||
# Filtrar por tipo de evento (alert_id) — ex.: falhas de login (1002)
|
||||
wp db query "SELECT FROM_UNIXTIME(created_on) quando, username, client_ip FROM ${PREFIX}wsal_occurrences WHERE alert_id=1002 ORDER BY id DESC LIMIT 30;" --allow-root --path=$PATH
|
||||
|
||||
# Distribuição por tipo de evento (para ver o que domina o log)
|
||||
wp db query "SELECT alert_id, COUNT(*) total FROM ${PREFIX}wsal_occurrences GROUP BY alert_id ORDER BY total DESC LIMIT 20;" --allow-root --path=$PATH
|
||||
|
||||
# Distribuição por severidade
|
||||
wp db query "SELECT severity, COUNT(*) total FROM ${PREFIX}wsal_occurrences GROUP BY severity ORDER BY total DESC;" --allow-root --path=$PATH
|
||||
|
||||
# Ver metadados de um evento específico (ex.: qual plugin foi alterado)
|
||||
wp db query "SELECT name, value FROM ${PREFIX}wsal_metadata WHERE occurrence_id=<ID>;" --allow-root --path=$PATH
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Tipos de evento e severidade (dados reais observados, `emanuelalmeida.pt`)
|
||||
|
||||
`severity` (código Melapress padrão): `200`=informational, `250`=user
|
||||
activity, `300`=notification, `400`=warning, `500`=critical.
|
||||
|
||||
Top `alert_id` observados em 60.337 eventos (~1,5 anos de histórico) — usar
|
||||
como referência de "normal" ao auditar um site novo, não como lista
|
||||
exaustiva (o WSAL tem 100+ tipos de evento definidos):
|
||||
|
||||
| `alert_id` | Ocorrências | Interpretação provável |
|
||||
|---|---|---|
|
||||
| `6070` | 26.476 | Verificação periódica de sistema (cron interno do WSAL) |
|
||||
| `1003` | 20.276 | Actividade de sessão/login |
|
||||
| `2008` | 3.202 | Conteúdo modificado (post/página) |
|
||||
| `6066` | 2.615 | Verificação periódica de sistema |
|
||||
| `6069` | 2.329 | Verificação periódica de sistema |
|
||||
| `1002` | 1.965 | Login falhado |
|
||||
| `1000` | 389 | Login com sucesso |
|
||||
| `2053`/`2054` | 305/133 | Conteúdo criado/eliminado |
|
||||
|
||||
**Não confiar em interpretações de `alert_id` sem confirmar** contra a
|
||||
documentação oficial Melapress (`https://melapress.com/support/kb/`) ou o
|
||||
código do plugin (`wp-content/plugins/wp-security-audit-log/`) — os números
|
||||
acima são inferência a partir do padrão de volume, não confirmados
|
||||
individualmente nesta sessão.
|
||||
|
||||
### 3.1 Categorias de eventos (mapa completo, `defaults.php`)
|
||||
|
||||
Ficheiro central de definições: `defaults.php` (raiz do plugin, função
|
||||
`set_wsal_alerts()`, ~3.760 linhas). Define **as categorias core** — os
|
||||
eventos de integrações de terceiros (WooCommerce, Yoast, ACF, Rank Math,
|
||||
etc.) vivem em ficheiros separados (ver §3.2). Categorias core, por ordem
|
||||
de aparição no ficheiro (nome + intervalo aproximado de `alert_id`):
|
||||
|
||||
| Categoria (grupo topo) | Subcategorias | Intervalo `alert_id` | Conteúdo |
|
||||
|---|---|---|---|
|
||||
| Users Logins & Sessions Events | User Activity | `1000`–`1099` | Login/logout, falhas de login, sessões, alteração de password |
|
||||
| Content & Comments | Content, Categories, Custom Fields, Custom Fields (ACF), Comments, Widgets, Menus, Custom Post Types, Pages | `2000`–`2999` | Posts/páginas criados/editados/eliminados, categorias, comentários, widgets, menus, custom post types, ACF |
|
||||
| User Accounts | User Profiles, Multisite User Profiles | `4000`–`4999` | Utilizadores criados/editados/eliminados, mudança de role, password reset |
|
||||
| Plugins & Themes | Plugins, Themes, Themes on Multisite | `5000`–`5599` | Instalação/activação/desactivação/actualização de plugins e temas |
|
||||
| Activity Logs | Activity log plugin | `6000`–`6099`, `6300`–`6399` | Config do próprio WSAL alterada (ex.: `6310`/`6311`/`6312`/`6319` já usados pelos comandos WP-CLI de notificação — ver §1.1); também cobre eventos de "Notifications & Integrations" (Slack/SMS/e-mail custom) |
|
||||
| WordPress & System | System | `6000`–`6099` | Cron interno do WSAL, verificações periódicas (os IDs `6066`/`6069`/`6070` de alto volume observados em §3 pertencem aqui) |
|
||||
| — | WordPress Site Settings | `4700`–`4799` (aprox.) | Alteração de opções core do WP (site title, timezone, permalinks, etc.) |
|
||||
| — | Email Events | `8800`–`8899` (aprox.) | Falhas de envio de e-mail via `wp_mail` |
|
||||
| — | Database Events | `9000`–`9099` (aprox.) | Erros de query, updates de schema da BD |
|
||||
|
||||
**Nota:** as gamas de `alert_id` acima são aproximadas (extraídas da ordem
|
||||
de definição em `defaults.php`, não documentadas oficialmente pela
|
||||
Melapress como ranges fixos) — para confirmar a categoria exacta de um
|
||||
`alert_id` específico, o método fiável é `grep -A6 "^\s*$ALERT_ID,$"
|
||||
defaults.php` no código-fonte do servidor.
|
||||
|
||||
### 3.2 Alertas de integrações de terceiros (activados só se o plugin correspondente estiver presente)
|
||||
|
||||
Ficheiros em `classes/WPSensors/Alerts/` (18 ficheiros, um por integração
|
||||
suportada) — cada um define o próprio bloco de `alert_id`, só carregado se
|
||||
o plugin alvo estiver activo no site:
|
||||
|
||||
| Ficheiro | Integração | Volume aprox. de alertas |
|
||||
|---|---|---|
|
||||
| `class-woocommerce-custom-alerts.php` | WooCommerce | ~417 linhas de definição (produtos, encomendas, cupões, definições da loja) |
|
||||
| `class-yoast-custom-alerts.php` | Yoast SEO | Meta SEO, sitemaps, redirects |
|
||||
| `class-rank-math-custom-alerts.php` | Rank Math | Meta SEO, schema, redirects |
|
||||
| `class-acf-custom-alerts.php` | Advanced Custom Fields | Grupos de campos, campos criados/editados |
|
||||
| `class-gravity-forms-custom-alerts.php` | Gravity Forms | Formulários, entradas, notificações |
|
||||
| `class-wpforms-custom-alerts.php` | WPForms | Formulários, entradas |
|
||||
| `class-wp-2fa-custom-alerts.php` | WP 2FA (Melapress) | Activação/desactivação de 2FA por utilizador |
|
||||
| `class-memberpress-custom-alerts.php` | MemberPress | Subscrições, membros |
|
||||
| `class-paid-memberships-pro-custom-alerts.php` | Paid Memberships Pro | Níveis, membros |
|
||||
| `class-learndash-custom-alerts.php` | LearnDash | Cursos, inscrições |
|
||||
| `class-bbpress-custom-alerts.php` | bbPress | Fóruns, tópicos |
|
||||
| `class-tablepress-custom-alerts.php` | TablePress | Tabelas |
|
||||
| `class-redirection-custom-alerts.php` | Redirection | Regras de redirect |
|
||||
| `class-termly-custom-alerts.php` | Termly | Consentimento de cookies |
|
||||
| `class-ai-wp-plugin-alerts.php` | AI (Melapress AI features) | Uso de funcionalidades AI do próprio WSAL |
|
||||
| `class-multisite-custom-alerts.php` | WordPress Multisite | Criação/eliminação de sites na rede |
|
||||
| `class-mainwp-server-custom-alerts.php` | MainWP (servidor gerido) | Propagação de definições via dashboard MainWP — ver aviso em `defaults.php:2593` ("definições do WSAL foram sobrepostas a partir do MainWP") |
|
||||
|
||||
Confirmar quais estão activos num site: `wp plugin list --status=active
|
||||
--allow-root --path=$PATH` e cruzar com a tabela acima — só os que
|
||||
correspondem a um plugin activo geram eventos.
|
||||
|
||||
---
|
||||
|
||||
## 4. Replicar o padrão de segurança num site novo (checklist)
|
||||
|
||||
Baseado na configuração real confirmada em `emanuelalmeida.pt` (avaliada
|
||||
como "acima da média"):
|
||||
|
||||
```bash
|
||||
PATH=/home/USER/public_html
|
||||
|
||||
# 1. Instalar/activar (slug correcto — nome comercial mudou, slug não)
|
||||
wp plugin install wp-security-audit-log --activate --allow-root --path=$PATH
|
||||
|
||||
# 2. Identificar o ID do utilizador de IT/admin de confiança (NÃO um admin genérico partilhado)
|
||||
wp user list --role=administrator --fields=ID,user_login,user_email --allow-root --path=$PATH
|
||||
|
||||
# 3. Restringir visualização do log e config a esse utilizador
|
||||
wp option update wsal_restrict-log-viewer only_me --allow-root --path=$PATH
|
||||
wp option update wsal_restrict-plugin-settings only_me --allow-root --path=$PATH
|
||||
wp option update wsal_only-me-user-id <ID_do_utilizador_IT> --allow-root --path=$PATH
|
||||
|
||||
# 4. Activar stealth mode — esconder o plugin da lista wp-admin
|
||||
wp option update wsal_hide-plugin yes --allow-root --path=$PATH
|
||||
wp option update wsal_mwp-child-stealth-mode yes --allow-root --path=$PATH
|
||||
|
||||
# 5. Confirmar (ler de volta, nunca confiar só no exit code)
|
||||
wp option get wsal_restrict-log-viewer --allow-root --path=$PATH
|
||||
wp option get wsal_only-me-user-id --allow-root --path=$PATH
|
||||
wp user get <ID_do_utilizador_IT> --field=user_login --allow-root --path=$PATH
|
||||
```
|
||||
|
||||
Não mexer em `wsal_disabled-alerts` por defeito — deixar todos os ~900+
|
||||
tipos de evento activos (contando módulos de terceiros — ver §3.1). O padrão
|
||||
observado de apenas 13 IDs desligados, todos de baixo valor informativo, é a
|
||||
postura recomendada; desligar mais do que isso reduz cobertura de auditoria
|
||||
sem ganho real.
|
||||
|
||||
---
|
||||
|
||||
## 5. GOTCHA CRÍTICO — stealth mode e "only_me" não protegem contra WP-CLI/SQL
|
||||
|
||||
**Confirmado nesta sessão por teste directo:** apesar de `hide-plugin=yes`
|
||||
esconder o plugin da lista em `wp-admin/plugins.php` (via hook PHP no ecrã
|
||||
de admin), o plugin continua **totalmente visível e operável via WP-CLI**:
|
||||
|
||||
```bash
|
||||
wp plugin list --allow-root --path=$PATH | grep security-audit
|
||||
# → wp-security-audit-log,active,none,5.6.5,,on (aparece normalmente)
|
||||
|
||||
wp plugin status wp-security-audit-log --allow-root --path=$PATH
|
||||
# → Status: Active (nenhuma restrição aplicada)
|
||||
```
|
||||
|
||||
**Implicação de segurança real:** o padrão "esconder + restringir a
|
||||
`only_me`" protege apenas contra um atacante que compromete uma **sessão de
|
||||
browser wp-admin** de um utilizador administrador genérico (não vê o plugin
|
||||
na UI, não consegue desactivá-lo nem ler o log pela interface). **Não
|
||||
protege** contra:
|
||||
- Acesso SSH/WP-CLI ao servidor (qualquer comando `wp plugin deactivate`,
|
||||
`wp option update wsal_hide-plugin no`, ou `wp db query "DELETE FROM
|
||||
wsal_occurrences"` funciona sem qualquer verificação de `only-me-user-id`);
|
||||
- Acesso directo à base de dados (phpMyAdmin, mysql CLI);
|
||||
- Um plugin malicioso que corra `update_option()`/`deactivate_plugins()` em
|
||||
PHP no mesmo processo WordPress (o hook de stealth só filtra a
|
||||
*renderização* da lista, não a capability real).
|
||||
|
||||
Estas restrições são **apenas de UI**, implementadas por filtros como
|
||||
`all_plugins`/menu — não são um controlo de acesso ao nível dos dados. Ao
|
||||
avaliar a robustez do log de auditoria de um site, tratar sempre acesso
|
||||
SSH/WP-CLI e acesso à BD como "full trust" que ignora completamente esta
|
||||
protecção — a defesa real contra esses vectores é a segurança do próprio
|
||||
servidor (SSH keys, `mysql` sem exposição externa), não a config do plugin.
|
||||
|
||||
---
|
||||
|
||||
## 6. Retenção, arquivo e volume do log
|
||||
|
||||
O plugin **não faz purga agressiva por defeito** — confirmado:
|
||||
`emanuelalmeida.pt` tinha 60.337 eventos cobrindo Mar/2025 a Ago/2026 (~1,5
|
||||
anos) sem gaps aparentes, ocupando `~13 MB` (`wsal_occurrences`) + `~50 MB`
|
||||
(`wsal_metadata`, guarda os detalhes de cada evento — cresce mais rápido
|
||||
que a tabela principal).
|
||||
|
||||
```bash
|
||||
# Verificar tamanho actual antes de decidir sobre arquivo/purga
|
||||
wp db query "SELECT table_name, ROUND(((data_length+index_length)/1024/1024),2) size_mb, table_rows FROM information_schema.TABLES WHERE table_schema=DATABASE() AND table_name LIKE '%wsal%';" --allow-root --path=$PATH
|
||||
```
|
||||
|
||||
### 6.1 Purga automática (pruning) — `wsal_pruning-*`, classe `Plugin_Settings_Helper`/`Settings_Helper`
|
||||
|
||||
Ao contrário do que a auditoria pontual anterior sugeria, a purga
|
||||
automática **não é exclusiva da versão paga** — a lógica e as opções vivem
|
||||
no core (`classes/Helpers/class-plugin-settings-helper.php` +
|
||||
`class-settings-helper.php`) e há um comando WP-CLI dedicado (`set_retention`,
|
||||
ver §1.1). Confirmado nesta expansão: nenhuma destas opções está definida em
|
||||
`emanuelalmeida.pt` (usa os defaults do código, purga desligada).
|
||||
|
||||
| Opção | Default no código | O que faz |
|
||||
|---|---|---|
|
||||
| `wsal_pruning-date-e` | `false` (desligado) | Activa/desactiva a purga automática por data |
|
||||
| `wsal_pruning-date` | calculado por `get_default_pruning_date()` | Data-limite (`strtotime`-compatible, ex. `"6 months"`) — eventos mais antigos são apagados no próximo cron |
|
||||
| `wsal_pruning-unit` | `months` | Unidade usada no picker da UI (`days`/`months`/`years`) |
|
||||
| `wsal_pruning-limit-e` | não confirmado | Activa purga por **limite de contagem** (em vez de por data) |
|
||||
| `wsal_pruning-limit` | `1` (mínimo) | Nº máximo de eventos a manter, quando `pruning-limit-e=true` |
|
||||
| `wsal_delete-data` | `false` | Se `true`, ao desinstalar o plugin todos os dados (`wsal_occurrences`/`wsal_metadata`/opções) são apagados; se `false`, ficam órfãos na BD |
|
||||
|
||||
```bash
|
||||
# Ler estado actual de purga
|
||||
wp option list --search='wsal_pruning*' --format=table --allow-root --path=$PATH
|
||||
|
||||
# Activar purga a 6 meses via WP-CLI (equivalente ao form da UI)
|
||||
wp wsal_cli_commands set_retention --enabled=true --pruning-value=6 --pruning-unit=months --allow-root --path=$PATH
|
||||
wp option get wsal_pruning-date-e --allow-root --path=$PATH
|
||||
wp option get wsal_pruning-date --allow-root --path=$PATH
|
||||
```
|
||||
|
||||
### 6.2 Arquivo (archiving) para BD externa — `wsal_archiving-*`
|
||||
|
||||
Funcionalidade distinta da purga: em vez de apagar, **move** eventos
|
||||
antigos para uma segunda ligação de base de dados (`Archive_Records::archive()`
|
||||
em `classes/Entities/Archive/class-archive-records.php`) via cron. Requer
|
||||
configurar previamente uma "connection" de arquivo (ver §6.3) — sem
|
||||
connection definida, `is_archiving_set_and_enabled()` devolve `false` e o
|
||||
cron não corre, mesmo com `archiving-e=yes`.
|
||||
|
||||
| Opção | O que faz |
|
||||
|---|---|
|
||||
| `wsal_archiving-e` | Liga/desliga o arquivo automático |
|
||||
| `wsal_archiving-date` + `wsal_archiving-date-type` (`days`/`months`/`years`, default `1`/`months`) | Antiguidade a partir da qual um evento é arquivado |
|
||||
| `wsal_archiving-run-every` | Frequência do cron de arquivo (default `hourly`) |
|
||||
| `wsal_archiving-stop` | Pausa temporária do arquivo sem desligar a config |
|
||||
| `wsal_archiving-cron-started` | Flag interna — cron já agendado |
|
||||
|
||||
```bash
|
||||
wp option list --search='wsal_archiving*' --format=table --allow-root --path=$PATH
|
||||
```
|
||||
|
||||
**Não confirmado activo em nenhum site auditado** (`emanuelalmeida.pt` não
|
||||
tem nenhuma destas opções definidas).
|
||||
|
||||
### 6.3 Espelhamento (mirroring) para BD/serviço externo — `wsal_wsal-mirror-*`
|
||||
|
||||
Envia uma cópia em tempo real de cada evento para uma ligação externa
|
||||
(outra tabela MySQL, ou syslog/SIEM de terceiros via plugin de mirror
|
||||
dedicado — **o WSAL não tem integração nativa de syslog/SIEM no core**, só
|
||||
o mecanismo genérico de "connections" reutilizado por mirror e archiving).
|
||||
`Settings_Helper::get_all_mirrors()` lê todas as opções com prefixo
|
||||
`WSAL_MIRROR_PREFIX` (`wsal-mirror-`); cada uma é um array serializado
|
||||
(`connection`, filtros de `alert_id`, etc.).
|
||||
|
||||
```bash
|
||||
wp option list --search='wsal-mirror-*' --format=table --allow-root --path=$PATH
|
||||
wp option list --search='wsal_connection-*' --format=table --allow-root --path=$PATH
|
||||
```
|
||||
|
||||
Se `database_logging_enabled` for `false` E existir pelo menos um mirror
|
||||
configurado, o WSAL passa a **não gravar mais em `wsal_occurrences` local**
|
||||
— todo o log vai só para o(s) destino(s) espelhados. Confirmar sempre
|
||||
`Settings_Helper::is_database_logging_enabled()` (via `wp eval`) antes de
|
||||
assumir que as queries SQL do §2 devolvem o histórico completo num site com
|
||||
mirror activo.
|
||||
|
||||
**Nota operacional (aplica-se a §6.1–§6.3):** a ausência de purga é boa
|
||||
para auditoria (histórico completo disponível), mas em sites com muita
|
||||
actividade o crescimento é linear e sem limite. Se `wsal_metadata`
|
||||
ultrapassar dimensões incómodas (centenas de MB), considerar:
|
||||
- Activar `wsal_pruning-date-e` com uma janela realista (6–12 meses) via
|
||||
`set_retention`;
|
||||
- Arquivar eventos antigos para uma tabela `_archive` antes de apagar
|
||||
(nunca `DELETE` directo sem backup — perde-se rasto de auditoria);
|
||||
- Configurar uma connection de arquivo (§6.2) se o volume justificar
|
||||
automação em vez de purga manual.
|
||||
|
||||
Não foi necessário agir em `emanuelalmeida.pt` nesta sessão — volume actual
|
||||
(~63 MB total) é irrelevante para performance.
|
||||
|
||||
---
|
||||
|
||||
## 7. Notificações, relatórios e integrações
|
||||
|
||||
### 7.1 Notificações incorporadas (resumo diário/semanal por e-mail — gratuito)
|
||||
|
||||
Opção `wsal_built-in-notifications` (array serializado, constante
|
||||
`Notifications::BUILT_IN_NOTIFICATIONS_SETTINGS_NAME`). Confirmado em
|
||||
`emanuelalmeida.pt`: só contém config de resumo diário
|
||||
(`daily_summary_notification`, `daily_email_address`); a v5.3+ acrescentou
|
||||
resumo **semanal** (`weekly_summary_notification`, evento `6319` ao
|
||||
desactivar — ver §1.1 `remove_weekly_notification`).
|
||||
|
||||
```bash
|
||||
wp option get wsal_built-in-notifications --format=json --allow-root --path=$PATH
|
||||
```
|
||||
|
||||
### 7.2 Notificações customizadas (regra "se `alert_id` X ocorrer, notifica Y") — Premium
|
||||
|
||||
Opção `wsal_custom-notifications` (constante
|
||||
`CUSTOM_NOTIFICATIONS_SETTINGS_NAME`) — permite regras condicionais por
|
||||
utilizador/IP/tipo de evento, com entrega por e-mail, **Slack**
|
||||
(`classes/Controllers/slack/`) ou **SMS via Twilio**
|
||||
(`classes/Controllers/twilio/`). Não confirmado activo em nenhum site
|
||||
auditado; `wsal_notifications` (nota: nome sem `custom-`, é outra opção)
|
||||
só guarda config global de encurtamento de URLs (`shorten_notification_urls`,
|
||||
`notification_bitly_shorten_key`) — confirmado vazio/desligado em
|
||||
`emanuelalmeida.pt`.
|
||||
|
||||
```bash
|
||||
wp option get wsal_custom-notifications --format=json --allow-root --path=$PATH
|
||||
wp option get wsal_notifications --format=json --allow-root --path=$PATH
|
||||
```
|
||||
|
||||
### 7.3 Exportação e relatórios
|
||||
|
||||
- **CSV** — gratuito, core. Acção AJAX `wsal_export_csv_results`
|
||||
(`classes/Writers/class-csv-writer.php`), disponível no ecrã do log em
|
||||
wp-admin (botão "Export"). Não há comando WP-CLI dedicado — a exportação
|
||||
é sempre via browser/AJAX; para extrair dados por CLI usar as queries SQL
|
||||
do §2 e `wp db query ... --format=csv` como alternativa equivalente.
|
||||
- **Relatórios agendados** (geração automática + entrega por e-mail,
|
||||
white-label) — feature **Premium** (`classes/Views/class-premium-features.php`,
|
||||
`AuditLog.php:470` mostra link de upsell "Get scheduled reports... with
|
||||
Premium" nos eventos de tipo `2000`/`2001`/`2100`/`4000`). Não existe em
|
||||
wp-options nem endpoint WP-CLI na versão gratuita.
|
||||
|
||||
### 7.4 SIEM/Syslog externo
|
||||
|
||||
**Não existe integração nativa de Syslog/SIEM no core do plugin** —
|
||||
confirmado por ausência de qualquer classe/ficheiro com `syslog`/`SIEM` no
|
||||
código-fonte (`grep -rl` devolveu zero resultados). A única via de exportar
|
||||
eventos em tempo real para um sistema externo é o mecanismo de
|
||||
**espelhamento (mirroring)** descrito em §6.3, que só suporta ligações
|
||||
configuradas como "connections" do próprio plugin (outra BD MySQL) — não um
|
||||
protocolo Syslog/CEF nativo. Para integração SIEM real, a Melapress
|
||||
documenta um add-on comercial separado; confirmar sempre no site do
|
||||
fornecedor antes de assumir que existe suporte nativo.
|
||||
|
||||
---
|
||||
|
||||
## 8. Erros comuns
|
||||
|
||||
| Sintoma | Causa | Solução |
|
||||
|---|---|---|
|
||||
| `wp plugin activate wp-activity-log` falha ("plugin not found") | Usou o nome comercial em vez do slug | Slug é sempre `wp-security-audit-log`, independentemente do rebranding |
|
||||
| Query em `wsal_occurrences` devolve datas erradas | `created_on` é Unix timestamp `double` (com microssegundos), não `DATETIME` | Usar sempre `FROM_UNIXTIME(created_on)` |
|
||||
| Achar que o plugin "não está lá" num site com `hide-plugin=yes` | Confundir stealth mode de UI com ausência real | Confirmar sempre via `wp plugin list`/`wp plugin status` — o WP-CLI nunca respeita esta flag (ver §5) |
|
||||
| `only-me-user-id` aponta para um ID que já não existe/foi desactivado | Utilizador de IT mudou de conta e a opção não foi actualizada | Confirmar sempre com `wp user get <ID>` antes de assumir que a restrição é válida — um ID órfão equivale a log inacessível a todos via UI |
|
||||
| Achar `wsal_disabled-alerts` vazio = tudo activo | O array serializado inclui sempre um `s:0:""` inicial (artefacto de serialização PHP), não é um alerta desligado real | Ignorar a primeira entrada vazia ao contar IDs desligados |
|
||||
| Achar que "não há WP-CLI para este plugin" | Confusão histórica — o WSAL regista `wp wsal_cli_commands` desde a v4.6 | Usar `wp cli cmd-dump \| grep wsal` para confirmar; ver §1.1 |
|
||||
| Achar que purga automática (`pruning`) é só Premium | `set_retention`/`wsal_pruning-*` são core, disponíveis na versão gratuita | Confirmar sempre no código (`class-plugin-settings-helper.php`) antes de recomendar upgrade pago só para ligar retenção |
|
||||
| Confundir `wsal_notifications` com `wsal_custom-notifications` | Nomes parecidos, funções diferentes — a primeira é só config de encurtamento de URL, a segunda são as regras de alerta customizado (Premium) | Ler sempre as duas e não assumir que uma vazia implica a outra desligada |
|
||||
| Assumir que o log SQL (§2) tem o histórico completo num site com mirroring activo | Se `database_logging_enabled=false` com mirror configurado, o WSAL deixa de escrever localmente | Confirmar `Settings_Helper::is_database_logging_enabled()` via `wp eval` antes de tirar conclusões de volume/gaps |
|
||||
|
||||
---
|
||||
|
||||
**Fonte:** `CONFIG-Plugins-Referencia.md` §9 (WP Security Audit Log / WP
|
||||
Activity Log) + verificação SSH ao vivo nesta sessão (`emanuelalmeida.pt`,
|
||||
opções `wsal_*`, estrutura e contagem de `wsal_occurrences`/`wsal_metadata`,
|
||||
teste de bypass `wp plugin list`) + **leitura completa do código-fonte do
|
||||
plugin nesta expansão** (`wp-content/plugins/wp-security-audit-log/`,
|
||||
versão `5.6.5`, ~99.000 linhas PHP): `defaults.php` (definições de todos os
|
||||
eventos core, função `set_wsal_alerts()`), `classes/WPSensors/Alerts/*`
|
||||
(18 integrações de terceiros), `classes/Controllers/WP_CLI/class-wp-cli-commands.php`
|
||||
(comandos WP-CLI nativos), `classes/Helpers/class-settings-helper.php` +
|
||||
`class-plugin-settings-helper.php` (todas as opções `wsal_*` — pruning,
|
||||
archiving, mirroring, notificações), `classes/Entities/Archive/class-archive-records.php`
|
||||
(mecanismo de arquivo), `classes/notification/*` (notificações
|
||||
incorporadas e customizadas, Slack/Twilio), `classes/Views/class-premium-features.php`
|
||||
e `AuditLog.php` (features gated como Premium: relatórios agendados,
|
||||
notificações custom, mirroring/archiving).
|
||||
Reference in New Issue
Block a user