Custom SIEM + Sentinel BAS
A detection-and-response platform built from scratch in Python, paired with Sentinel BAS, a breach-and-attack-simulation engine that runs Atomic Red Team techniques against the live lab and checks which detections actually fire.
- Role
- Design, engineering and validation
- Year
- 2026
- Status
- Public, MIT license
- Detection rules
- 35
- Measured coverage, 7 of 10 techniques
- 70%
- Attack-chain correlation window
- 60 min
- Built-in threat hunts
- 8
Overview
Problem
A detection rule that looks correct in review can still be unable to fire: a parser can drop the field it depends on, or the telemetry can be polluted. Without running real attack techniques against the pipeline, detection coverage is an assumption.
What I built
Mini SIEM, a detection-and-response platform written from scratch in Python, with multi-source ingestion, 35 detection rules, a Sigma engine, attack-chain correlation, case management, threat hunting and analyst-approved SOAR.
Alongside it, Sentinel BAS drives Atomic Red Team techniques against the live lab and classifies each one as Detected, Delayed or Missed.
Why it matters
The first validation run exposed defects that rule review had missed. The Kerberoasting rule was structurally unable to fire because TicketEncryptionType was never extracted, and the log forwarder was polluting telemetry with its own noise.
Architecture
Telemetry flows through one pipeline, from collection to response, and Sentinel BAS closes the loop by testing it with real techniques.
- CollectWindows Event Log, Sysmon, Linux syslog, remote forwarder
- StoreSQLite with parameterized queries
- Detect35 rules, Sigma engine, IOC watchlist, auto ATT&CK tags
- Correlate3+ rule types, same user or IP, 60 min
- RespondCases and SOAR with analyst approval
- ValidateSentinel BAS replays Atomic Red Team
Ingestion
Windows Security and System logs, Sysmon (process create, process access, injection, DNS query) and Linux syslog (SSH, sudo, su, useradd/usermod). Remote Windows hosts ship events through a forwarder agent built on Get-WinEvent.
Investigation
Incidents become numbered cases with evidence, assignment and resolution tracking. Analysts get a threat-hunting query language with 8 built-in saved hunts, a MITRE ATT&CK heatmap, timelines, risk context and AI-assisted incident summaries.
Response
SOAR playbooks queue response actions behind analyst approval gates, so nothing destructive runs automatically.
Deployment
A standalone Windows executable (PyInstaller + waitress), a hosted Linux mode (gunicorn), and a public demo mode that disables the ingest endpoint entirely.
Known limits
SQLite isn't built for high-volume concurrent ingestion, it's a single node, it serves HTTP rather than HTTPS, and the Sigma engine covers common patterns rather than the full specification. These are documented in the repository.
Stack
Detection
Thirty-five rules across Windows, Sysmon, Linux and behavioral analytics. Every alert is tagged with MITRE ATT&CK automatically.
| Category | Rules | Examples |
|---|---|---|
| Windows core | 11 | Brute force, password spraying, audit log cleared, new service, Kerberoasting |
| Advanced Windows / Sysmon | 7 | Office spawning a shell, AMSI bypass, LSASS access, CreateRemoteThread injection, DNS tunneling |
| Discovery, lateral movement, persistence | 8 | LOLBin abuse, Run key persistence, remote service execution, shadow copy deletion |
| Linux | 5 | SSH brute force, suspicious sudo, new user, added to a privileged group |
| Behavioral | 2 | Unusual login hour, new source IP |
| Platform security | 1 | Brute force against the SIEM's own login |
| IOC watchlist | 1 | Matches events against known indicators |
A Sigma rule from the repository
The Sigma engine loads YAML rules with common single and multi-selection AND/OR conditions. This one catches well-known credential-dumping tools.
title: Credential Dumping Tool Execution
status: stable
logsource:
category: process_creation
detection:
selection:
EventID: 4688
CommandLine:
- '*mimikatz*'
- '*sekurlsa*'
- '*lsadump*'
condition: selection
level: critical
tags:
- attack.credential_access
- attack.t1003
Attack-chain correlation
When three or more distinct rule types fire for the same user or source IP within 60 minutes, the alerts are clustered into a single incident automatically, so an analyst sees one attack chain instead of a dozen disconnected alerts.
Validation
Sentinel BAS turns “these rules should work” into a measured coverage report.
Method
- ExecuteRun an Atomic Red Team technique on the lab host
- CollectGather the alerts the SIEM raised
- MatchBy ATT&CK technique, host and timing
- ClassifyDetected within 60 s, delayed within 5 min, otherwise missed
Technique matching is hierarchy-aware: a test for T1003 correctly credits an alert tagged T1003.001.
Results by technique
No technique was delayed or left pending.
| Technique | Atomic test | Result | Latency |
|---|---|---|---|
T1003.001 LSASS memory | Dump LSASS memory | Detected | 0 s |
T1059.001 PowerShell | Encoded PowerShell command | Detected | 0 s |
T1136.001 Local account | Create a new local user | Detected | 0 s |
T1490 Inhibit system recovery | Delete volume shadow copies | Detected | 0 s |
T1547.001 Registry Run keys | Registry Run key persistence | Detected | 0 s |
T1543.003 Windows service | Install a new service | Detected | 4 s |
T1082 System information discovery | Discovery command burst | Detected | 21 s |
T1558.003 Kerberoasting | Request SPN tickets | Missed | No alert |
T1070.001 Clear Windows event logs | Clear the Security event log | Missed | No alert |
T1053.005 Scheduled task | Create a scheduled task | Missed | No alert |
What the misses revealed
A rule that could never fire
The Kerberoasting rule depended on
TicketEncryptionType, which the pipeline never extracted, so the rule was structurally unable to fire. Rule review hadn't caught it.Polluted telemetry
The remote forwarder was generating its own noise inside the telemetry it shipped.
Security
A SIEM holds sensitive telemetry, so the platform itself was hardened and audited.
Stored XSS found and fixed
A dedicated XSS audit found a real stored XSS: Sigma rule titles were rendered unescaped. Fixed, with Jinja2 autoescaping throughout.
Sessions and secrets
Secrets come from the environment, passwords are hashed and sessions are server-side. Cookies are HttpOnly, SameSite=Lax, Secure when enabled, with an 8-hour lifetime.
Access control
Role-based access for Viewer, Analyst and Admin, plus a login lockout after 5 failures in 15 minutes.
Security headers
CSP, X-Frame-Options, nosniff, Referrer-Policy, Permissions-Policy and HSTS on every response.
Injection defenses
Parameterized SQL and enumerated input validation.
Dependency scanning
Flask 3.0.3 to 3.1.3 (PYSEC-2026-2151) and requests 2.32.3 to 2.32.4 / 2.33.0 (PYSEC-2026-1872, PYSEC-2026-2275).
Documented trade-off: someone who knows a valid username could deliberately trigger the lockout.
Screenshots
Select a screenshot to view it full size, then swipe or use the arrow keys to move between them.
