Microsoft Sentinel Analytic Rules
cloudbrothers.infoAzure Sentinel RepoToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Multiple Password Reset by user

Back
Id0b9ae89d-8cad-461c-808f-0494f70ad5c4
RulenameMultiple Password Reset by user
DescriptionThis query will determine multiple password resets by user across multiple data sources.

Account manipulation including password reset may aid adversaries in maintaining access to credentials and certain permission levels within an environment.
SeverityLow
TacticsInitialAccess
CredentialAccess
TechniquesT1078
T1110
Required data connectorsAzureActiveDirectory
Office365
SecurityEvents
Syslog
WindowsForwardedEvents
WindowsSecurityEvents
KindScheduled
Query frequency1d
Query period1d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Detections/MultipleDataSources/MultiplePasswordresetsbyUser.yaml
Version2.1.7
Arm template0b9ae89d-8cad-461c-808f-0494f70ad5c4.json
Deploy To Azure
let selfServicePasswordReset = dynamic(["Self-service password reset flow activity progress", "Change password (self-service)", "Reset password (self-service)"]); 
//Self-service password reset flow activity progress is typically caused by a password policy which requires users to rotate passwords. This operation already implies the user has signed in successfully and therefore the password reset is non-malicious.
let PerUserThreshold = 5;
let TotalThreshold = 100;
let action = dynamic(["change", "changed", "reset"]);
let pWord = dynamic(["password", "credentials"]);
let PasswordResetMultiDataSource =
(union isfuzzy=true
(//Password reset events
//4723: An attempt was made to change an account's password
//4724: An attempt was made to reset an accounts password
SecurityEvent
| where EventID in ("4723","4724")
| project TimeGenerated, Computer, AccountType, Account, Type, TargetUserName),
(//Password reset events
//4723: An attempt was made to change an account's password
//4724: An attempt was made to reset an accounts password
WindowsEvent
| where EventID in ("4723","4724")
| extend SubjectUserSid = tostring(EventData.SubjectUserSid)
| extend TargetUserName = tostring(EventData.TargetUserName)
| extend Account = strcat(tostring(EventData.SubjectDomainName),"\\", tostring(EventData.SubjectUserName))
| extend AccountType=case(Account endswith "$" or SubjectUserSid in ("S-1-5-18", "S-1-5-19", "S-1-5-20"), "Machine", isempty(SubjectUserSid), "", "User")
| project TimeGenerated, Computer, AccountType, Account, Type, TargetUserName),
(//Azure Active Directory Password reset events
AuditLogs
| where OperationName has_any (pWord) and OperationName has_any (action) and Result =~ "success"
| where OperationName !in (selfServicePasswordReset)
| mv-apply TargetResource = TargetResources on 
  (
      where TargetResource.type =~ "User"
      | extend AccountType = tostring(TargetResource.type),
               Account = tostring(InitiatedBy.user.userPrincipalName),
               TargetUserName = tolower(tostring(TargetResource.userPrincipalName))
  )
| project TimeGenerated, AccountType, Account, TargetUserName, Computer = "", Type),
(//OfficeActive ActiveDirectory Password reset events
OfficeActivity
| where OfficeWorkload == "AzureActiveDirectory"
| where (ExtendedProperties has_any (pWord) or ModifiedProperties has_any (pWord)) and (ExtendedProperties has_any (action) or ModifiedProperties has_any (action))
| extend AccountType = UserType, Account = OfficeObjectId
| project TimeGenerated, AccountType, Account, Type, Computer = ""),
(// Unix syslog password reset events
Syslog
| where Facility in ("auth","authpriv")
| where SyslogMessage has_any (pWord) and SyslogMessage has_any (action)
| extend AccountType = iif(SyslogMessage contains "root", "Root", "Non-Root")
| where SyslogMessage matches regex ".*password changed for.*"
| parse SyslogMessage with * "password changed for" Account
| project TimeGenerated, AccountType, Account, Computer = HostName, Type)
);
let pwrmd = PasswordResetMultiDataSource
| project TimeGenerated, Computer, AccountType, Account, Type, TargetUserName;
(union isfuzzy=true
(pwrmd
| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), Computerlist = make_set(Computer, 25), AccountType = make_set(AccountType, 25), Computer = arg_max(Computer , TimeGenerated), TargetUserList = make_set(TargetUserName, 25), TargetUserName = arg_max(TargetUserName, TimeGenerated), Total=count() by Account, Type
| where Total > PerUserThreshold
| extend ResetPivot = "PerUserReset"),
(pwrmd
| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), ComputerList = make_set(Computer, 25), AccountList = make_set(Account, 25), AccountType = make_set(AccountType, 25), Computer = arg_max(Computer , TimeGenerated), TargetUserList = make_set(TargetUserName, 25), TargetUserName = arg_max(TargetUserName, TimeGenerated), Total=count() by Type
| where Total > TotalThreshold
| extend ResetPivot = "TotalUserReset")
)
| extend timestamp = StartTimeUtc, HostName = tostring(split(Computer, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(Computer, '.'), 1, -1), '.')), Name = tostring(split(Account, '@', 0)[0]), UPNSuffix = tostring(split(Account, '@', 1)[0]), TargetName = tostring(split(TargetUserName,'@',0)[0]), TargetUPNSuffix = tostring(split(TargetUserName,'@',1)[0])
entityMappings:
- entityType: Account
  fieldMappings:
  - identifier: FullName
    columnName: Account
  - identifier: Name
    columnName: Name
  - identifier: UPNSuffix
    columnName: UPNSuffix
- entityType: Host
  fieldMappings:
  - identifier: FullName
    columnName: Computer
  - identifier: HostName
    columnName: HostName
  - identifier: DnsDomain
    columnName: DnsDomain
- entityType: Account
  fieldMappings:
  - identifier: FullName
    columnName: TargetUserName
  - identifier: Name
    columnName: TargetName
  - identifier: UPNSuffix
    columnName: TargetUPNSuffix
queryFrequency: 1d
name: Multiple Password Reset by user
severity: Low
kind: Scheduled
tactics:
- InitialAccess
- CredentialAccess
metadata:
  author:
    name: Microsoft Security Research
  source:
    kind: Community
  categories:
    domains:
    - Security - Others
    - Identity
  support:
    tier: Community
triggerThreshold: 0
query: |
  let selfServicePasswordReset = dynamic(["Self-service password reset flow activity progress", "Change password (self-service)", "Reset password (self-service)"]); 
  //Self-service password reset flow activity progress is typically caused by a password policy which requires users to rotate passwords. This operation already implies the user has signed in successfully and therefore the password reset is non-malicious.
  let PerUserThreshold = 5;
  let TotalThreshold = 100;
  let action = dynamic(["change", "changed", "reset"]);
  let pWord = dynamic(["password", "credentials"]);
  let PasswordResetMultiDataSource =
  (union isfuzzy=true
  (//Password reset events
  //4723: An attempt was made to change an account's password
  //4724: An attempt was made to reset an accounts password
  SecurityEvent
  | where EventID in ("4723","4724")
  | project TimeGenerated, Computer, AccountType, Account, Type, TargetUserName),
  (//Password reset events
  //4723: An attempt was made to change an account's password
  //4724: An attempt was made to reset an accounts password
  WindowsEvent
  | where EventID in ("4723","4724")
  | extend SubjectUserSid = tostring(EventData.SubjectUserSid)
  | extend TargetUserName = tostring(EventData.TargetUserName)
  | extend Account = strcat(tostring(EventData.SubjectDomainName),"\\", tostring(EventData.SubjectUserName))
  | extend AccountType=case(Account endswith "$" or SubjectUserSid in ("S-1-5-18", "S-1-5-19", "S-1-5-20"), "Machine", isempty(SubjectUserSid), "", "User")
  | project TimeGenerated, Computer, AccountType, Account, Type, TargetUserName),
  (//Azure Active Directory Password reset events
  AuditLogs
  | where OperationName has_any (pWord) and OperationName has_any (action) and Result =~ "success"
  | where OperationName !in (selfServicePasswordReset)
  | mv-apply TargetResource = TargetResources on 
    (
        where TargetResource.type =~ "User"
        | extend AccountType = tostring(TargetResource.type),
                 Account = tostring(InitiatedBy.user.userPrincipalName),
                 TargetUserName = tolower(tostring(TargetResource.userPrincipalName))
    )
  | project TimeGenerated, AccountType, Account, TargetUserName, Computer = "", Type),
  (//OfficeActive ActiveDirectory Password reset events
  OfficeActivity
  | where OfficeWorkload == "AzureActiveDirectory"
  | where (ExtendedProperties has_any (pWord) or ModifiedProperties has_any (pWord)) and (ExtendedProperties has_any (action) or ModifiedProperties has_any (action))
  | extend AccountType = UserType, Account = OfficeObjectId
  | project TimeGenerated, AccountType, Account, Type, Computer = ""),
  (// Unix syslog password reset events
  Syslog
  | where Facility in ("auth","authpriv")
  | where SyslogMessage has_any (pWord) and SyslogMessage has_any (action)
  | extend AccountType = iif(SyslogMessage contains "root", "Root", "Non-Root")
  | where SyslogMessage matches regex ".*password changed for.*"
  | parse SyslogMessage with * "password changed for" Account
  | project TimeGenerated, AccountType, Account, Computer = HostName, Type)
  );
  let pwrmd = PasswordResetMultiDataSource
  | project TimeGenerated, Computer, AccountType, Account, Type, TargetUserName;
  (union isfuzzy=true
  (pwrmd
  | summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), Computerlist = make_set(Computer, 25), AccountType = make_set(AccountType, 25), Computer = arg_max(Computer , TimeGenerated), TargetUserList = make_set(TargetUserName, 25), TargetUserName = arg_max(TargetUserName, TimeGenerated), Total=count() by Account, Type
  | where Total > PerUserThreshold
  | extend ResetPivot = "PerUserReset"),
  (pwrmd
  | summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), ComputerList = make_set(Computer, 25), AccountList = make_set(Account, 25), AccountType = make_set(AccountType, 25), Computer = arg_max(Computer , TimeGenerated), TargetUserList = make_set(TargetUserName, 25), TargetUserName = arg_max(TargetUserName, TimeGenerated), Total=count() by Type
  | where Total > TotalThreshold
  | extend ResetPivot = "TotalUserReset")
  )
  | extend timestamp = StartTimeUtc, HostName = tostring(split(Computer, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(Computer, '.'), 1, -1), '.')), Name = tostring(split(Account, '@', 0)[0]), UPNSuffix = tostring(split(Account, '@', 1)[0]), TargetName = tostring(split(TargetUserName,'@',0)[0]), TargetUPNSuffix = tostring(split(TargetUserName,'@',1)[0])  
triggerOperator: gt
queryPeriod: 1d
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Detections/MultipleDataSources/MultiplePasswordresetsbyUser.yaml
relevantTechniques:
- T1078
- T1110
id: 0b9ae89d-8cad-461c-808f-0494f70ad5c4
requiredDataConnectors:
- connectorId: AzureActiveDirectory
  dataTypes:
  - AuditLogs
- connectorId: SecurityEvents
  dataTypes:
  - SecurityEvent
- connectorId: Syslog
  dataTypes:
  - Syslog
- connectorId: Office365
  dataTypes:
  - OfficeActivity
- connectorId: WindowsSecurityEvents
  dataTypes:
  - SecurityEvents
- connectorId: WindowsForwardedEvents
  dataTypes:
  - WindowsEvent
version: 2.1.7
description: |
  'This query will determine multiple password resets by user across multiple data sources.
  Account manipulation including password reset may aid adversaries in maintaining access to credentials and certain permission levels within an environment.'  
{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "workspace": {
      "type": "String"
    }
  },
  "resources": [
    {
      "apiVersion": "2024-01-01-preview",
      "id": "[concat(resourceId('Microsoft.OperationalInsights/workspaces/providers', parameters('workspace'), 'Microsoft.SecurityInsights'),'/alertRules/0b9ae89d-8cad-461c-808f-0494f70ad5c4')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/0b9ae89d-8cad-461c-808f-0494f70ad5c4')]",
      "properties": {
        "alertRuleTemplateName": "0b9ae89d-8cad-461c-808f-0494f70ad5c4",
        "customDetails": null,
        "description": "'This query will determine multiple password resets by user across multiple data sources.\nAccount manipulation including password reset may aid adversaries in maintaining access to credentials and certain permission levels within an environment.'\n",
        "displayName": "Multiple Password Reset by user",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "Account",
                "identifier": "FullName"
              },
              {
                "columnName": "Name",
                "identifier": "Name"
              },
              {
                "columnName": "UPNSuffix",
                "identifier": "UPNSuffix"
              }
            ]
          },
          {
            "entityType": "Host",
            "fieldMappings": [
              {
                "columnName": "Computer",
                "identifier": "FullName"
              },
              {
                "columnName": "HostName",
                "identifier": "HostName"
              },
              {
                "columnName": "DnsDomain",
                "identifier": "DnsDomain"
              }
            ]
          },
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "TargetUserName",
                "identifier": "FullName"
              },
              {
                "columnName": "TargetName",
                "identifier": "Name"
              },
              {
                "columnName": "TargetUPNSuffix",
                "identifier": "UPNSuffix"
              }
            ]
          }
        ],
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Detections/MultipleDataSources/MultiplePasswordresetsbyUser.yaml",
        "query": "let selfServicePasswordReset = dynamic([\"Self-service password reset flow activity progress\", \"Change password (self-service)\", \"Reset password (self-service)\"]); \n//Self-service password reset flow activity progress is typically caused by a password policy which requires users to rotate passwords. This operation already implies the user has signed in successfully and therefore the password reset is non-malicious.\nlet PerUserThreshold = 5;\nlet TotalThreshold = 100;\nlet action = dynamic([\"change\", \"changed\", \"reset\"]);\nlet pWord = dynamic([\"password\", \"credentials\"]);\nlet PasswordResetMultiDataSource =\n(union isfuzzy=true\n(//Password reset events\n//4723: An attempt was made to change an account's password\n//4724: An attempt was made to reset an accounts password\nSecurityEvent\n| where EventID in (\"4723\",\"4724\")\n| project TimeGenerated, Computer, AccountType, Account, Type, TargetUserName),\n(//Password reset events\n//4723: An attempt was made to change an account's password\n//4724: An attempt was made to reset an accounts password\nWindowsEvent\n| where EventID in (\"4723\",\"4724\")\n| extend SubjectUserSid = tostring(EventData.SubjectUserSid)\n| extend TargetUserName = tostring(EventData.TargetUserName)\n| extend Account = strcat(tostring(EventData.SubjectDomainName),\"\\\\\", tostring(EventData.SubjectUserName))\n| extend AccountType=case(Account endswith \"$\" or SubjectUserSid in (\"S-1-5-18\", \"S-1-5-19\", \"S-1-5-20\"), \"Machine\", isempty(SubjectUserSid), \"\", \"User\")\n| project TimeGenerated, Computer, AccountType, Account, Type, TargetUserName),\n(//Azure Active Directory Password reset events\nAuditLogs\n| where OperationName has_any (pWord) and OperationName has_any (action) and Result =~ \"success\"\n| where OperationName !in (selfServicePasswordReset)\n| mv-apply TargetResource = TargetResources on \n  (\n      where TargetResource.type =~ \"User\"\n      | extend AccountType = tostring(TargetResource.type),\n               Account = tostring(InitiatedBy.user.userPrincipalName),\n               TargetUserName = tolower(tostring(TargetResource.userPrincipalName))\n  )\n| project TimeGenerated, AccountType, Account, TargetUserName, Computer = \"\", Type),\n(//OfficeActive ActiveDirectory Password reset events\nOfficeActivity\n| where OfficeWorkload == \"AzureActiveDirectory\"\n| where (ExtendedProperties has_any (pWord) or ModifiedProperties has_any (pWord)) and (ExtendedProperties has_any (action) or ModifiedProperties has_any (action))\n| extend AccountType = UserType, Account = OfficeObjectId\n| project TimeGenerated, AccountType, Account, Type, Computer = \"\"),\n(// Unix syslog password reset events\nSyslog\n| where Facility in (\"auth\",\"authpriv\")\n| where SyslogMessage has_any (pWord) and SyslogMessage has_any (action)\n| extend AccountType = iif(SyslogMessage contains \"root\", \"Root\", \"Non-Root\")\n| where SyslogMessage matches regex \".*password changed for.*\"\n| parse SyslogMessage with * \"password changed for\" Account\n| project TimeGenerated, AccountType, Account, Computer = HostName, Type)\n);\nlet pwrmd = PasswordResetMultiDataSource\n| project TimeGenerated, Computer, AccountType, Account, Type, TargetUserName;\n(union isfuzzy=true\n(pwrmd\n| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), Computerlist = make_set(Computer, 25), AccountType = make_set(AccountType, 25), Computer = arg_max(Computer , TimeGenerated), TargetUserList = make_set(TargetUserName, 25), TargetUserName = arg_max(TargetUserName, TimeGenerated), Total=count() by Account, Type\n| where Total > PerUserThreshold\n| extend ResetPivot = \"PerUserReset\"),\n(pwrmd\n| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), ComputerList = make_set(Computer, 25), AccountList = make_set(Account, 25), AccountType = make_set(AccountType, 25), Computer = arg_max(Computer , TimeGenerated), TargetUserList = make_set(TargetUserName, 25), TargetUserName = arg_max(TargetUserName, TimeGenerated), Total=count() by Type\n| where Total > TotalThreshold\n| extend ResetPivot = \"TotalUserReset\")\n)\n| extend timestamp = StartTimeUtc, HostName = tostring(split(Computer, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(Computer, '.'), 1, -1), '.')), Name = tostring(split(Account, '@', 0)[0]), UPNSuffix = tostring(split(Account, '@', 1)[0]), TargetName = tostring(split(TargetUserName,'@',0)[0]), TargetUPNSuffix = tostring(split(TargetUserName,'@',1)[0])\n",
        "queryFrequency": "P1D",
        "queryPeriod": "P1D",
        "severity": "Low",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "CredentialAccess",
          "InitialAccess"
        ],
        "techniques": [
          "T1078",
          "T1110"
        ],
        "templateVersion": "2.1.7",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}