Potential Password Spraying Attack via SSH

This rule detects potential password spraying attacks via SSH by identifying multiple failed login attempts from a single source IP address targeting various user accounts within a short time frame. Password spraying is a technique where an attacker attempts to gain unauthorized access by trying a few commonly used passwords against many different accounts, rather than targeting a single account with multiple password attempts.

Elastic rule (View on GitHub)

 1[metadata]
 2creation_date = "2025/12/24"
 3integration = ["system"]
 4maturity = "production"
 5updated_date = "2025/12/24"
 6
 7[rule]
 8author = ["Elastic"]
 9description = """
10This rule detects potential password spraying attacks via SSH by identifying multiple failed login
11attempts from a single source IP address targeting various user accounts within a short time frame.
12Password spraying is a technique where an attacker attempts to gain unauthorized access by trying a
13few commonly used passwords against many different accounts, rather than targeting a single account
14with multiple password attempts.
15"""
16from = "now-9m"
17language = "esql"
18license = "Elastic License v2"
19name = "Potential Password Spraying Attack via SSH"
20risk_score = 21
21rule_id = "9e81b1fd-e9fb-49a7-8ebe-0d1a14090142"
22severity = "low"
23tags = [
24    "Domain: Endpoint",
25    "OS: Linux",
26    "Use Case: Threat Detection",
27    "Tactic: Credential Access",
28]
29timestamp_override = "event.ingested"
30type = "esql"
31query = '''
32from logs-system.auth-* metadata _id, _index, _version
33
34// Create 5-minute time buckets
35| eval Esql.time_window_date_trunc = date_trunc(5 minutes, @timestamp)
36
37// Ensure event.action values in a list are expanded
38| mv_expand event.action 
39
40| where
41  event.category == "authentication" and event.action in ("ssh_login", "user_login") and event.outcome == "failure" and
42  source.ip is not null 
43
44// Keep relevant fields
45| keep
46   @timestamp,
47   _id,
48   _index,
49   _version,
50   event.category,
51   event.action,
52   event.outcome,
53   source.ip,
54   process.name,
55   user.name,
56   event.dataset,
57   data_stream.namespace,
58   agent.id,
59   user.id,
60   Esql.time_window_date_trunc
61
62| stats
63  Esql.event_count = count(*),
64  Esql.user_name_count_distinct = count_distinct(user.name),
65  Esql.user_name_values = values(user.name),
66  Esql.process_name_values = values(process.name),
67  Esql.event_dataset_values = values(event.dataset),
68  Esql.data_stream_namespace_values = values(data_stream.namespace)
69
70  by Esql.time_window_date_trunc, source.ip
71
72| where Esql.user_name_count_distinct > 10 and Esql.event_count >= 30
73'''
74
75[[rule.threat]]
76framework = "MITRE ATT&CK"
77
78[[rule.threat.technique]]
79id = "T1110"
80name = "Brute Force"
81reference = "https://attack.mitre.org/techniques/T1110/"
82
83[[rule.threat.technique.subtechnique]]
84id = "T1110.001"
85name = "Password Guessing"
86reference = "https://attack.mitre.org/techniques/T1110/001/"
87
88[[rule.threat.technique.subtechnique]]
89id = "T1110.003"
90name = "Password Spraying"
91reference = "https://attack.mitre.org/techniques/T1110/003/"
92
93[rule.threat.tactic]
94id = "TA0006"
95name = "Credential Access"
96reference = "https://attack.mitre.org/tactics/TA0006/"

Related rules

to-top