abdullahshammari796-ctrl/aegis-soc-lab
GitHub: abdullahshammari796-ctrl/aegis-soc-lab
Stars: 0 | Forks: 0
# Aegis — Threat Detection & Response Lab
## Table of Contents
- [Project Overview](#project-overview)
- [Lab Architecture](#lab-architecture)
- [Phase 1 — Foundation](#phase-1--foundation)
- [Phase 2 — SIEM Installation](#phase-2--siem-installation)
- [Phase 3 — Agent Deployment](#phase-3--agent-deployment)
- [Phase 4 — First Detection: Sudo Brute-Force](#phase-4--first-detection-sudo-brute-force)
- [Phase 4.5 — FIM & Persistence Detection](#phase-45--fim--persistence-detection)
- [Phase 5 — Network Reconnaissance & SSH Brute-Force](#phase-5--network-reconnaissance--ssh-brute-force)
- [Phase 6 — PKI Deep Dive](#phase-6--pki-deep-dive)
- [Phase 7 — Cowrie Honeypot](#phase-7--cowrie-honeypot)
- [Phase 8 — Network IDS with Suricata](#phase-8--network-ids-with-suricata)
- [Phase 9 — Threat Intelligence Enrichment](#phase-9--threat-intelligence-enrichment)
- [Cross-Phase Lessons Learned](#cross-phase-lessons-learned)
- [MITRE ATT&CK Coverage](#mitre-attck-coverage)
- [Skills Demonstrated](#skills-demonstrated)
- [What's Next](#whats-next)
## Project Overview
Aegis is a fully isolated security operations lab that detects, alerts on, and enriches real attacks — built end-to-end on a single Windows laptop. Across nine phases I deployed a SIEM, instrumented an endpoint with an agent, simulated attacker techniques from MITRE ATT&CK, wrote custom Wazuh decoders and rules, deployed an interactive SSH honeypot, layered in a network IDS, and finished with automatic threat intelligence enrichment that cross-references every network alert against a 517-entry feed of known-malicious IPs.
The headline result: when an attacker scans the SIEM from a known-bad IP, two alerts fire — Suricata's signature match *and* a level-12 enrichment alert that tells the analyst "we have prior intelligence on this source." That's the difference between noise and signal in a real SOC.
Each phase introduces a new detection capability or hardening step. They build on each other: Phases 1–3 stand up the platform, Phases 4 and 4.5 prove it works against attacker techniques, Phase 5 adds reconnaissance simulation, Phase 6 hardens the dashboard with a proper PKI chain, Phase 7 adds an interactive deception layer, Phase 8 adds Layer-3 visibility with Suricata, and Phase 9 crowns the stack with threat intelligence enrichment.
## Lab Architecture
graph LR
subgraph "LabNet — 192.168.56.0/24 (Host-only)"
subgraph "Kali Linux — 192.168.56.101"
KaliOS[Kali 2026.1]
Cowrie[Cowrie Honeypot
port 2222] Agent[Wazuh Agent 001] KaliOS --> Cowrie KaliOS --> Agent end subgraph "Aegis-SIEM — 192.168.56.102" Suricata[Suricata 7.0.3
50,180 ETOpen rules] Wazuh[Wazuh 4.14.5
Manager + Indexer + Dashboard] CDB[(Threat Intel CDB
517 IPs)] PKI[2-tier PKI
Root + Intermediate CA] Suricata -->|eve.json| Wazuh CDB -->|enrichment| Wazuh PKI -->|HTTPS| Wazuh end Agent -->|encrypted| Wazuh end Attacker[Attacker traffic] --> Kali Attacker --> Suricata | Component | Detail | |---|---| | Host OS | Windows, 16 GB RAM | | Hypervisor | Oracle VirtualBox | | Lab Network | Host-only `LabNet` — 192.168.56.0/24, no internet bridge | | SIEM VM | Ubuntu Server 24.04 — 4 GB RAM, 60 GB disk | | Endpoint VM | Kali Linux 2026.1 — 4 GB RAM, 40 GB disk | | SIEM Stack | Wazuh 4.14.5 (manager + indexer + dashboard, all-in-one) | | IDS | Suricata 7.0.3 on `enp0s8`, HOME_NET=`192.168.56.102/32` | | Honeypot | Cowrie SSH honeypot on TCP/2222 (systemd) | | Ruleset | ETOpen 50,180 rules + 7 custom Wazuh rules (100200–100205, 100300) | | Threat Intel | Emerging Threats Compromised IPs — 517-entry CDB list | | PKI | 2-tier (Root CA → Intermediate CA → Server cert) using OpenSSL | ## Phase 1 — Foundation ### Objective Establish a fully isolated lab environment with two virtual machines that can communicate with each other but cannot reach the public internet. Isolation is the most important property here — every attack in this lab is allowed to be loud, destructive, and obvious, because nothing leaves the host. ### Implementation Oracle VirtualBox was chosen as the hypervisor for its no-cost availability on Windows and its straightforward host-only networking. Two VMs were provisioned: The host-only network `LabNet` was configured as `192.168.56.0/24` with DHCP disabled. Both VMs received static IPs (`192.168.56.101` for Kali, `192.168.56.102` for the SIEM) configured in `/etc/netplan/` on Ubuntu and `/etc/network/interfaces.d/` on Kali. After initial package installation, the NAT NIC on each VM was disabled to enforce isolation. ### Verification # From Kali ping -c 2 192.168.56.102 # Should succeed ping -c 2 8.8.8.8 # Should fail (isolation working) ### Outcome Two reachable, isolated VMs forming the substrate for everything that follows. The lab is a sealed environment — attacker traffic, IDS signatures, and SIEM telemetry all stay inside. ## Phase 2 — SIEM Installation ### Objective Deploy a SIEM platform on `Aegis-SIEM` capable of ingesting endpoint logs, network alerts, and file integrity events from multiple sources, with a queryable dashboard for incident response. ### Implementation Wazuh 4.14.5 was deployed using the official all-in-one installer, which bundles the manager, indexer (OpenSearch fork), and dashboard onto a single host. The all-in-one approach was chosen because it mirrors how small organizations actually deploy Wazuh — separate-host topology adds operational complexity that isn't useful for a learning lab. # Download and run the all-in-one installer curl -sO https://packages.wazuh.com/4.14/wazuh-install.sh sudo bash ./wazuh-install.sh -a The installer generated initial credentials and bootstrapped the certificates needed for inter-component TLS. The dashboard came up at `https://192.168.56.102` on port 443. ### Verification # Check that all three services are running sudo systemctl status wazuh-manager wazuh-indexer wazuh-dashboard All three returned `active (running)`. Logging into the dashboard and navigating to the Management section showed the manager status as healthy with the indexer reachable. ### Outcome A fully functional SIEM ready to receive telemetry from agents. The dashboard's self-signed certificate would be replaced with a proper PKI chain in Phase 6. ## Phase 3 — Agent Deployment ### Objective Enrol the Kali endpoint as a managed agent of the Wazuh manager so that endpoint logs, system events, and command-line activity flow into the SIEM in real time. ### Implementation On the SIEM, a new agent was registered through the dashboard's agent management interface. The dashboard generated a registration command containing the manager's IP and an enrolment key. On Kali, the Wazuh agent package was installed and pointed at the manager: curl -so wazuh-agent.deb \ https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_4.14.5-1_amd64.deb sudo WAZUH_MANAGER='192.168.56.102' WAZUH_AGENT_NAME='Kali-Lab' \ dpkg -i ./wazuh-agent.deb sudo systemctl enable wazuh-agent --now The agent appeared in the dashboard as `Kali-Lab` with ID `001`, status `Active`. The default agent configuration ingested `/var/log/auth.log`, `/var/log/syslog`, and several other standard Linux log sources. ### Verification A test event was triggered on Kali (`sudo whoami` with a deliberately wrong password) and the corresponding alert appeared in the dashboard's Security Events view within seconds. ### Outcome Telemetry pipeline operational. The lab now has visibility into endpoint activity on Kali. Everything that follows — sudo brute-force detection, FIM, honeypot integration — depends on this pipeline working. ## Phase 4 — First Detection: Sudo Brute-Force ### Objective Validate that the SIEM detects a real attacker technique end-to-end: from action on the endpoint, through log capture by the agent, to alert generation by the manager, to visibility in the dashboard. ### Implementation The attacker technique chosen was a sudo brute-force attempt — repeated failed `sudo` invocations as a low-privileged user attempting to escalate. This maps to **MITRE T1548.003 — Abuse Elevation Control Mechanism: Sudo and Sudo Caching**. The Wazuh default ruleset includes detections for repeated authentication failures, but sudo-specific rules are part of the standard `pam_rules.xml` ruleset, which triggers on multiple failed `sudo` events from `/var/log/auth.log`. ### Attack simulation On Kali, as a non-root user: for i in {1..8}; do echo "wrongpassword$i" | sudo -S whoami 2>/dev/null done ### Detection Within seconds of the attack, the Wazuh dashboard showed multiple alerts at `rule.level >= 5`, escalating into a correlated high-severity alert when the failure threshold was crossed. The triggered rule was Wazuh's default `5403` (multiple sudo failures) with the MITRE ID surfaced in the alert metadata. ### Outcome First confirmed end-to-end detection. The platform works. This phase is small but critical — every subsequent phase assumes this pipeline is reliable. | Field | Value | |---|---| | Technique | T1548.003 | | Wazuh Rule | 5403 (multiple sudo failures) | | Log Source | `/var/log/auth.log` | ## Phase 4.5 — FIM & Persistence Detection ### Objective Detect attacker persistence — specifically, the creation of a backdoor user account — using Wazuh's File Integrity Monitoring (FIM) module. ### Implementation FIM was already enabled in the default agent configuration with a default scan interval. The agent's `ossec.conf` was reviewed to confirm `/etc/passwd` and `/etc/shadow` were under FIM watch:
/etc
Real-time monitoring meant that changes to files under `/etc` would be detected within seconds rather than waiting for the next periodic scan.
### Attack simulation
On Kali, simulating attacker persistence:
sudo useradd -m -s /bin/bash backdoor_user
sudo passwd backdoor_user # set a known password
### Detection
The dashboard surfaced two FIM alerts almost immediately: one for the modification of `/etc/passwd` (new line added) and one for `/etc/shadow` (new hashed password entry). Each alert showed the before/after diff and the SHA256 hash change.
This maps to **MITRE T1565.001 — Stored Data Manipulation**, the technique family that covers adversary modification of stored data including system files like `/etc/passwd`.
### Outcome
FIM works as the second line of detection — even if the attacker disables shell logging or wipes `auth.log`, the FIM module catches the file modifications. This is the defence-in-depth principle in action: multiple independent detection layers for the same attacker objective.
| Field | Value |
|---|---|
| Technique | T1565.001 |
| Wazuh Rule | 550 (FIM file modified), 554 (FIM file added) |
| Log Source | FIM real-time syscheck |
## Phase 5 — Network Reconnaissance & SSH Brute-Force
### Objective
Detect network-level attacker activity — port scanning and credential brute-forcing — that originates from off-host rather than from inside the endpoint.
### Implementation
Two attack vectors were simulated against the SIEM box from Kali. The first was an nmap port scan; the second was an SSH brute-force using `hydra` against the SIEM's SSH service.
For the nmap detection, Wazuh's default ruleset includes `5712` ("SSHD: ATTACK Possible attack on the ssh server (or version gathering)") and related rules that trigger on patterns indicative of scanning activity surfacing through `/var/log/auth.log` and SSH daemon logs.
For SSH brute-force, Wazuh's `5712` and the higher-severity `5720` (multiple SSH authentication failures from same source) provided the correlation logic.
### Attack simulation
# Reconnaissance
sudo nmap -sS -sV -p 1-1000 192.168.56.102
# SSH brute-force using a small wordlist
hydra -l aegis -P /usr/share/wordlists/rockyou-small.txt \
ssh://192.168.56.102 -t 4 -V
### Detection
The nmap scan produced multiple `5712` alerts as SSH connection attempts probed the service. The hydra run produced a cascade of `5710` alerts (sshd authentication failed) culminating in rule `5720` firing at level 10 once the threshold of failures from a single source IP was crossed.
The brute-force activity maps to **MITRE T1110 — Brute Force**, and the network discovery activity maps to **T1046 — Network Service Discovery**.
### Outcome
Network-level attacks now generate alerts even when no agent is installed on the attacker's machine. This is important because not every adversary will obligingly install your agent — most network detection has to happen from the SIEM's vantage point or from a network sensor (which Phase 8 will add).
| Field | Value |
|---|---|
| Techniques | T1110, T1046 |
| Wazuh Rules | 5710, 5712, 5720 |
| Log Source | `/var/log/auth.log` |
## Phase 6 — PKI Deep Dive
### Objective
### Implementation
A two-tier Certificate Authority was built using OpenSSL:
1. **Root CA** — Long-lived (10 years), kept offline conceptually (encrypted with passphrase, never used directly for issuance)
2. **Intermediate CA** — Shorter-lived, signed by the Root CA, used to issue end-entity certificates
3. **Server certificate** — Signed by the Intermediate CA, with a Subject Alternative Name (SAN) extension covering the IP `192.168.56.102` and hostnames `aegis-siem` and `aegis-siem.lab`
The full directory structure lived in `~/aegis-pki/` with separate subdirectories for `root-ca/`, `intermediate-ca/`, and `certs/`. CA private keys were AES-256 encrypted with a strong passphrase (redacted) — kept out of the repository for obvious reasons.
Key OpenSSL configuration excerpt for the server cert:
[ server_cert ]
basicConstraints = CA:FALSE
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = aegis-siem
DNS.2 = aegis-siem.lab
DNS.3 = localhost
IP.1 = 192.168.56.102
IP.2 = 127.0.0.1
Once the server certificate was issued, it was deployed into the Wazuh dashboard's certificate path along with the full chain (server + intermediate), and the dashboard service was restarted.
The Root CA was then imported into Edge's trusted root store on the Windows host, completing the chain of trust.
### Verification
Loading `https://192.168.56.102` in Edge produced a green padlock with no warnings. The certificate viewer showed the full three-tier chain: Aegis Lab Root CA → Aegis Lab Intermediate CA → aegis-siem certificate.
### Outcome
A production-realistic PKI. Real organizations almost never deploy SIEMs with self-signed certificates — they integrate with internal CAs. This phase demonstrates the same operation in miniature, with attention to SAN configuration (the most common cause of "this site is not secure" warnings in real deployments).
## Phase 7 — Cowrie Honeypot
### Objective
Deploy an interactive SSH honeypot that lets attackers "log in" with weak credentials, captures every command they type, and surfaces structured session telemetry to Wazuh as high-severity alerts.
### Implementation
Cowrie was installed on Kali as a Python application, running as a dedicated non-privileged user, exposed on port `2222` (since the real SSH service still listened on `22`). A systemd unit was authored to manage the service:
[Unit]
Description=Cowrie SSH Honeypot
After=network.target
[Service]
Type=simple
User=cowrie
WorkingDirectory=/opt/cowrie
ExecStart=/opt/cowrie/bin/cowrie start -n
ExecStop=/opt/cowrie/bin/cowrie stop
Restart=on-failure
[Install]
WantedBy=multi-user.target
Cowrie was configured to emit JSON logs to `/opt/cowrie/var/log/cowrie/cowrie.json`. The Wazuh agent on Kali was extended to read this file as a `json` log source.
The custom detection rules were authored in `/var/ossec/etc/rules/cowrie_rules.xml`, covering six distinct honeypot events:
| Rule ID | Event | Level | MITRE |
|---|---|---|---|
| 100200 | Cowrie session connected | 5 | T1078 |
| 100201 | Cowrie login failed | 7 | T1110 |
| 100202 | Cowrie login succeeded (low-effort credentials) | 10 | T1078 |
| 100203 | Cowrie command executed inside session | 10 | T1059 |
| 100204 | Cowrie file downloaded by attacker | 12 | T1105 |
| 100205 | Cowrie session disconnected | 3 | — |
A common gotcha during authoring: the description variable `$(username)` only resolves correctly when the decoder extracts the field with that exact name. Several iterations were required to get the decoder, rule field reference, and JSON path all aligned.
### Verification
A test login from a separate machine using `ssh root@192.168.56.101 -p 2222` with the password `123456` produced a cascade of alerts — connection at level 5, failed attempts at level 7, eventual "success" at level 10 (Cowrie accepts certain weak credentials by design to keep the attacker engaged), then command alerts at level 10 for every command typed inside the fake shell.
### Outcome
An active deception layer. Cowrie tarpits attackers and feeds rich session telemetry — every command, every download attempt, every credential pair tried — into Wazuh with custom MITRE-mapped detections.
## Phase 8 — Network IDS with Suricata
### Objective
Add Layer-3 visibility to the lab by deploying Suricata as a network IDS on the SIEM host, with full ETOpen ruleset enabled and alerts forwarded to Wazuh.
### Implementation
Suricata 7.0.3 was installed on `Aegis-SIEM` and bound to the host-only interface `enp0s8`. The `HOME_NET` variable in `suricata.yaml` was set to `192.168.56.102/32` — the SIEM itself — so that "inbound" alerts mean traffic destined for the SIEM rather than passing through it. (This is a common point of confusion: HOME_NET defines what counts as *inside* the network you're defending.)
The full ETOpen ruleset was downloaded and enabled — 50,180 signatures covering everything from port scans to known C2 traffic patterns to specific CVE exploit attempts. The ruleset was updated with `suricata-update`.
Suricata's `eve.json` output (the structured JSON event log) was written to `/var/log/suricata/eve.json`. The Wazuh manager was configured to read this file as a `json` log source.
Wazuh ships with a built-in rule `86601` ("Suricata: Alert") that parses Suricata events from `eve.json` and creates corresponding Wazuh alerts. No custom rule was needed for the basic integration — but Phase 9 would build on top of it.
json
/var/log/suricata/eve.json
### Verification
An nmap scan from Kali (`sudo nmap -sS -A 192.168.56.102`) triggered multiple Suricata signatures, all of which surfaced in Wazuh as `86601` alerts within seconds. The signatures that fired included `ET SCAN Suspicious inbound to MSSQL port 1433`, `ET INFO Possible Kali Linux hostname in DHCP Request Packet`, and various scan-detection rules.
### Outcome
Layer-3 visibility added. The lab now sees attacks at the packet level, not just from endpoint logs. The combination of FIM (Phase 4.5) + endpoint logs (Phases 3–5) + honeypot telemetry (Phase 7) + network IDS (Phase 8) provides genuine defence-in-depth.
| Field | Value |
|---|---|
| Techniques | T1046, T1190 |
| Wazuh Rule | 86601 (Suricata: Alert) |
| Suricata Interface | `enp0s8` |
| Ruleset Size | 50,180 ETOpen rules |
## Phase 9 — Threat Intelligence Enrichment
### Objective
Cross-reference every Suricata alert against a curated feed of known-malicious IPs in real time, firing a separate high-severity alert when a match is found. This is the difference between *suspicious traffic* and *known bad actor* — the prioritization a SOC analyst actually needs.
### Implementation
A Wazuh CDB list (Constant Database, used for fast key-value lookups inside rules) was built from the Emerging Threats Compromised IPs feed:
sudo curl -o /tmp/compromised-ips.txt \
https://rules.emergingthreats.net/blockrules/compromised-ips.txt
# Format as Wazuh CDB list: "IP:label" per line
sudo awk 'NF && !/^#/ {print $0":ET_COMPROMISED"}' /tmp/compromised-ips.txt \
| sudo tee /var/ossec/etc/lists/threat_intel_ips > /dev/null
# Add lab test entry for end-to-end validation
echo "192.168.56.101:LAB_TEST_KALI" \
| sudo tee -a /var/ossec/etc/lists/threat_intel_ips > /dev/null
Final list: 517 entries (516 ET-sourced + 1 lab test).
The CDB list was referenced in `ossec.conf`:
Wazuh 4.x auto-compiles CDB lists at manager restart — no separate `makelists` step needed (older guides reference this; the binary doesn't exist in 4.x).
The cascade rule was authored in `/var/ossec/etc/rules/threat_intel_rules.xml`:
86601
THREAT INTEL HIT: Suricata alert from known malicious IP $(src_ip) - cross-reference matched
T1595
threat_intel,attack,
Three things doing the work: `86601 ` only fires this rule as a child of Wazuh's Suricata rule; `
port 2222] Agent[Wazuh Agent 001] KaliOS --> Cowrie KaliOS --> Agent end subgraph "Aegis-SIEM — 192.168.56.102" Suricata[Suricata 7.0.3
50,180 ETOpen rules] Wazuh[Wazuh 4.14.5
Manager + Indexer + Dashboard] CDB[(Threat Intel CDB
517 IPs)] PKI[2-tier PKI
Root + Intermediate CA] Suricata -->|eve.json| Wazuh CDB -->|enrichment| Wazuh PKI -->|HTTPS| Wazuh end Agent -->|encrypted| Wazuh end Attacker[Attacker traffic] --> Kali Attacker --> Suricata | Component | Detail | |---|---| | Host OS | Windows, 16 GB RAM | | Hypervisor | Oracle VirtualBox | | Lab Network | Host-only `LabNet` — 192.168.56.0/24, no internet bridge | | SIEM VM | Ubuntu Server 24.04 — 4 GB RAM, 60 GB disk | | Endpoint VM | Kali Linux 2026.1 — 4 GB RAM, 40 GB disk | | SIEM Stack | Wazuh 4.14.5 (manager + indexer + dashboard, all-in-one) | | IDS | Suricata 7.0.3 on `enp0s8`, HOME_NET=`192.168.56.102/32` | | Honeypot | Cowrie SSH honeypot on TCP/2222 (systemd) | | Ruleset | ETOpen 50,180 rules + 7 custom Wazuh rules (100200–100205, 100300) | | Threat Intel | Emerging Threats Compromised IPs — 517-entry CDB list | | PKI | 2-tier (Root CA → Intermediate CA → Server cert) using OpenSSL | ## Phase 1 — Foundation ### Objective Establish a fully isolated lab environment with two virtual machines that can communicate with each other but cannot reach the public internet. Isolation is the most important property here — every attack in this lab is allowed to be loud, destructive, and obvious, because nothing leaves the host. ### Implementation Oracle VirtualBox was chosen as the hypervisor for its no-cost availability on Windows and its straightforward host-only networking. Two VMs were provisioned: The host-only network `LabNet` was configured as `192.168.56.0/24` with DHCP disabled. Both VMs received static IPs (`192.168.56.101` for Kali, `192.168.56.102` for the SIEM) configured in `/etc/netplan/` on Ubuntu and `/etc/network/interfaces.d/` on Kali. After initial package installation, the NAT NIC on each VM was disabled to enforce isolation. ### Verification # From Kali ping -c 2 192.168.56.102 # Should succeed ping -c 2 8.8.8.8 # Should fail (isolation working) ### Outcome Two reachable, isolated VMs forming the substrate for everything that follows. The lab is a sealed environment — attacker traffic, IDS signatures, and SIEM telemetry all stay inside. ## Phase 2 — SIEM Installation ### Objective Deploy a SIEM platform on `Aegis-SIEM` capable of ingesting endpoint logs, network alerts, and file integrity events from multiple sources, with a queryable dashboard for incident response. ### Implementation Wazuh 4.14.5 was deployed using the official all-in-one installer, which bundles the manager, indexer (OpenSearch fork), and dashboard onto a single host. The all-in-one approach was chosen because it mirrors how small organizations actually deploy Wazuh — separate-host topology adds operational complexity that isn't useful for a learning lab. # Download and run the all-in-one installer curl -sO https://packages.wazuh.com/4.14/wazuh-install.sh sudo bash ./wazuh-install.sh -a The installer generated initial credentials and bootstrapped the certificates needed for inter-component TLS. The dashboard came up at `https://192.168.56.102` on port 443. ### Verification # Check that all three services are running sudo systemctl status wazuh-manager wazuh-indexer wazuh-dashboard All three returned `active (running)`. Logging into the dashboard and navigating to the Management section showed the manager status as healthy with the indexer reachable. ### Outcome A fully functional SIEM ready to receive telemetry from agents. The dashboard's self-signed certificate would be replaced with a proper PKI chain in Phase 6. ## Phase 3 — Agent Deployment ### Objective Enrol the Kali endpoint as a managed agent of the Wazuh manager so that endpoint logs, system events, and command-line activity flow into the SIEM in real time. ### Implementation On the SIEM, a new agent was registered through the dashboard's agent management interface. The dashboard generated a registration command containing the manager's IP and an enrolment key. On Kali, the Wazuh agent package was installed and pointed at the manager: curl -so wazuh-agent.deb \ https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_4.14.5-1_amd64.deb sudo WAZUH_MANAGER='192.168.56.102' WAZUH_AGENT_NAME='Kali-Lab' \ dpkg -i ./wazuh-agent.deb sudo systemctl enable wazuh-agent --now The agent appeared in the dashboard as `Kali-Lab` with ID `001`, status `Active`. The default agent configuration ingested `/var/log/auth.log`, `/var/log/syslog`, and several other standard Linux log sources. ### Verification A test event was triggered on Kali (`sudo whoami` with a deliberately wrong password) and the corresponding alert appeared in the dashboard's Security Events view within seconds. ### Outcome Telemetry pipeline operational. The lab now has visibility into endpoint activity on Kali. Everything that follows — sudo brute-force detection, FIM, honeypot integration — depends on this pipeline working. ## Phase 4 — First Detection: Sudo Brute-Force ### Objective Validate that the SIEM detects a real attacker technique end-to-end: from action on the endpoint, through log capture by the agent, to alert generation by the manager, to visibility in the dashboard. ### Implementation The attacker technique chosen was a sudo brute-force attempt — repeated failed `sudo` invocations as a low-privileged user attempting to escalate. This maps to **MITRE T1548.003 — Abuse Elevation Control Mechanism: Sudo and Sudo Caching**. The Wazuh default ruleset includes detections for repeated authentication failures, but sudo-specific rules are part of the standard `pam_rules.xml` ruleset, which triggers on multiple failed `sudo` events from `/var/log/auth.log`. ### Attack simulation On Kali, as a non-root user: for i in {1..8}; do echo "wrongpassword$i" | sudo -S whoami 2>/dev/null done ### Detection Within seconds of the attack, the Wazuh dashboard showed multiple alerts at `rule.level >= 5`, escalating into a correlated high-severity alert when the failure threshold was crossed. The triggered rule was Wazuh's default `5403` (multiple sudo failures) with the MITRE ID surfaced in the alert metadata. ### Outcome First confirmed end-to-end detection. The platform works. This phase is small but critical — every subsequent phase assumes this pipeline is reliable. | Field | Value | |---|---| | Technique | T1548.003 | | Wazuh Rule | 5403 (multiple sudo failures) | | Log Source | `/var/log/auth.log` | ## Phase 4.5 — FIM & Persistence Detection ### Objective Detect attacker persistence — specifically, the creation of a backdoor user account — using Wazuh's File Integrity Monitoring (FIM) module. ### Implementation FIM was already enabled in the default agent configuration with a default scan interval. The agent's `ossec.conf` was reviewed to confirm `/etc/passwd` and `/etc/shadow` were under FIM watch:
- etc/lists/threat_intel_ips
- etc/lists/threat_intel_ips
- ` looks up the JSON `src_ip` field as a key in the CDB; `level="12"` puts the alert at the top of any prioritization queue.
### Validation — synthetic injection
Before running real traffic, the rule logic was validated by injecting a fake Suricata event:
sudo bash -c 'echo "{\"timestamp\":\"2026-05-25T11:35:00.000+0000\",\"flow_id\":2,\"src_ip\":\"192.168.56.101\",\"src_port\":22222,\"dest_ip\":\"192.168.56.102\",\"dest_port\":22,\"proto\":\"TCP\",\"event_type\":\"alert\",\"alert\":{\"signature\":\"TEST INJECTION FROM KALI\",\"signature_id\":99999,\"severity\":2}}" >> /var/log/suricata/eve.json'
Expected output in `alerts.json`:
L12: THREAT INTEL HIT: Suricata alert from known malicious IP 192.168.56.101 - cross-reference matched
✅ Logic confirmed before exposing the rule to real traffic.
### Verification — live attack
A real nmap scan was launched from Kali:
sudo nmap -sS -sV -A -p 1-1000 192.168.56.102
Within the scan window, six rule `100300` alerts were generated in `alerts.json`, four of which fell inside the dashboard's 15-minute view. The Suricata signatures that triggered the cascade included:
ET SCAN Suspicious inbound to MSSQL port 1433
ET INFO Possible Kali Linux hostname in DHCP Request Packet (x2)
SURICATA ICMPv4 unknown code
The `ET INFO Possible Kali Linux hostname in DHCP Request Packet` signature is particularly telling: Suricata identified the attacker's operating system by name from a single DHCP request packet. The attacker's own machine announced what it was.
Not every Suricata alert cascaded into rule `100300`, which is correct behaviour: some signatures (ICMPv4 anomalies, certain DHCP detections) don't populate `src_ip` in the standard field, so they fire `86601` but can't be enriched against a source-IP reputation list.
### Outcome
For a SOC analyst, the value is prioritization. With Phase 8 alone, every Suricata alert demands triage. With Phase 9, alerts split cleanly into two tiers:
- Level 3–7 (default Suricata) — opportunistic activity from an unknown source. Triage when time permits.
- Level 12 (enriched) — activity from a source we already have intelligence on. *Look now.*
The same pattern (CDB list + child rule with `
- ` lookup) extends naturally to layer reputation onto Cowrie honeypot alerts (Phase 7), brute-force events (Phase 5), or any other Wazuh-parsed source.
| Field | Value |
|---|---|
| Technique | T1595 (Active Scanning) |
| Custom Rule | 100300 (Level 12) |
| Parent Rule | 86601 (Suricata: Alert) |
| Threat Intel Feed | Emerging Threats Compromised IPs (517 entries) |
## Cross-Phase Lessons Learned
**Wazuh 4.x changed CDB list handling.** Older guides reference `/var/ossec/bin/ossec-makelists` to compile the binary `.cdb` from the text source. That binary doesn't exist in 4.x — the manager auto-compiles on restart. Don't hunt for it.
**JSON field naming matters in rule definitions.** Custom rules referencing Suricata events must use `src_ip` (underscore, matching the JSON path), not `srcip` (the older Wazuh decoder convention). Using the wrong name silently fails — the rule compiles, the parent fires, and the child never matches. The same applies to `$(src_ip)` in description variables.
**Threat intel feed shape matters more than feed quality.** Wazuh CDB lists match exact IPs only — not CIDR ranges. FireHOL Level 1 is mostly ranges and would not have worked. Emerging Threats Compromised IPs is single-IP entries, which is the right shape. Pick feeds that match your tool's lookup semantics, not just by reputation.
**Regional ISP blocks affect feed choice.** `torproject.org` was unreachable from UAE due to SSL handshake blocking. Switching to `emergingthreats.net` solved the connectivity problem. Worth knowing if you build labs in regions with content filtering.
**PKI hostname binding is brittle.** Browser-trusted dashboards require the certificate's SAN to exactly match how you access the URL — IP vs hostname vs FQDN all count. Most "this site is not secure" warnings in real deployments come from this exact mismatch.
**Suricata HOME_NET defines what counts as "internal."** Get it wrong and either everything looks like an attack or nothing does. For a single-host lab sensor watching its own ingress, `HOME_NET=
- `. MITRE ATT&CK mapping at the rule level.
**Tooling.** Wazuh full stack (manager, indexer, dashboard, agents) — installation, hardening, custom rule deployment, FIM configuration. Suricata 7.0.3 — interface binding, ETOpen ruleset management, eve.json output, SIEM integration. Cowrie SSH honeypot — installation, systemd service authoring, JSON logging configuration.
**Cryptography and PKI.** Two-tier Certificate Authority (Root CA + Intermediate CA) using OpenSSL. Subject Alternative Names, key usage and extended key usage extensions, certificate chain validation. Trusted dashboard HTTPS with full chain installed in browser trust stores.
**Linux and Infrastructure.** Ubuntu Server 24.04 administration. systemd service authoring and dependency management. Network configuration via netplan. Log pipeline troubleshooting across file permissions, JSON path mismatches, and decoder field naming.
**Adversary Simulation.** Sudo brute-force (T1548.003), backdoor user creation (T1565.001), nmap reconnaissance with version detection and OS fingerprinting, SSH credential brute-force using hydra (T1110).
## What's Next
Possible extensions if the lab continues to grow:
- **Windows endpoint.** Add a Windows 11 victim VM with Sysmon forwarding to Wazuh. Most enterprise environments are Windows-heavy and the rule logic differs substantially from Linux.
- **Velociraptor for forensics.** Layer Velociraptor on top of Wazuh as an endpoint forensics tool. Wazuh detects; Velociraptor investigates.
- **Active response automation.** Wire Wazuh's active response framework into iptables so that a level-12 alert (e.g. rule 100300) automatically blocks the offending IP for a configurable duration. This is the lab's path toward SOAR-style automation.
- **MISP for managed threat intel.** Replace the single-feed CDB list with MISP, supporting multiple feeds, taxonomy, and IOC sharing. The CDB pattern remains, but the source becomes pluggable.
- **Detection-as-code.** Version every custom Wazuh rule with a CI test harness — synthetic events for each rule, automated assertions that the expected alert fires. This transforms ad-hoc rule writing into a sustainable engineering practice.
*Aegis is a learning project built solo over multiple months. Every detection above was tested against a simulated attack and verified in the dashboard.*