courses

Lab — Week 7: Detection and Monitoring
Due: 14 August 2026
Submission: GitLab repo secdevops-s26-<CECS>

Overview

Build the detection layer on top of the preventive controls: knowing when an attack is happening, what it’s doing, and how to respond.

Prerequisites


Part 1: Wazuh Rules, Tuning, and Active Response

Built-in Wazuh rules cover standard Linux events well but know nothing about DVWA’s specific log format or your threat model’s priority threats. This part writes two custom detection rules, tests them by triggering the attack from Kali, and configures an active response that automatically blocks a brute-force source.

Custom Rule: DVWA Login Brute Force

  1. On the Wazuh manager (10.10.10.30), create /var/ossec/etc/rules/local_rules.xml if it does not exist.

  2. Write a rule pair:
    • A parent rule (level 3, id in range 100001–100099) that matches any nginx access log line referencing /dvwa/login.php
    • A child rule (level 10) using frequency and timeframe that fires when the parent rule matches 5 or more times from the same source IP within 60 seconds
  3. Test the rule syntax without restarting:
    /var/ossec/bin/wazuh-logtest
    

    Paste a sample nginx log line for /dvwa/login.php and confirm the parent rule matches.

  4. Restart the manager: sudo systemctl restart wazuh-manager

  5. From Kali, trigger the brute-force rule:
    for i in {1..7}; do
      curl -s -o /dev/null -X POST http://10.10.10.20/dvwa/login.php \
        -d "username=admin&password=wrong&Login=Login"
    done
    
  6. Confirm the level-10 alert fires in the Wazuh dashboard. Take a screenshot showing the rule ID, level, and source IP.

Custom Rule: Unexpected Container Spawn

  1. Write a second rule (level 12, id in range 100100–100199) in the same local_rules.xml that fires when a docker run or docker exec command appears in the auditd log outside of the docker compose process tree.

    Use <match> or <regex> targeting the execve syscall with docker run in the arguments, and <if_matched_group> or <different_user> to distinguish ad-hoc runs from compose-managed ones if possible.

  2. Test from ubuntu-server: docker run --rm hello-world

  3. Confirm the alert fires in the dashboard. Take a screenshot.

Active Response

  1. On the Wazuh manager, configure firewall-drop to trigger when the DVWA brute-force rule (your level-10 rule) fires:
    <active-response>
      <command>firewall-drop</command>
      <location>local</location>
      <rules_id>YOUR_RULE_ID</rules_id>
      <timeout>3600</timeout>
    </active-response>
    

    Add this stanza to /var/ossec/etc/ossec.conf on the manager, inside <ossec_config>.

  2. Restart the manager: sudo systemctl restart wazuh-manager

  3. From Kali, trigger the brute-force rule again (5+ POST requests in 60 seconds).

  4. On ubuntu-server, confirm the active response fired:
    sudo tail -20 /var/ossec/logs/active-responses.log
    sudo nft list ruleset | grep 10.10.10.10
    
  5. Take a screenshot showing the blocked IP in nftables.

  6. Unblock Kali: sudo nft delete element inet ... @blocked_ips { 10.10.10.10 } or wait for the 3600-second timeout.

Deliverables

Create lab13/ in your repo containing:


Part 2: Suricata Integration and File Integrity Monitoring

Network and host detection are complementary layers. Suricata sees packet contents; auditd sees syscalls. Neither sees everything the other does. This part adds network-layer detection by integrating Suricata EVE logs with Wazuh, writes a custom Suricata rule targeting a known attack pattern, and completes the FIM configuration to detect unauthorized changes to critical files — closing the final gaps in your detection stack.

Part 1 must be complete — Wazuh custom rules working.

Suricata Setup

  1. Enable and start Suricata in IDS mode on ubuntu-server, monitoring the primary interface (check ip a to confirm the interface name — likely ens19 or ens18):
    sudo sed -i 's/- interface: eth0/- interface: ens19/' /etc/suricata/suricata.yaml
    sudo systemctl enable --now suricata
    sudo suricata --build-info | grep "AF_PACKET"   # confirm AF_PACKET support
    
  2. Confirm Suricata is writing EVE JSON:
    sudo tail -5 /var/log/suricata/eve.json | python3 -m json.tool
    

Wazuh–Suricata Integration

  1. On ubuntu-server, add the following to /var/ossec/etc/ossec.conf inside <ossec_config>:
    <localfile>
      <log_format>json</log_format>
      <location>/var/log/suricata/eve.json</location>
    </localfile>
    
  2. Restart the Wazuh agent: sudo systemctl restart wazuh-agent

  3. From Kali, generate traffic that will produce Suricata events:
    nmap -sV 10.10.10.20
    
  4. Confirm Suricata alert events appear in the Wazuh dashboard filtered by rule.groups: suricata. Take a screenshot.

Custom Suricata Rule

  1. Write a custom Suricata rule in /etc/suricata/rules/local.rules that detects nmap SYN scans:
    alert tcp any any -> $HOME_NET any (
      msg:"Nmap SYN scan detected";
      flags:S,12;
      threshold:type threshold, track by_src, count 10, seconds 2;
      sid:9000001; rev:1;
    )
    
  2. Reference the rule file in /etc/suricata/suricata.yaml under rule-files:.

  3. Reload Suricata rules: sudo suricatasc -c reload-rules

  4. Trigger the rule from Kali: nmap -sS 10.10.10.20

  5. Confirm the custom rule fires in both eve.json and the Wazuh dashboard. Take a screenshot of the Wazuh alert showing your rule’s msg field.

File Integrity Monitoring

  1. On ubuntu-server, configure Wazuh FIM in /var/ossec/etc/ossec.conf to monitor:
    • /etc (all files, check_all=”yes”)
    • /etc/nginx/ (all files)
    • The directory containing your docker-compose.yml

    Set <frequency>300</frequency> (5-minute check interval).

  2. Restart the Wazuh agent: sudo systemctl restart wazuh-agent

  3. Force an immediate FIM baseline scan:
    sudo /var/ossec/bin/agent_control -r -u <agent-id>
    
  4. Simulate post-compromise tampering from ubuntu-server itself:
    echo "# tampered" | sudo tee -a /etc/nginx/nginx.conf
    
  5. Wait up to 5 minutes, or force a rescan. Confirm the FIM alert fires in the Wazuh dashboard. Take a screenshot showing the modified file path and the before/after hash.

  6. Restore the file: sudo sed -i '/# tampered/d' /etc/nginx/nginx.conf

Threat Model — Final

  1. In lab02/threat-model.md, mark all remaining OPEN threats with either MITIGATED (and the control), DETECTED (and the Wazuh/Suricata rule), or ACCEPTED RISK (with rationale). By the end of this lab, every original threat entry must have a non-OPEN status.

Deliverables

Create lab14/ in your repo containing:


Submission

Commit all files for both parts — lab13/ and lab14/ — and push to your GitLab repo. The lab is considered submitted when the commit appears in GitLab before the due date.