| 1 | # Purple-Team Lab |
| 2 | |
| 3 | Emulate adversary techniques, then prove the detections fire. This is the validation |
| 4 | half of [detection-as-code](https://github.com/zionboggan/detection-as-code): I run |
| 5 | ATT&CK techniques against an instrumented Ubuntu endpoint enrolled in my |
| 6 | [SOC automation lab](https://github.com/zionboggan/soc-automation-lab), and confirm |
| 7 | each one raises the alert it's supposed to - mapped to the right technique, at a |
| 8 | severity that would actually page someone. |
| 9 | |
| 10 | Writing a detection is a hypothesis. This is the test. |
| 11 | |
| 12 |  |
| 13 | |
| 14 | Every row is an atomic I executed on the endpoint and the rule that caught it - five of |
| 15 | the six are detections I wrote (`100410`-`100413`) plus the brute-force rule, all on the |
| 16 | `purple-target` agent, all ATT&CK-tagged. |
| 17 | |
| 18 | ## How it's wired |
| 19 | |
| 20 | ```mermaid |
| 21 | flowchart LR |
| 22 | A[Atomic Red Team atomics<br/>run on purple-target VM] --> B[Wazuh agent<br/>auth log + real-time FIM] |
| 23 | B -->|1514/tcp| C[Wazuh manager<br/>analysisd: built-in + custom rules] |
| 24 | C --> D[Indexer] |
| 25 | D --> E[Dashboard<br/>ATT&CK-mapped alerts] |
| 26 | F[MITRE Caldera<br/>adversary emulation] -.-> B |
| 27 | ``` |
| 28 | |
| 29 | The target is a dedicated Ubuntu 22.04 VM (not a container - kernel-level telemetry |
| 30 | needs a real kernel). It runs the Wazuh agent shipping auth logs and **real-time file |
| 31 | integrity monitoring** on the paths attackers use for persistence. Caldera is available |
| 32 | for graph-based adversary emulation; the day-to-day validation uses Atomic Red Team |
| 33 | because it maps cleanly one-atomic-to-one-detection. |
| 34 | |
| 35 | ## Validation matrix |
| 36 | |
| 37 | Each technique was executed on the endpoint and confirmed in the SIEM: |
| 38 | |
| 39 | | Technique | Atomic | Telemetry | Rule | Level | Result | |
| 40 | |-----------|--------|-----------|------|-------|--------| |
| 41 | | T1110 Brute Force | 18 invalid SSH logins | auth log | `5712` (built-in) | 10 | ✅ detected | |
| 42 | | T1053.003 Cron persistence | drop job in `/etc/cron.d` | FIM | `100410` (custom) | 10 | ✅ detected | |
| 43 | | T1543.002 Systemd persistence | create `.service` unit | FIM | `100411` (custom) | 10 | ✅ detected | |
| 44 | | T1098.004 SSH authorized_keys | append attacker key | FIM | `100412` (custom) | 12 | ✅ detected | |
| 45 | | T1543 Tooling drop | binary into `/usr/local/bin` | FIM | `100413` (custom) | 10 | ✅ detected | |
| 46 | | T1078 / T1548.003 | login + sudo to root | auth log | `5501` / `5402` | 3 | ✅ (informational baseline) | |
| 47 | |
| 48 | The custom rules are in [`rules/local_purple_rules.xml`](rules/local_purple_rules.xml); |
| 49 | the atomics that exercise them are in [`atomics/run_atomics.sh`](atomics/run_atomics.sh). |
| 50 | |
| 51 | ## Why FIM for persistence |
| 52 | |
| 53 | The persistence detections key off **file integrity monitoring**, not syscall auditing. |
| 54 | That's deliberate: FIM is Wazuh-native and works everywhere - including containers and |
| 55 | hardened hosts where the kernel audit framework isn't available to you - whereas auditd |
| 56 | execve rules silently do nothing on a host that boots with audit disabled. The auditd |
| 57 | ruleset I'd layer on a host that *does* have kernel auditing is included in |
| 58 | [`agent/auditd-purple.rules`](agent/auditd-purple.rules), but the validated detections |
| 59 | above don't depend on it. |
| 60 | |
| 61 | ## Run it |
| 62 | |
| 63 | On the endpoint (enrolled Wazuh agent + the FIM config from `agent/`): |
| 64 | |
| 65 | ```bash |
| 66 | sudo bash atomics/run_atomics.sh # execute the technique set |
| 67 | ``` |
| 68 | |
| 69 | Then in the Wazuh dashboard, filter Threat Hunting → Events to |
| 70 | `rule.id:(100410 or 100411 or 100412 or 100413 or 5712)` and confirm the hits. |
| 71 | |
| 72 | Caldera (adversary-emulation UI, optional): |
| 73 | |
| 74 | ```bash |
| 75 | cd caldera && docker compose up -d # http://localhost:8888 |
| 76 | ``` |
| 77 | |
| 78 | ## Layout |
| 79 | |
| 80 | ``` |
| 81 | rules/local_purple_rules.xml custom FIM detections (deploy to the manager) |
| 82 | agent/fim-directories.xml real-time FIM config for the agent's syscheck block |
| 83 | agent/auditd-purple.rules auditd rules for hosts with kernel auditing |
| 84 | atomics/run_atomics.sh the ATT&CK technique set |
| 85 | caldera/docker-compose.yml MITRE Caldera server |
| 86 | docs/validation-matrix.md the matrix above, with notes per technique |
| 87 | ``` |