Parsing auth logs & thresholds
Spot brute-force attempts
Lesson 16 of 20 · 11 min · Module 5: Logs and evidence
Attackers try thousands of passwords against SSH servers. Repeated "Failed password" lines from the same address are the evidence.
Start this lesson →Free. No installation: you write and run the code in your browser, and it is checked automatically.
By the end, you’ll be able to…
- Capture a value with a regex group
- Make part of a pattern optional
- Apply a threshold to counts
The idea
A typical line: sshd[812]: Failed password for root from 203.0.113.9 port 50122 ssh2. A regular expression with a group can capture the address after from. Count per address, then keep those at or above a threshold.
import re
pattern = re.compile(r"Failed password for (?:invalid user )?\S+ from (\S+)")
print(pattern.search("Failed password for root from 203.0.113.9 port 5 ssh2").group(1))
01Capture what you need
Parentheses create a group, and match.group(1) returns its text. \S+ means "one or more non-space characters", which fits both IPv4 and IPv6 addresses.
02Optional phrases
(?: … )? groups text without capturing it and makes it optional. One pattern now matches both "for root" and "for invalid user oracle".
import re
print(bool(re.search(r"for (?:invalid user )?\S+ from", "for invalid user test from")))True03A threshold reduces noise
A single typo is not an attack. Requiring several failures from one address keeps the list short and meaningful.
Your turn
suspicious_ips(log_text, threshold) that returns a sorted list of addresses with at least threshold failed password attempts. Lines may say for invalid user NAME. Ignore successful logins.What the checks look for
- Finds an address over the threshold
- Handles invalid users and sorts the result
- Ignores successful logins
- Works with IPv6 sources
Take this with you
Capture the source, count per source, and flag only repeated failures.
Go a little further
Also return the user names each suspicious address tried.