Most people who say they "know SIEM" have clicked through a managed tool someone else configured. I wanted to understand what happens underneath — how events actually move from a compromised machine to an alert, how detection rules are tuned, and what the full attack-detect-respond loop looks like when you're the one running all three sides of it.

So I built a dedicated lab. Isolated VLAN, intentionally vulnerable target, Kali Linux attacker, and a live Wazuh SIEM server watching everything. This is the writeup of what I built, how it works, and what I'm doing with it.

Architecture

The whole lab lives on a dedicated Lab VLAN 30 (10.0.30.x), isolated from my main LAN and IoT network by UniFi firewall rules. The machines on it can reach the internet for updates but cannot touch any other VLAN — except for one deliberate exception I'll explain below.

Machine Role OS IP
X1 Carbon (host) Wazuh SIEM Server Ubuntu Server 24.04 10.0.30.10 (static)
Kali VM Attacker + monitored node Kali Linux 10.0.30.x (DHCP)
Metasploitable 3 VM Attack target Ubuntu 14.04 10.0.30.8 (static)
Raspberry Pi 4 Monitored endpoint Raspberry Pi OS 10.0.30.x (DHCP)

The X1 Carbon runs Wazuh all-in-one — Manager, Indexer, and Dashboard on a single Ubuntu host. VirtualBox runs the Kali and Metasploitable VMs on top of it. Both VMs have Wazuh agents installed so I can see what's happening on the attacker machine too, not just the target.

The deliberate hole in the wall

Lab VLAN is locked down from everything — but I punched one controlled opening: Wazuh agents on Lab machines ship logs back to the SIEM server. Just logs. Nothing else.

This is the thing that makes it a real detection environment rather than just a sandbox. Full isolation would contain an attack but leave me blind to it. Allowing only log traffic out gives me the best of both worlds: the vulnerable machines can't touch anything valuable, but I see every attack event, every rule trigger, every lateral movement attempt — in real time, the way a SOC analyst would.

The firewall rule that makes this work took more than one try. In UniFi Network 10.37.x, Accept rules always appear below Drop rules in the same policy table — you can't reorder them. The fix was to modify the Drop rule itself to exclude specific IP ranges rather than trying to add an Accept override above it. One Drop rule, multiple destination ranges, and the log traffic finds its path.

What's running right now

// build status · September 2026
UniFi Lab VLAN 30 created and isolated
X1 Carbon: Ubuntu Server 24.04, static IP 10.0.30.10
Wazuh 4.9.2 all-in-one installed, dashboard accessible
VirtualBox 7.0.16 installed (MOK enrolled for Secure Boot)
Kali VM: running at 10.0.30.81, Wazuh agent connected
Metasploitable 3 VM: running at 10.0.30.8, Wazuh agent connected
Wazuh dashboard showing 3 active agents (Kali + Metasploitable 3 + TrueNAS)
First attack cycle: nmap recon + ProFTPD RCE + privilege escalation to root
TrueNAS production server wired in — real-world SSH, PAM, and CIS compliance events flowing
Raspberry Pi: agent install pending (no USB keyboard on hand)
SQL injection + web app attack scenarios
Custom Wazuh detection rules written

Things that broke (and how I fixed them)

A setup guide that only shows the happy path isn't useful. Here are the three problems that took real time to solve.

ProtonVPN intercepting lab traffic. VPN on the Mac creates a utun4 interface at 10.2.0.x that absorbs all 10.x.x.x traffic, including the Lab VLAN. SSH to the X1 Carbon timed out even though routing was otherwise correct. Fix: a static route on the Mac to bypass the VPN for Lab traffic specifically — one command, doesn't affect anything else.

Boot hang on the X1 Carbon. After every reboot, the server stalled at boot and required a physical console login before SSH would respond. Root cause: systemd-networkd-wait-online timing out on the unused ethernet port while NetworkManager handled WiFi. Fix: disable and mask the service. SSH comes up clean on every reboot now.

Wazuh agent version mismatch. Kali's apt repo installed the latest Wazuh agent (4.14.7) but the manager was 4.9.2. The agent registered but immediately errored: "version must be lower or equal to manager." Fix: pin the agent install to the exact manager version and set the manager IP in the config. This applies to every agent added going forward.

Attack Cycle 1: ProFTPD RCE to Root

The first full attack cycle ran on September 15, 2026. Starting from nothing on Kali (10.0.30.81), the goal was to reach root on Metasploitable 3 (10.0.30.8) while Wazuh watched.

Phase 1 — Recon. An nmap -sV -sC -O -T4 scan against the target returned 8 open ports: FTP (21), SSH (22), HTTP (80), Samba (445), CUPS (631), MySQL (3306), and two HTTP services on 8080/8181. Service version fingerprinting exposed the full stack — ProFTPD 1.3.5, Apache 2.4.7, OpenSSH 6.6.1, Samba 4.3.11. Wazuh generated recon alerts as the scan progressed.

Phase 2 — Initial access via CVE-2015-3306. ProFTPD 1.3.5 ships with a vulnerable mod_copy module that allows unauthenticated file copy via SITE CPFR/CPTO FTP commands. The Metasploit module exploit/unix/ftp/proftpd_modcopy_exec used this to write a PHP web shell to /var/www/html, then triggered it via HTTP to get a reverse shell. Result: command shell as www-data, no credentials required.

Phase 3 — Privilege escalation. With a shell as www-data, lateral movement to the vagrant account was possible using the Vagrant project's published insecure SSH private key — the default keypair shipped with every Vagrant box that was never rotated on this image. SSH required a legacy algorithm flag (PubkeyAcceptedKeyTypes=+ssh-rsa) due to the old OpenSSH version. The vagrant user has unrestricted passwordless sudo, so sudo su gave root immediately.

Phase Technique Tool Result
Recon Service version scan nmap -sV -sC 8 open ports enumerated
Initial Access CVE-2015-3306 ProFTPD mod_copy Metasploit Shell as www-data
Privilege Escalation Vagrant insecure SSH key + sudo SSH + sudo su Root shell

What Wazuh caught: 1,469 total events generated across the session. 1,455 authentication failures from the hydra brute-force attempt. The FTP exploit triggered ProFTPD session alerts (rule 11201) and a new listening port event (rule 533) when the reverse shell opened. The privilege escalation fired rule 5402 (successful sudo to ROOT) and rule 5305 (first-time su execution) within the same second. MITRE ATT&CK techniques mapped automatically: Password Guessing, Brute Force, Valid Accounts, Remote Services, Sudo and Sudo Caching. Every phase of the kill chain produced a distinct, correlated signature.

Extending to Production: TrueNAS Agent

Lab VMs are useful for controlled attack scenarios, but they only tell half the story. I also wanted Wazuh watching a system with real stakes attached — my self-hosted media and file server, which my household depends on daily. If it goes down, it's not just a lab exercise.

The challenge: TrueNAS SCALE has a read-only root filesystem. Running apt install works, but the install gets wiped on every system update. The solution was to run the Wazuh agent as a Docker container via the existing Dockge stack manager — persistent storage on the data pool, managed alongside every other service on the box.

There's no official standalone Wazuh agent image on Docker Hub, so I built one from a debian:12-slim base, pinned to the exact manager version (4.9.2), with host network mode and privileged: true so Wazuh can see through the container into the actual TrueNAS system. The host's /var/log and /etc are mounted read-only into the container.

A firewall exception was required — TrueNAS lives on the main LAN while the Wazuh manager is on the isolated Lab VLAN. The connection is one-way outbound only: the agent ships logs to the manager on port 1514 TCP. Nothing on the lab network can reach back.

Lesson learned — the tee heredoc pattern. Creating files over SSH with nano led to a paste error that put the wrong content in both files, causing the container to fail on build. The fix was using sudo tee /path/to/file << 'EOF' ... EOF — content and destination in one atomic command, no clipboard mix-ups, no CRLF line ending issues. Small thing, but it's the kind of operational habit that matters in a real environment.

Within minutes of the agent connecting, Wazuh ran an automatic CIS Debian Family Linux Benchmark compliance scan — 52 checks passed, 42 failed, 55% overall. It also began mapping events to MITRE ATT&CK tactics automatically: Defense Evasion, Initial Access, Persistence, Privilege Escalation, and Lateral Movement all appeared from normal system activity alone. Every SSH login generates correlated PAM session events. Every sudo command is tracked.

Wazuh dashboard showing TrueNAS agent overview with MITRE ATT&CK mapping and CIS benchmark compliance scan results

TrueNAS agent overview — MITRE ATT&CK auto-mapping and CIS Debian benchmark compliance scan running automatically on connect.

Wazuh threat hunting events view showing 208 real-world events from TrueNAS including PAM sessions, CIS benchmark checks, and host anomaly detection

208 real-world events in the first hour — SSH authentication, PAM session lifecycle, host-based anomaly detection, and CIS compliance findings.

What comes next

The first attack cycle is documented. Next phases:

SQL injection on the payroll app — the payroll_app.php endpoint exposed by nmap is likely injectable. This is a different attack surface — web app layer — with different detection signatures in Wazuh.

Custom detection rules — write my own Wazuh rules for behaviors the defaults don't catch. This is the part that translates most directly to real SOC work: understanding what your detection coverage actually is, and filling the gaps.

DVWA via Docker — add a dedicated web application target for broader web attack scenarios (XSS, brute force, file inclusion). Different attack surface, richer detection data.

Download the portfolio document

The full PDF writeup covers architecture diagrams, the complete attack scenario table, Wazuh configuration details, detection findings, and skills demonstrated — formatted for job applications and technical reviewers.

Download PDF Get in touch