DEV Community

Cover image for Hands-On SIEM Lab: Custom Rules for Threat Detection with ELK Stack
Mounica
Mounica

Posted on

Hands-On SIEM Lab: Custom Rules for Threat Detection with ELK Stack

Author: Mounica S Goodala

Date: 06 August 2026

🎯 Introduction

Security Operations Centers rely on SIEM systems to correlate logs and detect malicious activity. This tutorial walks through building three custom correlation rules in the ELK Stack (Elasticsearch + Kibana) to detect:

  • Credential Stuffing (T1110.004) — Attackers using stolen credentials to target multiple accounts.
  • DNS Tunneling (T1071.004) — Attackers abusing DNS to exfiltrate data.
  • PowerShell Exploitation (T1059.001) — Attackers abusing PowerShell to execute malicious scripts.

The goal is to build a complete detection pipeline—from log injection to alert generation—using open-source tools.


🛠️ 1. Lab Environment Setup

The ELK Stack was deployed locally using Elastic's official one-liner, which spins up two Docker containers:

  • Elasticsearch on port 9200 — the search and indexing engine.
  • Kibana on port 5601 — the visual interface for rule creation and alert monitoring.
curl -fsSL <https://elastic.co/start-local> | sh
Enter fullscreen mode Exit fullscreen mode

Authentication is enabled by default. The credentials can be retrieved from the generated .env file:

cat elastic-start-local/.env | grep ELASTIC_PASSWORD
Enter fullscreen mode Exit fullscreen mode
  • Username: elastic
  • Password: (from .env)

This setup provides a lightweight, reproducible SIEM lab suitable for detection engineering.


📁 2. Data Views in Kibana

Before writing any rules, Data Views (index patterns) were created in Kibana to make indices searchable. Navigate to Stack Management → Data Views and create the following:

  • test-logs-all → pattern logs-test*
  • logs-dns → pattern logs-dns*
  • logs-powershell → pattern logs-powershell*

All three use @timestamp as the timestamp field.

This step ensures that logs injected into Elasticsearch are discoverable in Kibana's Discover interface.

Test-logs Data View created in Kibana


💉 3. Attack Telemetry Injection

To validate the rules, realistic attack telemetry was generated and injected into Elasticsearch using two methods:

  • Python scripts (with the requests library) for structured, repeatable injections.
  • CURL commands for quick, ad-hoc injections directly from the terminal.

All scripts were developed in Visual Studio Code and executed via the integrated terminal.

Here's a sample REST API call used for injection:

curl -X POST "<http://localhost:9200/logs-test/_doc>" \
     -u elastic:YOUR_PASSWORD \
     -d '{"@timestamp":"...", "source.ip":"203.0.113.45", ...}'
Enter fullscreen mode Exit fullscreen mode

This approach provides full control over the telemetry data, enabling precise validation of detection logic.


🎯 4. Credential Stuffing (T1110.004)

What it is: Credential stuffing occurs when attackers use username/password pairs from data breaches and "spray" them across multiple accounts. The key signature is a single source IP targeting many distinct user accounts, typically with only 1–2 attempts per account.

How it was tested: A Python script injected 15 failed login attempts to 15 distinct users (alice, bob, ... oscar) from a single IP (203.0.113.45). Each injection received a "result":"created" response.

The detection logic: An ES|QL rule aggregates failed authentication attempts by source IP and counts the distinct target usernames using count_distinct(). If an IP targets more than 10 unique users, an alert is generated.

from logs-test*
| where event.category == "authentication" and event.type == "failure"
| eval attacker_ip = source.ip
| stats
    targeted_accounts = count_distinct(user.name),
    total_attempts = count(*),
    example_users = values(user.name)
  by attacker_ip
| where targeted_accounts > 10
Enter fullscreen mode Exit fullscreen mode

Result: The rule triggered with targeted_accounts: 15 from IP 203.0.113.45, confirming successful detection of credential stuffing behavior.

Detailed view of Credential Stuffing detected in Kibana


🌐 5. DNS Tunneling (T1071.004)

What it is: DNS tunneling exploits the DNS protocol—which is rarely blocked by firewalls—to exfiltrate data or establish C2 channels. Attackers generate a high volume of queries to a single domain with abnormally long subdomains containing encoded payload data.

How it was tested: A Bash loop injected 20 DNS queries, each with a random 120-character subdomain pointing to malicious-tunnel.com. Each CURL request returned a successful "result":"created" response.

The detection logic: An ES|QL rule calculates the character length of the queried domain and aggregates the total count per source IP. Queries exceeding 100 characters are flagged, and any IP generating more than 10 such queries triggers an alert.

from logs-dns*
| where dns.question.name is not null
| eval attacker_ip = source.ip
| eval query_length = length(dns.question.name)
| where query_length > 100
| stats
    total_queries = count(*),
    sample_domains = values(dns.question.name)
  by attacker_ip
| where total_queries > 10
Enter fullscreen mode Exit fullscreen mode

Result: The rule flagged total_queries: 20 from IP 203.0.113.45, validating the detection of DNS tunneling activity.

Detailed view of DNS Tunneling detected in Kibana


💻 6. PowerShell Exploitation (T1059.001)

What it is: PowerShell is a legitimate Windows administration tool frequently abused by attackers to execute malicious scripts, download payloads, and evade detection. Common obfuscation techniques include -EncodedCommand, its shorthand -e, and WebClient.DownloadFile.

How it was tested: Three separate CURL commands injected PowerShell process events with suspicious argument patterns:

  • One with EncodedCommand
  • One with shorthand e
  • One invoking WebClient.DownloadFile

Each injection returned "result":"created".

The detection logic: An EQL rule inspects the command-line arguments of newly started powershell.exe processes, specifically looking for strings indicative of abuse.

process where event.type == "start"
and process.name : "powershell.exe"
and (
    process.command_line : "*EncodedCommand*" or
    process.command_line : "*-e *" or
    process.command_line : "*-ec *" or
    process.command_line : "*WebClient*" or
    process.command_line : "*DownloadFile*" or
    process.command_line : "*Reflection.Assembly*"
)
Enter fullscreen mode Exit fullscreen mode

Result: Three separate high-severity alerts were generated, confirming the rule's ability to catch varied obfuscation techniques.

Detailed view of Suspicious Powershell Arguments detected in Kibana


🧠 7. Key Learnings

Choosing the Right Rule Language:

  • ES|QL excels at statistical aggregation across large datasets—counting distinct users, calculating query lengths, and grouping events.
  • EQL is superior for parsing discrete process events and matching specific command-line strings with sequence awareness.

Threshold Tuning:

  • targeted_accounts > 10 proved effective for credential stuffing.
  • Thresholds that are too low generate false positives; thresholds too high risk missing attacks.
  • Production environments require baselining to determine optimal thresholds.

Layered Detection:

  • Combining authentication logs, DNS queries, and PowerShell telemetry provides comprehensive visibility.
  • No single rule is sufficient; a layered approach transforms raw logs into actionable intelligence.

📊 8. Results

After executing all three rules via "Run now", the Alerts dashboard displayed:

  • 3 alerts for Credential Stuffing — each confirming 15 distinct users targeted from a single IP.
  • 1 alert for DNS Tunneling — flagging 20 queries with domains exceeding 100 characters.
  • 3 alerts for PowerShell Exploitation — detecting encoded commands and WebClient invocations.

Total: 7 alerts across all three techniques, validating the detection logic.

Detailed view of all 3 MITRE ATT&CK techniques detected in Kibana


🛠️ 9. Tools Summary

  • Docker provided a containerized, reproducible environment.
  • Elasticsearch & Kibana (v9.5.0) served as the core SIEM platform.
  • Visual Studio Code was used for developing Python injection scripts.
  • Python + requests injected structured attack telemetry.
  • CURL enabled quick, ad-hoc log injection.

🚀 10. Explore Further

  • Expand detection coverage to additional MITRE ATT&CK techniques.
  • Integrate threat intelligence for alert enrichment.
  • Implement automated response playbooks.
  • Deploy Elastic Agents for real endpoint telemetry.

📚 11. References

  • MITRE ATT&CK T1110.004
  • MITRE ATT&CK T1071.004
  • MITRE ATT&CK T1059.001
  • Elastic Security Docs
  • Elastic Docker Deployment

💬 Discussion

What MITRE ATT&CK techniques have you built detection rules for? Share your experiences below.

Top comments (0)