Project · Cyber Security: from zero to SOC analyst
Project: catch a password-guessing attack
The brief
An engineering college's lab server is open to SSH from the internet. Its log shows a burst of failed logins. You write a Python detector that parses the log, counts failures per address, flags the attackers, and finds the one login that worked. Then you read the same kind of log on your own Linux VM.
Why it matters
Brute-force and password-spraying attacks on SSH, RDP and web logins never stop. Finding them in authentication logs is one of the first jobs a SOC analyst does, and "many failures, then a success" is a classic SIEM rule. Doing it in Python teaches you what the SIEM is doing for you.
Skills you practise
- reading Linux authentication logs
- regular expressions
- counting with dictionaries
- thresholds and false positives
- CIDR checks
You need
- For the last step: your own Linux VM (Rocky, AlmaLinux, RHEL, Ubuntu or Kali) with SSH running
What you will have at the end
detect.py, a tested brute-force detector that names the attacking addresses and the compromised account, plus real log lines from your own VM and a short list of fixes.
How it is marked (rubric, 100 points)
| Detector worksEvery check passes: parsing, counts, suspects, outside addresses and the break-in. | 45 |
|---|---|
| Analyst judgementYou can explain the threshold you chose and why "failures then success" is the most urgent alert. | 25 |
| Real log evidenceReal failed-login lines from your own VM are pasted. | 15 |
| FixesYou name concrete fixes: lock and reset asha, keys-only SSH, fail2ban or firewall rules, and MFA. | 15 |
0/6 steps done
Step 1 of 6
Parse one log line
parse_line(line) pulls out the result, the user name and the IP address from an sshd line, and returns None for other lines.
Every sshd login line says "Failed password" or "Accepted password", then "for <user> from <ip> port <n>". Failed logins for accounts that do not exist add "invalid user" before the name. A regular expression with groups captures the three parts.
The pattern is given in the solution style: (Failed|Accepted) password for (?:invalid user )?(\S+) from (\S+) port. \S+ means "one or more characters that are not spaces". Lines from other programs, such as CRON, must return None.
Run shows what your code prints. Check runs the step's tests. Ctrl+Enter checks too.