Case Study

Building and Validating 28 Wazuh Rule Blocks

28 rule blocks across 24 XML files - authored for SOC triage patterns, bundled for deployment, and validated with reproducible commands from repo root.

Context

The Wazuh rules in this portfolio are not copies of community defaults. They target specific detection gaps identified during lab triage - RDP brute force patterns, PowerShell encoded command execution, suspicious scheduled task creation, and Windows process anomalies. Each rule was authored to generate actionable alerts that map directly to IR playbook decision points.

Problem

Default Wazuh rules produce high-volume, low-context alerts. Analyst fatigue is the predictable result. Without custom tuning, triage time increases because analysts must manually determine whether each alert is worth investigating. The goal was to build a rule set that pre-filters noise and surfaces events with enough context for immediate triage decisions.

Approach

  1. Identify detection gaps by reviewing alert volume during normal lab operation and noting which attack patterns produced no alerts.
  2. Author XML rules under content/detection-rules/wazuh/rules/, each with a descriptive description field and a mitre mapping where applicable.
  3. Build deployment bundles with scripts/build-wazuh-bundle.ps1 to ensure rules are packaged consistently.
  4. Count files and <rule id= blocks separately - file count and rule block count diverge because some XML files contain multiple rules.
  5. Run representative alert simulations (e.g., encoded PowerShell commands on the primary endpoint) and verify generated alerts appear in Wazuh dashboards.

Validation commands

# Build deployment bundle
pwsh -File .\scripts\build-wazuh-bundle.ps1

# Count XML files
(Get-ChildItem .\detection-rules\wazuh\rules -Filter *.xml).Count

# Count rule blocks (not files)
Select-String -Path .\detection-rules\wazuh\rules\*.xml `
  -Pattern '<rule\s+id=' | Measure-Object | % Count

# Full verification
pwsh -NoProfile -File .\scripts\verify\verify-counts.ps1

Evidence

The rule source files, bundle script, and verification outputs are all in the public repo:

Lab screenshots of alert firing are available on request. Dashboard images are withheld to avoid exposing internal Wazuh indexer configuration.

Outcome

  • 28 rule blocks active and verified against VERIFIED_COUNTS.md.
  • Rule set covers: RDP brute force, encoded PowerShell, suspicious schtasks, process anomalies, and file integrity changes.
  • Bundle script produces a deployable archive - no manual assembly required.
  • Verification runs in under 10 seconds from repo root.

Lessons and next steps

  • Synthetic event generators would enable regression testing without requiring a live lab endpoint.
  • Splitting high-noise rules into tuning profiles per environment type (endpoint vs. server) would reduce alert fatigue further.
  • A false-positive review matrix per rule family would give reviewers a quick trust signal.
  • Adding automated log sample replay (similar to the detection harness) would close the validation loop.
Browse all detections Back to projects