>samit_hota
Back to research
CAREER & ADVISORY

Stop Building Home Labs That Only Teach You How to Hack

Samit Hota·
#homelab#detection-engineering#sysmon#blue-team

Most security home labs are a waste of time for modern career progression. The standard advice—download a vulnerable VM from VulnHub, run Metasploit, pop a root shell, and collect a flag—teaches you how to run scripts, not how production environments actually break or how modern defenders spot malicious activity. If you can’t answer what process execution events, network connections, or file modifications your attack generated, you’ve only learned half the craft.

If you want skills that translate directly to SOC analysis, detection engineering, or senior red teaming, you need a dual-sided lab: a vulnerable target sitting directly alongside an enterprise-grade telemetry and detection stack.

Here is a blueprint for building a tight, low-resource detection lab on a single Linux virtual machine using Docker, Sysmon for Linux, Promtail, Grafana Loki, and Grafana.

The Lab Architecture: Target + Telemetry Pipeline

Rather than spinning up four heavy virtual machines that eat up 32GB of RAM, this architecture isolates attack surfaces inside Docker containers on an Ubuntu 22.04 LTS host while monitoring system activity at the kernel level.

The telemetry flows in three distinct layers:

  1. Target Layer: Docker containers running vulnerable services (e.g., OWASP Juice Shop or exposed custom web applications) alongside native host services.
  2. Telemetry Layer: Microsoft Sysmon for Linux capturing eBPF-based system events (process creation, network connections, file modifications) and writing structured logs to syslog.
  3. Ingestion & Visualization Layer: Promtail reading the system logs, pushing them to a Loki log aggregation instance, and rendering them inside Grafana for hunting and rule development.

This gives you a real-time feedback loop. Every time you trigger an exploit against your target, you can immediately pivot to Grafana and examine the forensic footprint left behind.

Step 1: Installing and Configuring Sysmon for Linux

First, install Sysmon for Linux on your Ubuntu target host. Microsoft maintains official packages in their Linux software repository.

Run the following commands to add the repository and install the binary:

wget -q https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
sudo apt-get update
sudo apt-get install -y sysmonforlinux

Sysmon requires an XML configuration file to define what events it should capture. Create a lean configuration file named sysmon-config.xml that captures process execution (Event ID 1) and raw network connections (Event ID 3):

<Sysmon schemaversion="4.81">
  <EventFiltering>
    <RuleGroup name="process_creation" groupRelation="or">
      <ProcessCreate onmatch="include">
        <Rule name="AllProcessCreates" groupRelation="or">
          <Image condition="begin with">/</Image>
        </Rule>
      </ProcessCreate>
    </RuleGroup>
    <RuleGroup name="network_connect" groupRelation="or">
      <NetworkConnect onmatch="include">
        <Rule name="AllNetworkConnects" groupRelation="or">
          <DestinationPort condition="is">3000</DestinationPort>
          <DestinationPort condition="is">4444</DestinationPort>
        </Rule>
      </NetworkConnect>
    </RuleGroup>
  </EventFiltering>
</Sysmon>

Apply this configuration and start the Sysmon service:

sudo sysmon -i sysmon-config.xml

Verify that Sysmon is active and writing to /var/log/syslog:

sudo tail -f /var/log/syslog | grep -i sysmon

Step 2: Deploying the Ingestion Pipeline (Loki & Grafana)

Instead of setting up a heavy Elastic cluster that hogs 8GB of memory just to idle, use Grafana Loki and Promtail. They run inside Docker and consume less than 300MB of RAM.

Create a directory named logging-stack and add the following docker-compose.yml:

version: '3.8'

services:
  loki:
    image: grafana/loki:2.9.2
    ports:
      - "3100:3100"
    command: -config.file=/etc/loki/local-config.yaml
    restart: unless-stopped

  promtail:
    image: grafana/promtail:2.9.2
    volumes:
      - /var/log:/var/log:ro
      - ./promtail-config.yml:/etc/promtail/config.yml:ro
    command: -config.file=/etc/promtail/config.yml
    restart: unless-stopped

  grafana:
    image: grafana/grafana:10.2.0
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=LabPassword123!
    restart: unless-stopped

Next, create the promtail-config.yml file in the same directory to pull system logs containing Sysmon telemetry:

server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /tmp/positions.yaml

clients:
  - url: http://loki:3100/loki/api/v1/push

scrape_configs:
  - job_name: sysmon
    static_configs:
      - targets:
          - localhost
        labels:
          job: sysmon
          __path__: /var/log/syslog

Launch the logging stack:

docker compose up -d

Navigate to http://<YOUR-VM-IP>:3000, log into Grafana using admin / LabPassword123!, go to Connections > Data Sources, select Loki, and set the HTTP URL to http://loki:3100. Click Save & test.

Step 3: Spinning Up the Vulnerable Service

Now deploy the vulnerable target application. We’ll use OWASP Juice Shop, but we will also introduce an intentionally insecure administrative script on the host to simulate Remote Code Execution (RCE).

Run Juice Shop in Docker:

docker run -d --name target-juiceshop -p 8080:3000 bkimminich/juice-shop

To create a realistic command injection vector on the host system itself, create a simple Python HTTP server under /opt/vulnerable-app/app.py:

from flask import Flask, request
import os

app = Flask(__name__)

@app.route('/ping')
def ping():
    host = request.args.get('host', '127.0.0.1')
    # Vulnerable to command injection
    cmd = f"ping -c 1 {host}"
    return os.popen(cmd).read()

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

Install Flask and start the app in the background:

pip3 install flask
python3 /opt/vulnerable-app/app.py &

Step 4: Executing the Attack and Analyzing Telemetry

With the monitoring stack active, launch a command injection payload against the vulnerable Flask application to spawn a reverse shell or read sensitive files.

From a local machine (or another terminal window), run:

curl "http://<YOUR-VM-IP>:5000/ping?host=127.0.0.1;cat+/etc/passwd"

Next, attempt to spawn a shell by delivering a secondary execution string:

curl "http://<YOUR-VM-IP>:5000/ping?host=127.0.0.1;id"

Now, switch to your Grafana instance at http://<YOUR-VM-IP>:3000. Navigate to Explore, select the Loki data source, and enter the following LogQL query:

{job="sysmon"} |= "Sysmon" |= "ProcessCreate"

Examine the returned events. Look closely at the field key-value pairs inside the Sysmon event payload. You will see a clear execution chain:

  1. Image: /usr/bin/ping spawned by ParentImage: /usr/bin/python3.
  2. Immediately following, Image: /usr/bin/id (or /bin/cat) spawned by ParentImage: /usr/bin/python3.

This is the exact operational pattern of an RCE exploit: a web daemon binary (python3, node, nginx, or java) invoking system utilities (/bin/sh, /usr/bin/id, /usr/bin/whoami) that it has no legitimate reason to execute.

Step 5: Engineering the Detection Rule

Running an exploit and looking at a log isn’t enough; you must complete the engineering loop by writing an actionable detection.

In a modern production pipeline, you’d translate this observation into a Sigma rule or a log analytics alert. In Loki, we express this via LogQL to detect anomalous child processes spawned by web engines.

Query string for process execution anomalies from web runtimes:

{job="sysmon"} |= "ProcessCreate" |~ "ParentImage.*(python|node|nginx|apache|java)" |~ "Image.*(sh|bash|whoami|id|cat|nc|curl|wget)"

Test this query in Grafana. It will cleanly filter out benign system noise and isolate the exact minute your curl payload compromised the Flask server.

Building Real Competency

A lab like this costs zero dollars to run, requires less than 2GB of total system RAM, and forces you to work with real logging drivers, structured schemas, eBPF telemetry, and query languages.

Instead of adding another root-flag trophy to your resume, you now have a repeatable environment where you can pull a red-team script off GitHub, execute it, observe the exact telemetry generated by the operating system kernel, and build rules that defend against it. That is the actual work of security engineering.

Want a second set of eyes on your security posture?

Let's talk about where your real exposure is.

Book an advisory call