Skip to content

Latest commit

 

History

8 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

Detection Engineering

A catalog of production-style detections for Microsoft Sentinel and Microsoft 365 Defender, each documented, tuned, and mapped to MITRE ATT&CK.

Platform Language Framework Status

Overview

This repository is where I design, document, and tune analytic rules for cloud identity and endpoint telemetry. Every detection here started as a question (how would I see this attack in the logs?) and ended as a query I have run against real sign-in and audit data in my lab.

The goal is not a pile of queries. It is a small set of detections that each carry the context a SOC needs to act: what the threat is, why the logic catches it, what will make it misfire, and how to validate that it works. That is the difference between a query and a detection.

What is inside

Each detection lives in its own folder and follows the same documentation standard, so any reviewer can open any rule and immediately understand it.

detection-engineering/
  detections/
    T1110.003-password-spray/
      detection.kql          # the analytic rule
      metadata.yml           # ATT&CK mapping, data source, severity
      README.md              # threat context, logic walkthrough, FP notes
      validation.md          # how to safely reproduce and confirm a hit
    T1078-suspicious-signin/
    T1098-mailbox-rule-abuse/
  docs/
    detection-standard.md    # the template every rule follows
    data-sources.md          # tables, connectors, and retention notes

Detection catalog

Detection ATT&CK Technique Data Source Severity Status
Password spray from single source T1110.003 SigninLogs High Stable
Brute force against single account T1110.001 SigninLogs Medium Stable
Sign-in from impossible travel T1078 SigninLogs Medium In tuning
Suspicious inbox forwarding rule T1098 OfficeActivity High In tuning

How every detection is documented

A query without context creates alert fatigue. Each rule in this repo ships with four things:

  1. Threat context. What the adversary is doing and why it matters.
  2. Logic walkthrough. A plain-language explanation of each clause, so the rule is maintainable by someone who did not write it.
  3. False positive notes. The legitimate behavior that looks similar, and how the logic accounts for it.
  4. Validation steps. A safe way to reproduce the activity and confirm the detection fires.

That standard lives in docs/detection-standard.md.

Featured detection: password spray (T1110.003)

A password spray is the inverse of a brute force. Instead of many guesses against one account (which triggers lockout), the adversary tries one or two common passwords across many accounts to stay under per-account thresholds. The signal is not volume against a user. It is breadth: one source touching many distinct accounts in a short window.

// T1110.003 - Password Spray Detection
// Surfaces a single source failing authentication across many distinct
// accounts inside a short window, the signature of a low-and-slow spray.

let lookback = 1h;
let sprayWindow = 30m;
let accountThreshold = 10;     // distinct accounts targeted from one source
SigninLogs
| where TimeGenerated > ago(lookback)
| where ResultType in (
    "50126",   // invalid username or password
    "50053",   // account locked from repeated failures
    "50055"    // expired password presented
  )
| summarize
    FailedAttempts   = count(),
    TargetedAccounts = dcount(UserPrincipalName),
    AccountList      = make_set(UserPrincipalName, 100),
    ResultCodes      = make_set(ResultType)
    by IPAddress, bin(TimeGenerated, sprayWindow)
| where TargetedAccounts >= accountThreshold
| project TimeGenerated, IPAddress, TargetedAccounts, FailedAttempts, AccountList, ResultCodes
| order by TargetedAccounts desc

Why it works. Aggregating by source IP and a time bucket, then filtering on the count of distinct accounts, isolates the spray pattern. A normal user fat-fingering a password fails against one account, not fifteen.

False positives to expect. A shared corporate NAT egress, a misconfigured application replaying stale credentials, or a security scanner can all light this up. The fix is environment-specific: maintain an allowlist of known egress IPs, or raise accountThreshold to match your tenant's baseline. The full tuning notes live in the detection folder.

Validation. Reproduce safely in a lab tenant by attempting failed logins against several test accounts from one host, then confirm the rule returns that source. Never run this against production identities you do not own.

Tooling and data sources

  • SIEM: Microsoft Sentinel (Log Analytics workspace)
  • Identity telemetry: Entra ID sign-in and audit logs (SigninLogs, AuditLogs)
  • Productivity telemetry: OfficeActivity
  • Query language: KQL
  • Framework: MITRE ATT&CK for technique mapping and coverage tracking

Connector setup, table schemas, and retention assumptions are documented in docs/data-sources.md.

Roadmap

  • Build out OAuth consent-grant abuse detection (T1528)
  • Add coverage tracking: an ATT&CK navigator layer showing detected vs. gaps
  • Pair each detection with an Atomic Red Team test for repeatable validation
  • Port stable rules into the detection-as-code pipeline

A note on sanitization

Every query here uses placeholder thresholds and lab-only data. No tenant identifiers, account names, or customer data appear in this repository. Replace accountThreshold and the egress allowlist with values baselined to your own environment before deploying.

About

Built and maintained by Edward Griggs, a Security+ certified systems administrator moving into detection engineering. I run identity and endpoint security for a federal contractor by day and develop detections in a self-built Sentinel and Wazuh lab. SC-200 in progress.

LinkedIn · GitHub

About

A catalog of documented, tuned, ATT&CK-mapped KQL detections for Microsoft Sentinel and Defender.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors