Detection rules › Kusto

StealthTalk - Multi new devices registration

Status
available
Severity
medium
Time window
1d
Group by
UserId
Source
github.com/Azure/Azure-Sentinel

Identifies a single StealthTalk user registering two or more previously-unseen devices within a 24-hour window. Sudden registration of multiple new devices is a strong indicator of account takeover (an attacker enrolling their own device after credential theft) or device-farm abuse. The rule fires when a user produces two or more distinct NewDeviceId values within the lookback window, regardless of operating system. Look at the OSList custom detail to spot cross-platform patterns (e.g. an iOS-only user suddenly enrolling an Android device).

MITRE ATT&CK coverage

Rule body

id: f9d4c2a8-1b6e-4a3f-9c7d-8e2b1a3c5d7e
name: StealthTalk - Multi new devices registration
description: |
  Identifies a single StealthTalk user registering two or more previously-unseen devices within
  a 24-hour window. Sudden registration of multiple new devices is a strong indicator of
  account takeover (an attacker enrolling their own device after credential theft) or
  device-farm abuse.

  The rule fires when a user produces two or more distinct NewDeviceId values within the
  lookback window, regardless of operating system. Look at the OSList custom detail to spot
  cross-platform patterns (e.g. an iOS-only user suddenly enrolling an Android device).
severity: Medium
requiredDataConnectors:
  - connectorId: StealthTalkAnomalousAuth
    dataTypes:
      - StealthTalkAnomalousAuth_CL
queryFrequency: 30m
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
status: Available
tactics:
  - Persistence
  - InitialAccess
  - DefenseEvasion
relevantTechniques:
  - T1078
  - T1098
query: |
  let LookbackPeriod = 24h;
  let MinNewDevices  = 2;
  StealthTalkAnomalousAuth_CL
  | where TimeGenerated >= ago(LookbackPeriod)
  | where EventType == "NewDeviceLogin"
  | summarize
      NewDeviceCount  = dcount(NewDeviceId),
      NewDevices      = make_set(NewDeviceId),
      NewDeviceOSList = make_set(NewDeviceOS),
      FirstSeen       = min(TimeGenerated),
      LastSeen        = max(TimeGenerated),
      AppVersions     = make_set(AppVersion)
    by UserId
  | where NewDeviceCount >= MinNewDevices
  | extend
      AlertName    = "MultiNewDevicesRegistration",
      AlertDetails = strcat(
          "User ", UserId,
          " registered ", NewDeviceCount, " new devices within 24 hours.",
          " Device IDs: ", tostring(NewDevices), ".",
          " Operating systems: ", tostring(NewDeviceOSList), "."
      )
  | project
      TimeGenerated = LastSeen,
      UserId, NewDeviceCount, NewDevices, NewDeviceOSList,
      FirstSeen, LastSeen, AppVersions, AlertName, AlertDetails
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: Name
        columnName: UserId
customDetails:
  NewDeviceCount: NewDeviceCount
  NewDevices: NewDevices
  NewDeviceOSList: NewDeviceOSList
  FirstSeen: FirstSeen
  LastSeen: LastSeen
alertDetailsOverride:
  alertDisplayNameFormat: 'StealthTalk: Multi New Devices - {{UserId}} ({{NewDeviceCount}} new devices)'
  alertDescriptionFormat: '{{AlertDetails}}'
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: true
    reopenClosedIncident: false
    lookbackDuration: 5h
    matchingMethod: Selected
    groupByEntities:
      - Account
suppressionEnabled: false
suppressionDuration: 5h
version: 1.0.0
kind: Scheduled

Stages and Predicates

Parameters

let LookbackPeriod = 24h;
let MinNewDevices = 2;

Stage 1: source

StealthTalkAnomalousAuth_CL

Stage 2: where

| where TimeGenerated >= ago(LookbackPeriod)

Stage 3: where

| where EventType == "NewDeviceLogin"

Stage 4: summarize

| summarize
    NewDeviceCount  = dcount(NewDeviceId),
    NewDevices      = make_set(NewDeviceId),
    NewDeviceOSList = make_set(NewDeviceOS),
    FirstSeen       = min(TimeGenerated),
    LastSeen        = max(TimeGenerated),
    AppVersions     = make_set(AppVersion)
  by UserId

Stage 5: where

| where NewDeviceCount >= MinNewDevices

Stage 6: extend

| extend
    AlertName    = "MultiNewDevicesRegistration",
    AlertDetails = strcat(
        "User ", UserId,
        " registered ", NewDeviceCount, " new devices within 24 hours.",
        " Device IDs: ", tostring(NewDevices), ".",
        " Operating systems: ", tostring(NewDeviceOSList), "."
    )

Stage 7: project

| project
    TimeGenerated = LastSeen,
    UserId, NewDeviceCount, NewDevices, NewDeviceOSList,
    FirstSeen, LastSeen, AppVersions, AlertName, AlertDetails

Indicators

These rows show field, operator, and value matches.

Output fields

These fields are emitted when the rule matches.

FieldSource
AlertDetailsproject
AlertNameproject
AppVersionsproject
FirstSeenproject
LastSeenproject
NewDeviceCountproject
NewDeviceOSListproject
NewDevicesproject
TimeGeneratedproject
UserIdproject