Detection rules › Splunk

Detect Excessive Account Lockouts From Endpoint

Status
production
Severity
low
Group by
All_Changes.dest, All_Changes.result
Author
David Dorsey, Splunk
Source
github.com/splunk/security_content

The following analytic detects endpoints causing a high number of account lockouts within a short period. It leverages the Windows security event logs ingested into the Change datamodel, specifically under the Account_Management node, to identify and count lockout events. This activity is significant as it may indicate a brute-force attack or misconfigured system causing repeated authentication failures. If confirmed malicious, this behavior could lead to account lockouts, disrupting user access and potentially indicating an ongoing attack attempting to compromise user credentials.

MITRE ATT&CK coverage

Rule body splunk

name: Detect Excessive Account Lockouts From Endpoint
id: c026e3dd-7e18-4abb-8f41-929e836efe74
version: 17
creation_date: '2020-04-29'
modification_date: '2026-05-13'
author: David Dorsey, Splunk
status: production
type: Anomaly
description: The following analytic detects endpoints causing a high number of account lockouts within a short period. It leverages the Windows security event logs ingested into the `Change` datamodel, specifically under the `Account_Management` node, to identify and count lockout events. This activity is significant as it may indicate a brute-force attack or misconfigured system causing repeated authentication failures. If confirmed malicious, this behavior could lead to account lockouts, disrupting user access and potentially indicating an ongoing attack attempting to compromise user credentials.
data_source: []
search: |-
    | tstats `security_content_summariesonly` count min(_time) as firstTime max(_time) as lastTime values(All_Changes.user) as user FROM datamodel=Change.All_Changes
      WHERE All_Changes.result="*lock*"
      BY All_Changes.dest All_Changes.result
    | `drop_dm_object_name("All_Changes")`
    | `drop_dm_object_name("Account_Management")`
    | `security_content_ctime(firstTime)`
    | `security_content_ctime(lastTime)`
    | search count > 5
    | `detect_excessive_account_lockouts_from_endpoint_filter`
how_to_implement: You must ingest your Windows security event logs in the `Change` datamodel under the nodename is `Account_Management`, for this search to execute successfully. Please consider updating the cron schedule and the count of lockouts you want to monitor, according to your environment.\n**Splunk>Phantom Playbook Integration** If Splunk>Phantom is also configured in your environment, a Playbook called \"Excessive Account Lockouts Enrichment and Response\" can be configured to run when any results are found by this detection search. The Playbook executes the Contextual and Investigative searches in this Story, conducts additional information gathering on Windows endpoints, and takes a response action to shut down the affected endpoint. To use this integration, install the Phantom App for Splunk `https://splunkbase.splunk.com/app/3411/`, add the correct hostname to the \"Phantom Instance\" field in the Adaptive Response Actions when configuring this detection search, and set the corresponding Playbook to active.\nPlaybook Link:`https://my.phantom.us/4.1/playbook/excessive-account-lockouts-enrichment-and-response/`)
known_false_positives: It's possible that a widely used system, such as a kiosk, could cause a large number of account lockouts.
references: []
drilldown_searches:
    - name: View the detection results for - "$user$" and "$dest$"
      search: '%original_detection_search% | search  user = "$user$" dest = "$dest$"'
      earliest_offset: $info_min_time$
      latest_offset: $info_max_time$
    - name: View risk events for the last 7 days for - "$user$" and "$dest$"
      search: '| from datamodel Risk.All_Risk | search normalized_risk_object IN ("$user$", "$dest$") | stats count min(_time) as firstTime max(_time) as lastTime values(search_name) as "Search Name" values(risk_message) as "Risk Message" values(analyticstories) as "Analytic Stories" values(annotations._all) as "Annotations" values(annotations.mitre_attack.mitre_tactic) as "ATT&CK Tactics" by normalized_risk_object | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)`'
      earliest_offset: 7d
      latest_offset: "0"
intermediate_findings:
    entities:
        - field: user
          type: user
          score: 20
          message: Multiple accounts have been locked out. Review $dest$ and results related to $user$.
        - field: dest
          type: system
          score: 20
          message: Multiple accounts have been locked out. Review $dest$ and results related to $user$.
analytic_story:
    - Active Directory Password Spraying
asset_type: Windows
mitre_attack_id:
    - T1078.002
product:
    - Splunk Enterprise
    - Splunk Enterprise Security
    - Splunk Cloud
category: endpoint
security_domain: access
tests:
    - name: True Positive Test
      attack_data:
        - data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1078.002/account_lockout/windows-security.log
          source: WinEventLog:Security
          sourcetype: WinEventLog
        - data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1078.002/account_lockout/windows-system.log
          source: WinEventLog:System
          sourcetype: WinEventLog
        - data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1078.002/account_lockout/windows-xml.log
          source: XmlWinEventLog:Security
          sourcetype: XmlWinEventLog
      test_type: unit

Stages and Predicates

Stage 1: tstats

| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time) as lastTime values(All_Changes.user) as user FROM datamodel=Change.All_Changes
  WHERE All_Changes.result="*lock*"
  BY All_Changes.dest All_Changes.result

Stage 2: search

| `drop_dm_object_name("All_Changes")`

Stage 3: search

| `drop_dm_object_name("Account_Management")`

Stage 4: search

| `security_content_ctime(firstTime)`

Stage 5: search

| `security_content_ctime(lastTime)`

Stage 6: search

| search count > 5

Stage 7: search

| `detect_excessive_account_lockouts_from_endpoint_filter`

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
All_Changes.resulteq
  • "*lock*" corpus 2 (splunk 2)
countgt
  • 5 corpus 14 (splunk 14)