Detection rules › Kusto

CreepyDrive request URL sequence

Severity
high
Time window
1d
Group by
SourceHostName, SourceIP
Author
Thomas McElroy
Source
github.com/Azure/Azure-Sentinel

'CreepyDrive uses OneDrive for command and control, however, it makes regular requests to predicatable paths. This detecton will alert when over 20 sequences are observed in a single day.'

MITRE ATT&CK coverage

Rule body kusto

id: eda260eb-f4a1-4379-ad98-452604da9b3e
name: CreepyDrive request URL sequence
description: |
  'CreepyDrive uses OneDrive for command and control, however, it makes regular requests to predicatable paths.
  This detecton will alert when over 20 sequences are observed in a single day.'
severity: High
requiredDataConnectors:
  - connectorId: Zscaler
    dataTypes:
      - CommonSecurityLog
  - connectorId: Fortinet
    dataTypes:
      - CommonSecurityLog
  - connectorId: CheckPoint
    dataTypes:
      - CommonSecurityLog
  - connectorId: PaloAltoNetworks
    dataTypes:
      - CommonSecurityLog
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Exfiltration
  - CommandAndControl
relevantTechniques:
  - T1567.002
  - T1102.002
tags:
  - POLONIUM
query: |
  let eventsThreshold = 20;
  CommonSecurityLog
  | where isnotempty(RequestURL)
  | project TimeGenerated, RequestURL, RequestMethod, SourceIP, SourceHostName
  | evaluate sequence_detect(TimeGenerated, 5s, 8s, login=(RequestURL has "login.microsoftonline.com/consumers/oauth2/v2.0/token"), graph=(RequestURL has "graph.microsoft.com/v1.0/me/drive/"), SourceIP, SourceHostName)
  | summarize Events=count() by SourceIP, SourceHostName
  | where Events >= eventsThreshold
entityMappings:
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: SourceIP
  - entityType: Host
    fieldMappings:
      - identifier: HostName
        columnName: SourceHostName
version: 1.0.1
kind: Scheduled
metadata:
    source:
        kind: Community
    author:
        name: Thomas McElroy
    support:
        tier: Community
    categories:
        domains: [ "Security - Others" ]

Stages and Predicates

Parameters

let eventsThreshold = 20;

Stage 1: source

CommonSecurityLog

Stage 2: where

| where isnotempty(RequestURL)

Stage 3: project

| project TimeGenerated, RequestURL, RequestMethod, SourceIP, SourceHostName

Stage 4: evaluate

| evaluate sequence_detect(TimeGenerated, 5s, 8s, login=(RequestURL has "login.microsoftonline.com/consumers/oauth2/v2.0/token"), graph=(RequestURL has "graph.microsoft.com/v1.0/me/drive/"), SourceIP, SourceHostName)

Stage 5: summarize

| summarize Events=count() by SourceIP, SourceHostName
Threshold
ge 20

Stage 6: where

| where Events >= eventsThreshold

Indicators

Each row is a field, operator, and value that the rule matches. The corpus column counts how many other rules in the catalog look for the same combination: high numbers point to widely-used, community-vetted indicators. Blank or 1 shows that the indicator is specific to this rule.

FieldKindValues
Eventsge
  • 20 transforms: cased
RequestURLis_not_null
  • (no value, null check)

Output fields

Fields the rule emits when it matches. Chronicle authors list these in the outcome block; they appear on the detection and $risk_score drives alerting. Sentinel / Defender XDR rules build them up through project / summarize / extend stages. Sentinel maps these into alert fields via entityMappings and customDetails; Defender XDR custom detections surface them as alert fields directly.

FieldSource
Eventssummarize
SourceHostNamesummarize
SourceIPsummarize