[New Rule] Potential Password Spraying Attack via SSH (#5515)

* [New Rule] Potential Password Spraying Attack via SSH

* ++

* Update rules/linux/credential_access_potential_password_spraying_attack.toml

Co-authored-by: Jonhnathan <26856693+w0rk3r@users.noreply.github.com>

* Update credential_access_potential_password_spraying_attack.toml

* Update credential_access_potential_password_spraying_attack.toml

* Change time bucket duration from 1 to 5 minutes

---------

Co-authored-by: Jonhnathan <26856693+w0rk3r@users.noreply.github.com>
This commit is contained in:
Ruben Groenewoud
2026-01-08 13:43:52 +01:00
committed by GitHub
parent 1c1632e0b9
commit ee936cb154
@@ -0,0 +1,96 @@
[metadata]
creation_date = "2025/12/24"
integration = ["system"]
maturity = "production"
updated_date = "2025/12/24"
[rule]
author = ["Elastic"]
description = """
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.
"""
from = "now-9m"
language = "esql"
license = "Elastic License v2"
name = "Potential Password Spraying Attack via SSH"
risk_score = 21
rule_id = "9e81b1fd-e9fb-49a7-8ebe-0d1a14090142"
severity = "low"
tags = [
"Domain: Endpoint",
"OS: Linux",
"Use Case: Threat Detection",
"Tactic: Credential Access",
]
timestamp_override = "event.ingested"
type = "esql"
query = '''
from logs-system.auth-* metadata _id, _index, _version
// Create 5-minute time buckets
| eval Esql.time_window_date_trunc = date_trunc(5 minutes, @timestamp)
// Ensure event.action values in a list are expanded
| mv_expand event.action
| where
event.category == "authentication" and event.action in ("ssh_login", "user_login") and event.outcome == "failure" and
source.ip is not null
// Keep relevant fields
| keep
@timestamp,
_id,
_index,
_version,
event.category,
event.action,
event.outcome,
source.ip,
process.name,
user.name,
event.dataset,
data_stream.namespace,
agent.id,
user.id,
Esql.time_window_date_trunc
| stats
Esql.event_count = count(*),
Esql.user_name_count_distinct = count_distinct(user.name),
Esql.user_name_values = values(user.name),
Esql.process_name_values = values(process.name),
Esql.event_dataset_values = values(event.dataset),
Esql.data_stream_namespace_values = values(data_stream.namespace)
by Esql.time_window_date_trunc, source.ip
| where Esql.user_name_count_distinct > 10 and Esql.event_count >= 30
'''
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1110"
name = "Brute Force"
reference = "https://attack.mitre.org/techniques/T1110/"
[[rule.threat.technique.subtechnique]]
id = "T1110.001"
name = "Password Guessing"
reference = "https://attack.mitre.org/techniques/T1110/001/"
[[rule.threat.technique.subtechnique]]
id = "T1110.003"
name = "Password Spraying"
reference = "https://attack.mitre.org/techniques/T1110/003/"
[rule.threat.tactic]
id = "TA0006"
name = "Credential Access"
reference = "https://attack.mitre.org/tactics/TA0006/"