Skip to content

Conversation

@Aegrah
Copy link
Contributor

@Aegrah Aegrah commented Dec 24, 2025

Summary

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.

{39FEC8ED-B397-4673-B764-7C4C52CE64DF}

@github-actions
Copy link
Contributor

Rule: New - Guidelines

These guidelines serve as a reminder set of considerations when proposing a new rule.

Documentation and Context

  • Detailed description of the rule.
  • List any new fields required in ECS/data sources.
  • Link related issues or PRs.
  • Include references.

Rule Metadata Checks

  • creation_date matches the date of creation PR initially merged.
  • min_stack_version should support the widest stack versions.
  • name and description should be descriptive and not include typos.
  • query should be inclusive, not overly exclusive, considering performance for diverse environments. Non ecs fields should be added to non-ecs-schema.json if not available in an integration.
  • min_stack_comments and min_stack_version should be included if the rule is only compatible starting from a specific stack version.
  • index pattern should be neither too specific nor too vague, ensuring it accurately matches the relevant data stream (e.g., use logs-endpoint.process-* for process data).
  • integration should align with the index. If the integration is newly introduced, ensure the manifest, schemas, and new_rule.yaml template are updated.
  • setup should include the necessary steps to configure the integration.
  • note should include any additional information (e.g. Triage and analysis investigation guides, timeline templates).
  • tags should be relevant to the threat and align/added to the EXPECTED_RULE_TAGS in the definitions.py file.
  • threat, techniques, and subtechniques should map to ATT&CK always if possible.

New BBR Rules

  • building_block_type should be included if the rule is a building block and the rule should be located in the rules_building_block folder.
  • bypass_bbr_timing should be included if adding custom lookback timing to the rule.

Testing and Validation

  • Provide evidence of testing and detecting the expected threat.
  • Check for existence of coverage to prevent duplication.

@tradebot-elastic
Copy link

tradebot-elastic commented Dec 24, 2025

⛔️ Test failed

Results
  • ❌ Potential Password Spraying Attack via SSH (esql)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta

timestamp_override = "event.ingested"
type = "esql"
query = '''
from "logs-system.auth-*" metadata _id, _index, _version
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
from "logs-system.auth-*" metadata _id, _index, _version
from logs-system.auth-*

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed this on Slack, although not necessary (as metadata is dropped after stats), we are enforcing metadata in unit tests soon for non-stats queries, and I think it's better for consistency to just add it, as it does no harm (as far as I know), and makes all rules similar.

Comment on lines 46 to 60
| 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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
| 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

Everything that is not used in the stats is dropped, makes more sense to do the KEEP after stats

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding KEEP after stats also makes no sense, because stats will only keep all fields within the by clause or used in the stats function, so it would not really do much. I mostly add keeps because the unit tests expect them. Think it is good to have a broader discussion about this in the new year.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are pros and cons for enforcing KEEP and placement. Performance (if any) for aggregation-based (use it before aggregating for performance). Otherwise by does a KEEP in theory. Non-aggregation-based, it can be used but forces limitations on fields that appear in the alert doc which I don't believe we want to practice doing. Maybe we follow-up with ES on the subject and if it is still best practice given our scenarios and rule examples.


by source.ip

| where Esql.user_name_count_distinct > 10 and Esql.event_count >= 30
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
| where Esql.user_name_count_distinct > 10 and Esql.event_count >= 30
| where Esql.user_name_count_distinct > 10 and Esql.event_count >= 30
| keep Esql.*, source.ip

…ck.toml

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

tradebot-elastic commented Dec 24, 2025

⛔️ Test failed

Results
  • ❌ Potential Password Spraying Attack via SSH (esql)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta

@tradebot-elastic
Copy link

tradebot-elastic commented Dec 24, 2025

⛔️ Test failed

Results
  • ❌ Potential Password Spraying Attack via SSH (esql)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta

Copy link
Contributor

@Mikaayenson Mikaayenson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One question that comes to mind is the bustiness of this. I think it's >10 unique users and >=30 failures in 1 min bucket? I wonder if we should expand the bucket e.g. 5 min or lower the counts?

@tradebot-elastic
Copy link

tradebot-elastic commented Jan 8, 2026

⛔️ Test failed

Results
  • ❌ Potential Password Spraying Attack via SSH (esql)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta

@tradebot-elastic
Copy link

tradebot-elastic commented Jan 8, 2026

⛔️ Test failed

Results
  • ❌ Potential Password Spraying Attack via SSH (esql)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta

@tradebot-elastic
Copy link

tradebot-elastic commented Jan 8, 2026

⛔️ Test failed

Results
  • ❌ Potential Password Spraying Attack via SSH (esql)
    • coverage_issue: no_rta
    • stack_validation_failed: no_rta

@Aegrah
Copy link
Contributor Author

Aegrah commented Jan 8, 2026

@Mikaayenson expanded the interval slightly.

@Aegrah Aegrah merged commit ee936cb into main Jan 8, 2026
14 checks passed
@Aegrah Aegrah deleted the new-rule-password-spraying branch January 8, 2026 12:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants