# Wazuh Alert Tuning — KNEL SOC **Date:** 2026-09-06 · **Ticket:** [Redmine #825](https://projects.knownelement.com/issues/825) · **Change:** GLPI CR 23 **Applied on:** tsys-siem (Wazuh manager 4.14.1), `/var/ossec/etc/rules/local_rules.xml` **Discourse:** https://community.turnsys.com/t/soc-security-operations-lane-wazuh-tuning-823-follow-through-soc-team/340 **Rollback:** `cp /var/ossec/etc/rules/local_rules.xml.bak-20260906-soc /var/ossec/etc/rules/local_rules.xml && systemctl restart wazuh-manager` ## Why The manager emails every alert of level >= 7 to coo@turnsys.com (max 12/hour). September 2026 through 09-06: **664k alerts this month** (518k from tsys-cloudron-new web 400s alone, ingested via journald = every Cloudron app's container stdout), and a permanent L7+ email storm: scanner-storm composites (31151 @ L10), CVE backlog refires (23505 High @ L10, 23506 Critical @ L13, 23504 Medium @ L7 — the whole backlog re-fires every scan), SCA failures (19007 @ L7), ssh/PAM fail amplifiers (2502 @ L10, 5551 @ L10), dpkg events (2902/2904 @ L7), generic syscheck churn (550 @ L7). Design rule going forward: **email (L7+) is reserved for genuine incidents.** Everything else lives in dashboards and the SOC weekly loop (triage notes on #825, OpenVAS/GLPI tickets for vulnerabilities, hardening backlog for SCA). ## Mechanism note (learned the hard way) Wazuh 4.14 rule `overwrite="yes"` in local_rules.xml **REPLACES the original rule definition — it is not a merge.** An override with only a level would match *every* event (observed: rule 2502 flagging kernel i2c lines at 1000/min). Therefore every override below carries the FULL original rule body with only level/frequency/timeframe changed. Also: nested `` elements are invalid in rule files — single root group only. Level-0 rules do not index but still count as "fired" for frequency composites (verified: 31151 keeps firing over the L0 31101 parent). ## Changes | Rule | Meaning | Was | Now | Rationale | |------|---------|-----|-----|-----------| | 31101 | web 400 per-line | L5 | **L0** | 492k/mo bot noise; raw logs stay in journald | | 31120 / 31122 | web 500 per-line | L5 | **L3** | real app errors, dashboard-only | | 31151 | web 400 storm composite | L10 freq 14/90s | **L6 freq 40/240s** | sustained scans only, no email | | 5501 / 5502 | PAM session open/close | L3 | **L0** | session accounting | | 23502 / 23507 | CVE solved / cleared | L3 | **L0** | lifecycle info | | 23503 | CVE low | L5 | **L3** | | | 23504 | CVE medium/untriaged | L7 | **L4** | was emailing; backlog refire | | 23505 | CVE high | L10 | **L6** | vulns = weekly OpenVAS/GLPI loop, not email | | 23506 | CVE critical | L13 | **L6** | same — backlog refire storm made email useless | | 19007 | SCA check failed | L7 | **L5** | hardening backlog | | 2902 / 2904 | dpkg installed / half-configured | L7 | **L3** | ops inventory, not incidents | | 550 | syscheck checksum changed (generic) | L7 | **L5** | churn; high-signal subcases below | | 2502 | "missed password >once" | L10 | **L5** | dup of 5503/5760 | | 5551 | PAM multiple failed logins | L10 | **L6** | 2.3k/mo on routine churn | | 31510 | CMS brute force | L8 freq 8/30s | **L6 freq 20/120s** | bot storms | | 40704 | systemd unit failed | L5 | **L3** | 145k/mo churn; root-cause dig tracked on #825 | **Kept at L7+ deliberately:** 5712 (sshd brute, L10), 5763 (sshd max-auth), 31152/31153 (401/403 storms, L10), 31162 (suspicious URI, L10), plus all auth *failures* at L5 (5710/5760/5503) — cheap and real now that SSH is tailnet-only (#769). ## New detections (the #823 pattern) The July 2026 ezeda.org compromise ([Redmine #823](https://projects.knownelement.com/issues/823)) persisted via wp-config.php backdoor + 41 webshells in uploads. New rules + Cloudron agent syscheck watchers catch a repeat: | Rule | Level | Fires when | |------|-------|------------| | 100500 | **L12 (email)** | any `wp-config.php` under Cloudron app data changes (syscheck) | | 100501 | **L10 (email)** | a `.php` file appears/changes inside any WP `uploads/` dir (syscheck) | | 100510 | L8 | web request reaches `.php` inside an `uploads/` path (access-log) | Agent 001 (tsys-cloudron-new) `ossec.conf` additions: syscheck `/home/yellowtent/appsdata/*/data/wp-config.php` + `*/data/wp-content/uploads` (frequency 12h); quarantine dirs excluded (`#823` evidence holds known malware). ## Verification (2026-09-06, clean window after deploy) | Metric | Before (per hour) | After (per hour) | |--------|-------------------|------------------| | Total alerts | ~19,000+ | ~2,500 | | L5 web-400 flood | ~25,000 | **0** | | 2502 misfire flood | ~60,000 at peak | **0** (7 per 10 min = genuine) | | L7+ (email to coo@) | constant (12/h cap hit) | **0** | | L10 scanner storms (31151) | continuous | L6, sustained scans only | Remaining L3 volume = systemd churn (40704) + apparmor denials (52002) + web 500s + sshd successes: visible for triage, below every notification path. ## Week-loop plan (adjustment cadence) 1. Daily: triage new L6+ in the Wazuh dashboard; note dispositions on #825. 2. Watch 5710/5760/5503 — should stay near-zero with tailnet-only SSH; a spike = someone knocking from inside the tailnet. 3. 100500/100501/100510 must stay at zero; any fire = possible #823 recurrence → incident. 4. Investigate 40704 root cause on tsys-siem (which unit churns) as an ops item. 5. Re-check email volume at coo@ weekly; tune further only on evidence. 6. Vulnerability backlog: OpenVAS scans (GLPI-fed targets) → tickets per the triage standard; Wazuh vuln alerts feed the same weekly review.