Zion Boggan zionboggan.com ↗

deployment notes + live threat-hunting and agent screenshots

d17b11f   Zion Boggan committed on May 28, 2026 (3 weeks ago)
README.md +6 -0
@@ -30,6 +30,12 @@ opens a TheHive case with the verdict attached, sets severity from the score, an
drops a message in the analyst channel. Everything after the rule match is hands
off.
+The detection layer, running with a Linux endpoint enrolled and an SSH brute-force
+replayed against it - alerts land already mapped to MITRE ATT&CK:
+
+![Wazuh Threat Hunting](docs/screenshots/01-wazuh-threat-hunting.png)
+![Enrolled agent](docs/screenshots/02-wazuh-agent.png)
+
## Stack
| Component | Role | Version pinned |
docs/deployment-notes.md +44 -0
@@ -0,0 +1,44 @@
+# Deployment notes
+
+Things worth knowing before you run this somewhere real. The stack was brought up
+and validated end to end on a single host (Wazuh indexer/manager/dashboard +
+TheHive + Cassandra + Elasticsearch + Cortex), with a Linux agent enrolled and SSH
+brute-force alerts flowing through to the dashboard.
+
+## Credentials
+
+The Wazuh indexer ships with the image's default users (`admin`, `kibanaserver`).
+`.env` sets the passwords the manager and dashboard use to talk to it - keep
+`INDEXER_PASSWORD` aligned with whatever the indexer actually has. For anything
+beyond a lab, change the indexer passwords with the Wazuh password tool and update
+`.env` to match. `config/wazuh/dashboard/wazuh.yml` holds the Wazuh API password the
+dashboard uses for the manager (`wazuh-wui`); set it to your `WAZUH_API_PASSWORD`.
+
+## Indexer compatibility
+
+Filebeat 7.10 refuses to publish to an indexer that reports an OpenSearch 2.x
+version, so the indexer config sets `compatibility.override_main_response_version:
+true`. Without it the manager produces alerts but nothing reaches the indexer and the
+dashboard stays empty.
+
+## Running inside an unprivileged LXC
+
+On bare metal or a normal VM the indexer and Elasticsearch lock memory
+(`bootstrap.memory_lock=true`, `memlock: -1`), which is the right production setting
+and what's committed here. Inside an unprivileged LXC container the kernel caps
+locked memory (often 8 MB) and the containers fail to start with an rlimit error. If
+that's your situation, set `bootstrap.memory_lock=false` and cap the `memlock`
+ulimit at the container's limit via a `docker-compose.override.yml` rather than
+editing the committed file.
+
+`vm.max_map_count` must be at least 262144 on the host for the indexer and
+Elasticsearch. On a normal host: `sysctl -w vm.max_map_count=262144`. In an LXC it's
+inherited from the node, so set it on the node.
+
+## CTI watchlists
+
+The `cti-malicious-*` lists are seeded into the manager by `deploy.sh` after the
+stack is up (CDB lists have to be writable so the manager can compile them, which
+rules out bind-mounting them read-only). In the full setup these lists are owned by
+the [CTI detection pipeline](../../cti-detection-automation), which regenerates and
+promotes them on approval.
docs/screenshots/01-wazuh-threat-hunting.png +0 -0
Binary file not shown
docs/screenshots/02-wazuh-agent.png +0 -0
Binary file not shown
docs/screenshots/README.md +12 -5
@@ -7,13 +7,20 @@ directory with the names listed and they'll render in the main README.
Capture at a consistent width (1280-1440), and annotate the call-out in each shot
(a red circle/arrow is enough).
+Captured from the running lab (detection layer):
+
+- `01-wazuh-threat-hunting.png` - Threat Hunting dashboard with the SSH brute-force
+ alerts and their MITRE ATT&CK breakdown.
+- `02-wazuh-agent.png` - the enrolled Linux endpoint, active and reporting in.
+
+Still to capture from the SOAR side, once the workflow is imported and a case has run
+through it:
+
| File | Where | Annotate |
|------|-------|----------|
-| `01-wazuh-alerts.png` | Wazuh dashboard → Security events, filtered to rule level ≥ 10 | the CTI / brute-force rule that fired, and its MITRE technique tag |
-| `02-shuffle-workflow.png` | Shuffle → the imported `Wazuh -> TheHive Enrichment` workflow canvas | the enrichment → scoring → case-creation path |
-| `03-shuffle-run.png` | Shuffle → a finished run of that workflow | the VirusTotal/OTX result feeding the severity score |
-| `04-thehive-case.png` | TheHive → the auto-created case | the severity, the MITRE tags, and the attached IOC observable |
-| `05-agent-enrolled.png` | Wazuh dashboard → Agents | the enrolled endpoint reporting in |
+| `03-shuffle-workflow.png` | Shuffle → the imported `Wazuh -> TheHive Enrichment` workflow canvas | the enrichment → scoring → case-creation path |
+| `04-shuffle-run.png` | Shuffle → a finished run of that workflow | the VirusTotal/OTX result feeding the severity score |
+| `05-thehive-case.png` | TheHive → the auto-created case | the severity, the MITRE tags, and the attached IOC observable |
## Triggering a test alert