A single actor resetting passwords for three or more accounts within one hour may indicate an adversary attempting to take over multiple accounts through credential compromise. SOC teams should proactively hunt for this behavior in Azure Sentinel to identify potential account takeovers before they escalate into broader breaches.
KQL Query
let timeframe = 1d;
let resetThreshold = 3;
let correlationWindow = 1h;
AuditLogs
| where TimeGenerated >= ago(timeframe)
| where OperationName in~ (
"Reset password (by admin)",
"Reset user password",
"Reset password"
)
| where Result =~ "success"
| extend ActorUpn = tostring(InitiatedBy.user.userPrincipalName)
| extend ActorApp = tostring(InitiatedBy.app.displayName)
| extend ActorIp = iff(
isnotempty(tostring(InitiatedBy.user.ipAddress)),
tostring(InitiatedBy.user.ipAddress),
tostring(InitiatedBy.app.ipAddress))
| extend Actor = iff(isnotempty(ActorUpn), ActorUpn, ActorApp)
| extend TargetUpn = tostring(TargetResources[0].userPrincipalName)
| where isnotempty(Actor) and isnotempty(TargetUpn) and Actor != TargetUpn
| summarize
ResetCount = dcount(TargetUpn),
TargetAccounts = make_set(TargetUpn, 20),
FirstReset = min(TimeGenerated),
LastReset = max(TimeGenerated),
ActorIp = take_any(ActorIp)
by Actor, TimeBucket = bin(TimeGenerated, correlationWindow)
| where ResetCount >= resetThreshold
| extend AccountName = iff(Actor has "@", tostring(split(Actor, "@")[0]), Actor)
| extend AccountUPNSuffix = iff(Actor has "@", tostring(split(Actor, "@")[1]), "")
| project
TimeBucket,
Actor,
AccountName,
AccountUPNSuffix,
ResetCount,
TargetAccounts,
FirstReset,
LastReset,
ActorIp
| sort by ResetCount desc
id: 0490ce45-3f01-48e2-a042-3ba0c3e559bc
name: Bulk admin-initiated password reset across multiple accounts
description: |
Identifies a single actor resetting passwords for three or more distinct accounts
within one hour. Bulk admin-initiated resets in rapid succession suggest active
account takeover before detection.
requiredDataConnectors:
- connectorId: AzureActiveDirectory
dataTypes:
- AuditLogs
tactics:
- CredentialAccess
- Persistence
relevantTechniques:
- T1098
- T1078.004
query: |
let timeframe = 1d;
let resetThreshold = 3;
let correlationWindow = 1h;
AuditLogs
| where TimeGenerated >= ago(timeframe)
| where OperationName in~ (
"Reset password (by admin)",
"Reset user password",
"Reset password"
)
| where Result =~ "success"
| extend ActorUpn = tostring(InitiatedBy.user.userPrincipalName)
| extend ActorApp = tostring(InitiatedBy.app.displayName)
| extend ActorIp = iff(
isnotempty(tostring(InitiatedBy.user.ipAddress)),
tostring(InitiatedBy.user.ipAddress),
tostring(InitiatedBy.app.ipAddress))
| extend Actor = iff(isnotempty(ActorUpn), ActorUpn, ActorApp)
| extend TargetUpn = tostring(TargetResources[0].userPrincipalName)
| where isnotempty(Actor) and isnotempty(TargetUpn) and Actor != TargetUpn
| summarize
ResetCount = dcount(TargetUpn),
TargetAccounts = make_set(TargetUpn, 20),
FirstReset = min(TimeGenerated),
LastReset = max(TimeGenerated),
ActorIp = take_any(ActorIp)
by Actor, TimeBucket = bin(TimeGenerated, correlationWindow)
| where ResetCount >= resetThreshold
| extend AccountName = iff(Actor has "@", tostring(split(Actor, "@")[0]), Actor)
| extend AccountUPNSuffix = iff(Actor has "@", tostring(split(Actor, "@")[1]), "")
| project
TimeBucket,
Actor,
AccountName,
AccountUPNSuffix,
ResetCount,
TargetAccounts,
FirstReset,
LastReset,
ActorIp
| sort by ResetCount desc
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: Actor
- identifier: Name
columnName: AccountName
- identifier: UPNSuffix
columnName: AccountUPNSuffix
- entityType: IP
fieldMappings:
- identifier: Address
columnName: ActorIp
version: 1.0.0
metadata:
source:
kind: Community
author:
name: descambiado
support:
tier: Community
categories:
domains: [ "Security - Threat Protection", "Identity" ]
| Sentinel Table | Notes |
|---|---|
AuditLogs | Ensure this data connector is enabled |
Scenario: Scheduled Password Expiry Job
Description: A system administrator runs a scheduled job to reset passwords for multiple user accounts as part of a routine password policy enforcement (e.g., using Microsoft Azure AD Password Protection or AWS IAM password policy).
Filter/Exclusion: Check for event_id or task_name indicating scheduled maintenance or password expiry tasks. Exclude events with source_system or job_name matching known password expiry tools.
Scenario: Multi-Factor Authentication (MFA) Enrollment
Description: An admin resets passwords for several accounts to enable MFA for a group of users (e.g., using Microsoft Intune or Okta).
Filter/Exclusion: Filter by action_type such as “MFA enrollment” or “MFA setup,” and exclude accounts where MFA is being configured for the first time.
Scenario: Bulk User Onboarding
Description: An admin provisions multiple new users at once (e.g., via Microsoft 365 Admin Center, AWS IAM User Creation, or Active Directory Import/Export).
Filter/Exclusion: Exclude events with user_role or account_type indicating new user creation, and filter by source_ip or tool_used matching provisioning tools.
Scenario: Password Reset for Compliance Audit
Description: An admin resets passwords for multiple accounts as part of a compliance audit (e.g., using Powershell scripts or LDAP bulk operations).
Filter/Exclusion: Filter by audit_flag or task_category indicating compliance or audit-related actions. Exclude events with user_role such as “Compliance Officer” or “Security Admin.”
Scenario: Help Desk Bulk Password Reset
Description: A help desk team resets passwords for multiple