Catch a Brute-Force Attack in the Logs (Free Lab)

MAG212 CYBER · Learn · Blue team · Lab 4

Catch a brute-force attack in the logs.

Every server on the internet gets login attacks. Most are loud and fail. The dangerous one is quiet: a few careful guesses that end in a real login. In this free lesson you read real-format Linux and Windows logs, find both kinds of attack, work out which account was broken into and what the attacker tried next, then write a detection rule so it is caught automatically.

Watch the walkthrough (5 minutes)

Prefer YouTube? Watch on YouTube (English captions and chapters included).

Level: beginner SOC analyst · Time: about 45 minutes · Needs: Python 3.9 or newer on Windows, macOS or Linux.

Two attacks that look alike

Brute forcePassword spraying
What it doesMany passwords against a few accountsOne or two common passwords against many accounts
SpeedFast, often several tries a secondSlow, to stay under lockout limits
MITRE ATT&CKT1110.001 Password guessingT1110.003 Password spraying
The clue in the logsMany failures per accountMany accounts, about one failure each

On Windows, the events to know are 4625 (failed logon), 4624 (successful logon) and 4740 (account locked out). In a 4625 event, SubStatus 0xC000006A means the password was wrong (so the account exists) and 0xC0000064 means the user does not exist.

Get the lab

The lab is a small folder: a Linux SSH log (auth.log), a Windows security log exported to CSV, a read-only Python analyzer, Sigma detection rules, seven exercises and an answer key. There is nothing to install.

Download: mag212-log-lab.zip (26 KB) · unzip it, open a terminal in the folder, and run python3 analyze_logs.py --help (on Windows use py instead of python3).

Safety: every log line is fictional and was generated for teaching, for a made-up company called Nimbus Coffee Co. The IP addresses come from ranges reserved for documentation (RFC 5737), so they belong to nobody. The tools only read files and make no network connections. Practise only on logs you own or are authorised to analyse.

The exercises

1. Get the big picture

python3 analyze_logs.py summary logs/auth.log

Count the failed and successful logins, and notice any denied sudo commands. A denied sudo means someone who was already logged in tried to become root.

2. Who is attacking?

python3 analyze_logs.py top-ips logs/auth.log
grep "Failed password" logs/auth.log | grep -oE "from [0-9.]+" | sort | uniq -c | sort -rn

Compare failures with the number of accounts tried for each address. One address is a brute force; another is a spray. The plain grep version works on any Linux server.

3. Which accounts were targeted?

python3 analyze_logs.py users logs/auth.log

Attackers try default names such as root, admin and ubuntu everywhere. Which ones really exist on this server?

4. Did anyone get in?

grep "Accepted password" logs/auth.log
python3 analyze_logs.py timeline logs/auth.log --ip 192.0.2.77

Separate the normal login (one typo from the office, then success) from the suspicious one, and build a timeline of what happened after it.

5. Windows: the attack that slips through

python3 analyze_logs.py detect logs/windows_security.csv
python3 analyze_logs.py detect logs/windows_security.csv --spray-users 5 --threshold 5

The default rules catch the loud attack that locks out Administrator. Find the quiet one that does not raise an alert, then lower the thresholds and think about the trade-off: more alerts, but also more false alarms.

6. Make it automatic

Open the Sigma rules in detections/ and read how they count events (see the next section).

7. Respond

Write down your first five actions for each compromised account. Then compare your work with ANSWERS.md.

The detection rule

The lab’s rules use Sigma, an open format that many security tools can import or convert. A base rule matches Windows event 4625, and two correlation rules build on it:

  • Brute force: 10 or more failures from one IP address in 5 minutes (event_count).
  • Spraying: 5 or more different accounts from one IP address in 60 minutes (value_count).
title: Password Spraying - Many Accounts From One Source (Lab 4)
correlation:
    type: value_count
    rules:
        - mag212_win_failed_logon
    group-by:
        - IpAddress
    timespan: 60m
    condition:
        field: TargetUserName
        gte: 5
level: high

With pySigma and its Splunk backend, the same rule converts into a Splunk search. The README shows the one-line command. The most valuable alert of all is success after failures: an address with several recent failures that then logs in.

Respond and prevent

  1. Disable the compromised accounts, reset their passwords and end active sessions.
  2. Block the attacking addresses at the firewall.
  3. Preserve the evidence: copy the logs and note the times.
  4. Check what the accounts touched: shell history, new files, scheduled tasks, new SSH keys, outbound connections.
  5. Look for the same addresses on other systems and tell your incident response lead.

Prevention: on Linux, use SSH keys and turn off password logins (PasswordAuthentication no, PermitRootLogin no). On Windows, never expose Remote Desktop directly to the internet, and remove unused accounts such as old interns. Everywhere: multi-factor authentication, banned-password lists, central logging and an alert on success after failures.

Check yourself

Try to answer from the lab output first, then open each answer.

1. One address made 412 failed logins against 3 accounts. Brute force or spraying?

Brute force: many failures per account, fast.

2. Which address got into the Linux server, and as which user?

192.0.2.77, as jsmith, at 13:54:18, after 17 failed attempts against other accounts.

3. What did the attacker try right after logging in?

sudo /usr/bin/bash and then reading /etc/shadow (the password hashes). Both were denied, because jsmith is not an administrator.

4. Why did the default rules miss the Windows attack from 198.51.100.199?

It made only 7 failures against 7 accounts, below the default thresholds (10 failures, 8 accounts), then logged in over Remote Desktop as temp_intern.

5. What does SubStatus 0xC0000064 tell you in event 4625?

The username does not exist. 0xC000006A means the account exists but the password was wrong.

Sources and further reading

More labs: Hands-on Labs · Next steps: SOC & incident response path

Need expert help?

MAG212 CYBER offers network and cybersecurity consultation, penetration testing with MAG212 Atlas, and security seminars for organisations around the world.

Explore our services →