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:
- When did the activity start and end?
- From which IP?
- How many attempts, against which usernames?
- Did it succeed? Which account, when?
- What happened after the successful login?
- What did the SIEM detect, and how fast?
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 userlines). 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.logrecords logins,sudoand account changes, not commands. This is a visibility gap (see section 8). - No persistence found in the available logs: no
useradd,usermod,passwdor group changes bylabtest, and no further logins by the attacker. SSH keys in~labtest/.ssh/authorized_keyswere 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
sudolines forlabtest. The onlysudoactivity that day is the adminbrainrot(account creation before the attack, evidence collection after it). The three failedsudoattempts at 11:21 (Wazuh 5404) were the analyst mistyping, not the attacker. - No outbound SSH from
dockersin the logs.
Confidence: Medium (based on auth.log only).
4.4 Actions on objective / impact
- Confirmed impact: the account
labtestis compromised (its password is known to the attacker). - Unknown: what was read or changed during the 44-second session.
laststill listed alabtestsession 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 withwhoand 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_historyfor 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
execverules, or Sysmon for Linux) so the next investigation can see what was done.
- Key-only SSH (
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.
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:
- A correlation rule: successful SSH login from an IP that triggered 100105 or 40112 in the last hour → level 13+.
- 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
sudopassword 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 -canswered most questions (IPs, usernames, attempts per minute). The gotcha:uniqonly merges lines next to each other, sosorthas 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.
Comments
Join the discussionNo comments yet. Be the first to comment.
Sprint-30
30 working days of hands-on security: a home SOC lab, detection engineering, pentesting and Active Directory attack + defence. Everything from my own lab.





