Skip to main content

Investigating an SSH brute force in my home lab: 357 failed logins, one stolen account

Updated 9 min readMarkdown
Part of seriesSprint-30
Investigating an SSH brute force in my home lab: 357 failed logins, one stolen account

Structured on the NIST SP 800-61 incident response lifecycle. Own lab: the attack was run on purpose against a throwaway account, then investigated from the logs as if it were a real alert.

Field Value
Case ID IR-2026-001
Analyst 0x8R41NR07
Date of incident 2026-11-10
Source Own lab (Proxmox): Ubuntu server dockers 10.10.10.30, Wazuh 4.14.8
Data auth.log from dockers, last / lastb output, Wazuh alert export (CSV, 1,385 alerts)
Tools used grep, cut, sort, uniq, last/lastb, a small Python CSV counter, Wazuh dashboard
Classification Credential access via SSH password guessing, followed by a valid-account login

1. Executive summary

On 10 November 2026 between 10:19 and 11:01 UTC, a single source (10.10.10.2) made 357 failed SSH password attempts against the account labtest on the server dockers, in two automated runs. Both runs guessed the correct password, and the attacker used it for an interactive 44-second login at 10:26 UTC; no privilege escalation, new accounts or persistence were found, but the commands run during that session could not be seen because the server doesn't log them. Wazuh flagged the brute force within seconds (rules 5763, 40112 and the custom rule 100105), but the follow-up interactive login only produced low-level "login success" events that nobody would review. Recommended: reset and lock the account, block the source, switch SSH to key-only authentication, and add an alert for a successful login from an IP that just triggered a brute-force alert.

2. Scenario

Alert: "Possible SSH brute force on dockers". Questions to answer:

  1. When did the activity start and end?
  2. From which IP?
  3. How many attempts, against which usernames?
  4. Did it succeed? Which account, when?
  5. What happened after the successful login?
  6. What did the SIEM detect, and how fast?
Hydra finds the (blurred) lab password

3. Timeline of events (UTC, 2026-11-10)

Time Source Event ATT&CK
10:14:42 auth.log Account labtest created by admin brainrot (lab setup, before the attack) –
10:19:37 auth.log First failed password for labtest from 10.10.10.2 (run 1) T1110.001
10:19 Wazuh First brute-force alerts within seconds: 5551, 5763 (level 10) –
10:21:42 auth.log Accepted password for labtest from 10.10.10.2; session closed after ~1 s (the tool verifying the password) T1110.001
10:21 Wazuh 40112 Multiple authentication failures followed by a success (level 12) –
10:26:14 auth.log Interactive login as labtest from 10.10.10.2 T1078
10:26:58 auth.log labtest disconnects (session length 44 s) –
10:59 auth.log Second run starts: same source, same account T1110.001
10:59 Wazuh Custom rule 100105 fires (46 alerts during run 2) –
11:01:19 auth.log Accepted password for labtest (run 2), closed after ~1 s T1110.001
11:07:58 – 11:08:12 auth.log One failed password, then a login as labtest (false-positive test, not the attacker) –
11:19 – 11:31 auth.log Analyst logins and sudo for evidence collection –

Times come from auth.log on dockers. The Wazuh dashboard shows local time (CET, UTC+1), and its timestamps differ from the server's log times by ~15 s because the two machines' clocks aren't perfectly synced.

4. Analysis

4.1 Initial access

Evidence: 357 lines Failed password for labtest from 10.10.10.2, then:

2026-11-10T10:21:42.982610+00:00 docker sshd[11808]: Accepted password for labtest from 10.10.10.2 port 54926 ssh2
  • All 357 failures come from one IP and target one existing account (no invalid user lines). One user, many passwords = password guessing (T1110.001), not spraying.
  • Rate: about 4 attempts every 2–4 seconds. Failures per minute: 10:19 = 32, 10:20 = 84, 10:21 = 63, then a gap, then 10:59 = 70, 11:00 = 80, 11:01 = 27. That's machine speed with ~4 parallel connections, consistent with a tool like Hydra.
  • Success: the password was guessed at 10:21:42 and again at 11:01:19. Each of those sessions closed within a second, which is what a brute-force tool does to confirm a hit.

Source IP note: 10.10.10.2 is the lab's Proxmox host, which NATs traffic from outside the lab network. The attacker's real address is hidden behind it. In production that would point to a NAT / VPN gateway that needs its own logs.

Confidence: High.

4.2 Execution and persistence

Evidence:

2026-11-10T10:26:14.829555+00:00 docker sshd[11913]: Accepted password for labtest from 10.10.10.2 port 40272 ssh2
2026-11-10T10:26:58.739686+00:00 docker sshd[11984]: Disconnected from user labtest 10.10.10.2 port 40272
  • Four and a half minutes after the first successful guess, the same source logged in interactively and stayed 44 seconds: a human using the stolen password (T1078 Valid Accounts).
  • What was typed is unknown. auth.log records logins, sudo and account changes, not commands. This is a visibility gap (see section 8).
  • No persistence found in the available logs: no useradd, usermod, passwd or group changes by labtest, and no further logins by the attacker. SSH keys in ~labtest/.ssh/authorized_keys were not checked; that would be the next step on a real host.

Confidence: High for the login. Low for "nothing else happened", because of the gap.

4.3 Privilege escalation / lateral movement

  • No sudo lines for labtest. The only sudo activity that day is the admin brainrot (account creation before the attack, evidence collection after it). The three failed sudo attempts at 11:21 (Wazuh 5404) were the analyst mistyping, not the attacker.
  • No outbound SSH from dockers in the logs.

Confidence: Medium (based on auth.log only).

4.4 Actions on objective / impact

  • Confirmed impact: the account labtest is compromised (its password is known to the attacker).
  • Unknown: what was read or changed during the 44-second session.
  • last still listed a labtest session from 11:08 as "still logged in" with no matching session closed line. It belongs to the false-positive test, but on a real host any unexplained open session should be checked with who and killed.

5. Indicators of compromise

Type Value Context
IP 10[.]10[.]10[.]2 Source of all 357 failures and of the interactive login (lab NAT gateway, see 4.1)
Account labtest Targeted and compromised account on dockers
Password [REDACTED] Guessed password, from the 200 most common entries of the rockyou wordlist
Behaviour ~4 attempts / 2–4 s, 4 parallel connections, Too many authentication failures disconnects Fingerprint of an automated SSH brute-force tool

6. MITRE ATT&CK summary

Tactic Technique ID
Credential Access Brute Force: Password Guessing T1110.001
Initial Access / Persistence Valid Accounts: Local Accounts T1078.003
Persistence Create Account: Local Account T1136.001 (not observed)

7. Response recommendations (NIST 800-61 phases)

  • Containment: lock labtest (passwd -l labtest) and end its sessions (pkill -u labtest); block 10.10.10.2 at the firewall (in production, find the real source behind the NAT first).
  • Eradication: reset the password; check ~labtest/.ssh/authorized_keys, crontabs and ~labtest/.bash_history for anything the attacker left. Delete the account if it isn't needed (here: it was a test account, deleted on 10 Nov).
  • Recovery: bring the account back only with a strong, unique password or key-based login, and watch it closely for a week.
  • Lessons learned / prevention:
    • Key-only SSH (PasswordAuthentication no): makes password guessing pointless.
    • fail2ban or a similar tool to block an IP after a few failures.
    • Don't expose SSH widely: allow it only from admin networks or through a VPN.
    • A password policy that rejects common passwords. This one was in the top 200 of a public wordlist.
    • Log commands (auditd execve rules, or Sysmon for Linux) so the next investigation can see what was done.

8. Detection opportunities

What fired: the brute force was caught fast and from several angles: 5760 for each failure, 5551 / 5763 / 2502 / 40111 (level 10) within seconds, 40112 (level 12) at each successful guess, and the custom rule 100105 (level 12, 8 failures in 60 s from one IP) in run 2. Detection write-up: 3 Wazuh detections, tested in my home lab (section 3). Rule files: detection-lab.

Built-in Wazuh alerts during the attack

What didn't: the interactive login at 10:26, the moment the attacker actually got in, only produced level-3 events (5715 authentication success, 5501 session opened). Nothing connects them to the brute force minutes earlier. Two improvements:

  1. A correlation rule: successful SSH login from an IP that triggered 100105 or 40112 in the last hour → level 13+.
  2. Command logging (auditd), so the session's contents become visible.

9. Analyst notes

  • Separating myself from the attacker was half the job. My own account creation, evidence collection, a mistyped sudo password and a false-positive test all land in the same log. I marked each one as analyst activity in the timeline before drawing conclusions.
  • sort | uniq -c answered most questions (IPs, usernames, attempts per minute). The gotcha: uniq only merges lines next to each other, so sort has to come first.
  • Use the server's log for times. Dashboard times are local time and the two clocks differ by seconds.
  • The biggest lesson is the gap in 4.2: the logs proved that someone got in, but not what they did. That's the argument for command logging on any server that allows SSH.

About the author

  • 30 years in creative leadership (in the ad industry as a Creative Director) taught me one core skill: dissecting complex systems and finding the flaw before someone else does. My tech roots run back to 8-bit machine code on a C64 (yeah – 80s, baby!) Today, I’m combining that legacy hacker curiosity with modern threat detection and offensive security. BATTLE-TESTED LOGIC: Decades of high-pressure problem solving and systems analysis. HACKER MINDSET: I don't just follow playbooks; I reverse-engineer how the attack path actually works. CONTINOUS SKILL-UP: CompTIA Security+ certified (among other certs), building home labs, and constantly training for L1 ops to future Pentesting.

No comments yet. Be the first to comment.

Sprint-30

Part 3 of 3

30 working days of hands-on security: a home SOC lab, detection engineering, pentesting and Active Directory attack + defence. Everything from my own lab.

Start from the beginningMy InfoSec HomeLabIsolated Security Homelab on Proxmox — Build Guide