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 = "2026/01/12"
  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"
 20note = """ ## Triage and analysis
 21
 22> **Disclaimer**:
 23> This investigation guide was created using generative AI technology and has been reviewed to improve its accuracy and relevance. While every effort has been made to ensure its quality, we recommend validating the content and adapting it to suit your specific environment and operational needs.
 24
 25### Investigating Potential Password Spraying Attack via SSH
 26
 27This rule flags bursts of failed SSH logins coming from the same network origin against many different Linux accounts within a short window, indicating password spraying that can precede account compromise. It matters because attackers try a small set of common passwords across broad user lists to evade lockouts and find one weak credential. A typical pattern is an external VPS rapidly trying passwords like “Welcome123” or “Spring2024!” against 30+ usernames (e.g., admin, test, ubuntu, devops) over five minutes via SSH on a single server.
 28
 29### Possible investigation steps
 30
 31- Check for any successful SSH authentications from the same source IP within a short window around the failures and, if found, pivot to session details such as interactive TTY use, sudo activity, and modifications like authorized_keys updates.
 32- Enrich the source IP with geolocation, ASN, reputation, and cloud-provider attribution and verify whether it is observed attempting SSH across multiple hosts to confirm a broad spray pattern.
 33- Compare the attempted usernames against your directory to identify valid and privileged or service accounts and confirm whether lockouts, password resets, or MFA challenges were triggered.
 34- Determine if the affected host is internet-exposed and which port SSH is reachable on, then review current SSH authentication settings (password vs key-based, PAM/MFA) to assess risk of compromise.
 35- Correlate the source IP with approved scanners, bastion hosts, or change tickets and maintenance windows to quickly rule out sanctioned testing or misconfigured monitoring.
 36
 37### False positive analysis
 38
 39- A misconfigured internal automation or admin script on a management or jump host sequentially attempts SSH to many accounts with an outdated password, producing more than 10 distinct usernames and at least 30 failures from a single source IP within five minutes.
 40- Legitimate users behind a shared NAT or bastion host concurrently attempt SSH with expired credentials during a password rotation or temporary authentication issue, making failures across many distinct usernames appear to come from one IP.
 41
 42### Response and remediation
 43
 44- Immediately block the spraying source IP(s) at host firewalls (iptables/nftables) and edge controls, and temporarily restrict SSH (port 22) to approved bastion/jump host CIDRs only.
 45- If any login succeeded or an sshd session from the same IP is active, terminate it, remove any newly added ~/.ssh/authorized_keys entries, and force password resets with MFA for the targeted users.
 46- Before restoring normal access, verify no persistence by checking for changes to /etc/ssh/sshd_config, sudoers, or cron jobs and reviewing /var/log/auth.log and lastlog for anomalies, then re-enable only required accounts.
 47- Escalate to incident response if privileged or service accounts were targeted, the spray spanned multiple servers, or there is evidence of sudo activity, file changes under /root or /etc, or a successful login, and preserve auth logs, bash histories, and firewall block artifacts.
 48- Harden SSH by disabling PasswordAuthentication, enforcing key-based auth with PAM MFA, setting conservative MaxAuthTries and LoginGraceTime, enabling fail2ban or equivalent bans, and restricting access via AllowUsers/AllowGroups and security group rules.
 49"""
 50risk_score = 21
 51rule_id = "9e81b1fd-e9fb-49a7-8ebe-0d1a14090142"
 52severity = "low"
 53tags = [
 54    "Domain: Endpoint",
 55    "OS: Linux",
 56    "Use Case: Threat Detection",
 57    "Tactic: Credential Access",
 58    "Resources: Investigation Guide",
 59]
 60timestamp_override = "event.ingested"
 61type = "esql"
 62query = '''
 63from logs-system.auth-* metadata _id, _index, _version
 64
 65// Create 5-minute time buckets
 66| eval Esql.time_window_date_trunc = date_trunc(5 minutes, @timestamp)
 67
 68// Ensure event.action values in a list are expanded
 69| mv_expand event.action 
 70
 71| where
 72  event.category == "authentication" and event.action in ("ssh_login", "user_login") and event.outcome == "failure" and
 73  source.ip is not null 
 74
 75// Keep relevant fields
 76| keep
 77   @timestamp,
 78   _id,
 79   _index,
 80   _version,
 81   event.category,
 82   event.action,
 83   event.outcome,
 84   source.ip,
 85   process.name,
 86   user.name,
 87   event.dataset,
 88   data_stream.namespace,
 89   agent.id,
 90   user.id,
 91   Esql.time_window_date_trunc
 92
 93| stats
 94  Esql.event_count = count(*),
 95  Esql.user_name_count_distinct = count_distinct(user.name),
 96  Esql.user_name_values = values(user.name),
 97  Esql.process_name_values = values(process.name),
 98  Esql.event_dataset_values = values(event.dataset),
 99  Esql.data_stream_namespace_values = values(data_stream.namespace)
100
101  by Esql.time_window_date_trunc, source.ip
102
103| where Esql.user_name_count_distinct > 10 and Esql.event_count >= 30
104'''
105
106[[rule.threat]]
107framework = "MITRE ATT&CK"
108
109[[rule.threat.technique]]
110id = "T1110"
111name = "Brute Force"
112reference = "https://attack.mitre.org/techniques/T1110/"
113
114[[rule.threat.technique.subtechnique]]
115id = "T1110.001"
116name = "Password Guessing"
117reference = "https://attack.mitre.org/techniques/T1110/001/"
118
119[[rule.threat.technique.subtechnique]]
120id = "T1110.003"
121name = "Password Spraying"
122reference = "https://attack.mitre.org/techniques/T1110/003/"
123
124[rule.threat.tactic]
125id = "TA0006"
126name = "Credential Access"
127reference = "https://attack.mitre.org/tactics/TA0006/"

Triage and analysis

Disclaimer: This investigation guide was created using generative AI technology and has been reviewed to improve its accuracy and relevance. While every effort has been made to ensure its quality, we recommend validating the content and adapting it to suit your specific environment and operational needs.

Investigating Potential Password Spraying Attack via SSH

This rule flags bursts of failed SSH logins coming from the same network origin against many different Linux accounts within a short window, indicating password spraying that can precede account compromise. It matters because attackers try a small set of common passwords across broad user lists to evade lockouts and find one weak credential. A typical pattern is an external VPS rapidly trying passwords like “Welcome123” or “Spring2024!” against 30+ usernames (e.g., admin, test, ubuntu, devops) over five minutes via SSH on a single server.

Possible investigation steps

  • Check for any successful SSH authentications from the same source IP within a short window around the failures and, if found, pivot to session details such as interactive TTY use, sudo activity, and modifications like authorized_keys updates.
  • Enrich the source IP with geolocation, ASN, reputation, and cloud-provider attribution and verify whether it is observed attempting SSH across multiple hosts to confirm a broad spray pattern.
  • Compare the attempted usernames against your directory to identify valid and privileged or service accounts and confirm whether lockouts, password resets, or MFA challenges were triggered.
  • Determine if the affected host is internet-exposed and which port SSH is reachable on, then review current SSH authentication settings (password vs key-based, PAM/MFA) to assess risk of compromise.
  • Correlate the source IP with approved scanners, bastion hosts, or change tickets and maintenance windows to quickly rule out sanctioned testing or misconfigured monitoring.

False positive analysis

  • A misconfigured internal automation or admin script on a management or jump host sequentially attempts SSH to many accounts with an outdated password, producing more than 10 distinct usernames and at least 30 failures from a single source IP within five minutes.
  • Legitimate users behind a shared NAT or bastion host concurrently attempt SSH with expired credentials during a password rotation or temporary authentication issue, making failures across many distinct usernames appear to come from one IP.

Response and remediation

  • Immediately block the spraying source IP(s) at host firewalls (iptables/nftables) and edge controls, and temporarily restrict SSH (port 22) to approved bastion/jump host CIDRs only.
  • If any login succeeded or an sshd session from the same IP is active, terminate it, remove any newly added ~/.ssh/authorized_keys entries, and force password resets with MFA for the targeted users.
  • Before restoring normal access, verify no persistence by checking for changes to /etc/ssh/sshd_config, sudoers, or cron jobs and reviewing /var/log/auth.log and lastlog for anomalies, then re-enable only required accounts.
  • Escalate to incident response if privileged or service accounts were targeted, the spray spanned multiple servers, or there is evidence of sudo activity, file changes under /root or /etc, or a successful login, and preserve auth logs, bash histories, and firewall block artifacts.
  • Harden SSH by disabling PasswordAuthentication, enforcing key-based auth with PAM MFA, setting conservative MaxAuthTries and LoginGraceTime, enabling fail2ban or equivalent bans, and restricting access via AllowUsers/AllowGroups and security group rules.

Related rules

to-top