Detection rules › Kusto
StealthTalk - Password brute force
Identifies a brute-force authentication attempt against a single StealthTalk user account. The StealthTalk anti-brute-force subsystem emits a MultiFailLogin event when consecutive failed attempts trigger an automatic account lockout. This rule fires when the reported number of consecutive failures is 9 or more, distinguishing a credential-guessing attack from an isolated user error. The lockout duration (LoginBlockingSeconds) is surfaced as a custom detail so the SOC analyst can prioritise by attack persistence.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Credential Access | T1110 Brute Force |
Rule body kusto
id: b8e5f3a2-9c4d-4d1f-8a7b-3c2d1e0f9a8b
name: StealthTalk - Password brute force
description: |
Identifies a brute-force authentication attempt against a single StealthTalk user account. The StealthTalk anti-brute-force subsystem emits a `MultiFailLogin` event when consecutive failed attempts trigger an automatic account lockout. This rule fires when the reported number of consecutive failures is 9 or more, distinguishing a credential-guessing attack from an isolated user error. The lockout duration (`LoginBlockingSeconds`) is surfaced as a custom detail so the SOC analyst can prioritise by attack persistence.
severity: High
requiredDataConnectors:
- connectorId: StealthTalkAnomalousAuth
dataTypes:
- StealthTalkAnomalousAuth_CL
queryFrequency: 15m
queryPeriod: 5h
triggerOperator: gt
triggerThreshold: 0
status: Available
tactics:
- CredentialAccess
- InitialAccess
relevantTechniques:
- T1110
query: |
let LookbackPeriod = 5h;
let MinFailedAttempts = 9;
StealthTalkAnomalousAuth_CL
| where TimeGenerated >= ago(LookbackPeriod)
| where EventType == "MultiFailLogin"
| where PassedAttempts >= MinFailedAttempts
| extend
BlockingMinutes = LoginBlockingSeconds / 60,
AlertName = "PasswordBruteForce",
AlertDetails = strcat(
"User ", UserId,
" had ", PassedAttempts, " consecutive failed login attempts",
" on device ", DeviceId, ".",
" Account blocked for ", LoginBlockingSeconds, " seconds",
" (", LoginBlockingSeconds / 60, " min)."
)
| project
TimeGenerated, UserId, DeviceId,
PassedAttempts, LoginBlockingSeconds, BlockingMinutes,
AppVersion, RawEventId, AlertName, AlertDetails
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: UserId
- entityType: Host
fieldMappings:
- identifier: HostName
columnName: DeviceId
customDetails:
PassedAttempts: PassedAttempts
BlockingMinutes: BlockingMinutes
LoginBlockingSeconds: LoginBlockingSeconds
AppVersion: AppVersion
EventReference: RawEventId
alertDetailsOverride:
alertDisplayNameFormat: 'StealthTalk: Password Brute Force - {{UserId}} ({{PassedAttempts}} failed attempts)'
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 = 5h;
let MinFailedAttempts = 9;
Stage 1: source
StealthTalkAnomalousAuth_CL
Stage 2: where
| where TimeGenerated >= ago(LookbackPeriod)
Stage 3: where
| where EventType == "MultiFailLogin"
Stage 4: where
| where PassedAttempts >= MinFailedAttempts
Stage 5: extend
| extend
BlockingMinutes = LoginBlockingSeconds / 60,
AlertName = "PasswordBruteForce",
AlertDetails = strcat(
"User ", UserId,
" had ", PassedAttempts, " consecutive failed login attempts",
" on device ", DeviceId, ".",
" Account blocked for ", LoginBlockingSeconds, " seconds",
" (", LoginBlockingSeconds / 60, " min)."
)
Stage 6: project
| project
TimeGenerated, UserId, DeviceId,
PassedAttempts, LoginBlockingSeconds, BlockingMinutes,
AppVersion, RawEventId, AlertName, AlertDetails
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.
| Field | Kind | Values |
|---|---|---|
EventType | eq |
|
PassedAttempts | ge |
|
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.
| Field | Source |
|---|---|
AlertDetails | project |
AlertName | project |
AppVersion | project |
BlockingMinutes | project |
DeviceId | project |
LoginBlockingSeconds | project |
PassedAttempts | project |
RawEventId | project |
TimeGenerated | project |
UserId | project |