Threat Hunting Exercise: Analyzing Linux SSH Brute Force Credential Stuffing Dataset
This hunt uses a simulated Linux authentication dataset (linux_auth_ssh_bruteforce_2022-10-11T033000.json) capturing T1110.004: Brute Force (Credential Stuffing), where an attacker uses a distributed botnet or proxy pool to attempt SSH logins against many usernames using credentials leaked from unrelated third-party breaches, seeking password reuse across the organization's exposed SSH-facing hosts.
Step 1: Hypothesis Formation
Hypothesis: A single or small set of source IPs generates a high volume of SSH authentication failures across many distinct usernames in a short window, with the username list resembling a common-breach-corpus pattern (email-address-style usernames, common first.last combinations) rather than a targeted guess against known organizational accounts, and at least one attempt eventually succeeds - indicating credential-stuffing rather than a targeted or misconfigured-client brute force. Indicators:
- High
sshdFailed passwordevent volume (dozens to hundreds) from one source IP within minutes, spanning many distinct usernames. - Username variety inconsistent with the organization's actual naming convention (e.g., attempts for
admin,root,oracle,test, alongside random email-style strings). - A successful
Accepted passwordevent for one of the attempted usernames immediately following the failure burst, especially for an account with a weak or reused password. - The source IP has no prior authentication history against this host and often resolves to a hosting/VPS provider or known brute-force botnet range.
Null Hypothesis: A misconfigured automated client (backup agent, monitoring tool) is retrying a single expired credential rapidly against one username, producing a failure burst without genuine brute-force intent. Invalidate by confirming a single consistent username is targeted and matching the source IP against internal/known-vendor IP ranges.
Rationale: Credential stuffing exploits password reuse rather than any technical vulnerability, so the definitive detection signal is behavioral - volume, username diversity, and source-IP reputation - rather than any single failed-login event, which is common and often benign in isolation.
Step 2: Data Sources and Scope
- Sources:
/var/log/auth.log(sshdFailed/Accepted password events);fail2banlogs; threat-intelligence IP reputation feeds. - Scope: ~2022-10-11T03:30:00-04:15:00 UTC; Host: srv-bastion-01 (203.0.113.44, internet-facing); Source: 179.43.128.6 (hosting-provider range, prior brute-force reputation).
- SIEM Queries (Splunk/ELK):
index=linux sourcetype=auth "Failed password" | stats count, dc(user) as unique_users by src_ip | where count>50 AND unique_users>20- Success-after-failure:
index=linux sourcetype=auth ("Accepted password") src_ip=179.43.128.6 - Reputation check:
| lookup threat_intel_ip src_ip OUTPUT reputation_score, known_categories
Step 3: Key Findings
Parsed events (5 shown) confirm 179.43.128.6 attempted SSH logins against 214 distinct usernames in 42 minutes, with a successful login for account j.reyes - whose password matched a value present in a public breach corpus - immediately following the failure burst.
| Timestamp (UTC) | Host | Event | Detail | IOC/Why Suspicious? |
|---|---|---|---|---|
| 2022-10-11 03:31:04 - 04:12:58 | srv-bastion-01 | auth.log (aggregate) | 1,847 Failed password events from 179.43.128.6 across 214 unique usernames | Volume+Diversity IOC: this scale and username variety is characteristic of automated credential-stuffing tooling (e.g., Hydra with a breach-corpus wordlist), not manual guessing or a misconfigured client. |
| 2022-10-11 03:31:05 | srv-bastion-01 | auth.log sample | Attempted usernames include admin, oracle, test, j.reyes, m.patel1985@gmail.com | Corpus-Pattern IOC: the mix of generic service-account guesses and email-style usernames is a signature of publicly available breach-derived credential lists rather than organization-specific reconnaissance. |
| 2022-10-11 04:13:02 | srv-bastion-01 | auth.log | Accepted password for j.reyes from 179.43.128.6 | Successful-Compromise IOC: a successful authentication immediately following the failure burst for the same source IP confirms the credential-stuffing attack succeeded against at least one account. |
| - | (threat intel) | (reputation lookup) | 179.43.128.6 flagged in threat-intel feeds as associated with SSH brute-force campaigns over the preceding 60 days | Corroborates the source as known malicious infrastructure rather than a legitimate remote worker or partner. |
| 2022-10-11 04:14:30 | srv-bastion-01 | auth.log | j.reyes session immediately ran sudo -l and cat ~/.ssh/authorized_keys | Post-Compromise IOC: immediate privilege-enumeration and SSH-key reconnaissance confirms active, intentional exploitation of the compromised account, not an idle successful login. |
Validation:
- Timeline: sustained high-volume, high-diversity failure burst from a reputation-flagged IP, followed by a successful login and immediate post-compromise reconnaissance - a complete and confirmed credential-stuffing-to-compromise chain.
- False Positives: the source IP has no prior legitimate authentication history on this host, and the username pattern does not match any single misconfigured internal automation client.
- Correlation: volume, username diversity, source-IP reputation, successful login, and post-compromise activity jointly confirm a successful credential-stuffing attack.
Step 4: Recommendations & Next Steps
- Immediate Response: Disable or force a password reset for
j.reyesimmediately, review and revoke any SSH keys added during the session, block 179.43.128.6 at the perimeter, and auditsrv-bastion-01for any additional accounts compromised in the same window. - Detection: Sigma-style rule:
title: SSH Credential Stuffing Followed by Successful Login→selection1: sourcetype=auth "Failed password" | stats count, dc(user) by src_ip 5m | where count>50 AND dc(user)>20selection2: sourcetype=auth "Accepted password" src_ip=selection1.src_ip within 10m→condition: selection1 and selection2. - Pro Tip: Enforce SSH key-based authentication with password authentication disabled (
PasswordAuthentication no) on all internet-facing bastion hosts - this single configuration change eliminates the entire credential-stuffing attack class regardless of password strength, reuse, or breach-corpus sophistication, and should be paired withfail2ban/rate-limiting for defense in depth on any host where password auth cannot yet be fully retired.
Hypothesis confirmed - a reputation-flagged IP conducted a credential-stuffing attack against 214 usernames on an internet-facing bastion host, successfully compromising the j.reyes account through password reuse and immediately beginning post-compromise reconnaissance!