Cyberlium

Python › Module 3 › Lesson 4

BeginnerModule 3Lesson 4/5

Lab — Build a Log Analyzer

Build a small analyzer that summarizes failed auth lines from a sample log file

25 min+21 XP3 quiz
Module progress4 of 5

Opening

Lab: count failures, rank IPs with Counter, lock the files — still YOUR fictional sample_auth.log, still not a hunt.

Lesson 3 taught the loop: open a copy you created, test Failed password, increment. This lab adds memory. collections.Counter maps each source IP to how many times it failed. most_common() prints a mini report: unique talkers, then the ranked list. That is the shape of a SOC one-pager without a SIEM. You will write log_analyzer.py in $HOME/cyberlium-lab, point it at sample_auth.log you own (create or reuse the fiction from last lesson), and chmod 600 the log, the script, and the notes. Scope is the folder you control. You will not scp production auth.log. You will not scan the IPs you extract. You will not WHOIS or deanonymize. You will not feed usernames into Hydra. Documentation addresses in the sample are labels. Regex here is a small extractor for from 1.2.3.4 — Module 4 will slow down on re.compile; for this lab, copy the pattern, do not turn it into a people-finder. Next lesson is the module quiz, then regex on the same kind of sample lines.

1. What the analyzer actually does: filter, extract, tally — then stop

The control flow is four gates. (1) Open the path you set, encoding utf-8, errors ignore, as a context manager. (2) Skip any line that does not contain Failed password — substring first, same as lesson 3, so Accepted lines never enter the tally. (3) Search that line for an IPv4 after the word from using a compiled pattern. If there is no match, skip; do not crash. (4) fails[ip] += 1 on a Counter. After the file ends, print how many unique IPs and each pair from most_common(). That is the product: a summary a human reads. There is no fifth gate that connects to the IP, locks an account, or writes a firewall rule. If you add that fifth gate, you left the lab.

Counter is a dict that defaults missing keys to zero. fails.most_common() sorts by count descending. fails.most_common(3) would be a top-three if you extend later — not required. len(fails) is unique sources that had at least one extracted IP on a failure line. A line can fail the substring and never reach regex. A line can match Failed password but lack a dotted quad (broken fiction you wrote); that line increments nothing in the IP map. That is fine. Do not “fix” missing IPs by scanning the network to see who is up. Write a better sample line instead.

2. The sample file is evidence you invented: chmod 600, no production, no people-finding

$HOME/cyberlium-lab/sample_auth.log must exist before the script runs. If you skipped lesson 3’s file, the lab block recreates a short fiction with 203.0.113.10 repeating (spray-shaped) and 198.51.100.8 appearing twice. Those repeats exist so Counter has something to rank. They are not a hint to attack 203.0.113.10. RFC 5737 TEST-NET addresses are reserved for documentation. Treating them as a botnet is how learners confuse a lab with a manhunt. chmod 600 on the log, analyzer, and notes so another account on a shared PC does not read even your fiction next to other lab secrets. Windows without chmod: WSL, Git Bash, or NTFS restrict in your profile — same as Topics 1–6.

Authorization reminder: if a future job gives you an export, you parse the export you were given, you do not pull more from production “to enrich,” and you do not take it home into this folder. This lab is not that job. Empty output because you pointed the script at the wrong path is a path bug. Empty output because you used a live system file you should not have opened is an ethics bug. Fix the first. Never “fix” the second by copying prod.

3. Wrong vs right: turning ranks into a scan vs a locked summary of YOUR fiction

Worked failure — Counter output is a report, not a target list. Right never includes scraping prod or spraying extracted users.

  • Wrong

    Replace the sample with /var/log/auth.log from work. nmap or Module 2’s scanner against every IP most_common() printed. Hydra the usernames. Gist the full log. chmod 644 on a shared machine. Geo-locate and message strangers. Add requests to “check if the attacker is still up.” Claim the log line was consent. This course forbids all of that.

  • Right

    Create or reuse fictional sample_auth.log in $HOME/cyberlium-lab. Run log_analyzer.py. Record unique IP count and the ranked table in analyzer-notes.txt. chmod 600 log, script, and notes. Stop. Next is Quiz — Automation, then regex on sample lines you still own.

4. Hands-on: sample, analyzer, notes — copy these blocks, fill the counts yourself

Work top to bottom in cyberlium-lab. Recreate the log if needed so paths match. Run python3 log_analyzer.py (or python). Fill the notes with YOUR numbers, not a screenshot of someone else’s gist. Do not add live IPs because the ranking felt short. The regex is a teaching extractor; Module 4 explains groups. Do not “improve” it into an email harvester or a phone-number scraper aimed at real people.

Command guide

Fictional sample_auth.log — YOU create, documentation IPs only

FICTIONAL. Do NOT replace with production logs. Do NOT scan, WHOIS-harass, or Hydra anything you extract.

Command — copy this

mkdir -p "$HOME/cyberlium-lab"
cd "$HOME/cyberlium-lab"

Command — copy this

cat > sample_auth.log << 'LOG'
sshd: Failed password for root from 203.0.113.10 port 44022
sshd: Accepted password for alice from 192.0.2.10 port 51111
sshd: Failed password for admin from 203.0.113.10 port 44023
sshd: Failed password for root from 198.51.100.8 port 51234
sshd: Failed password for root from 203.0.113.10 port 44024
sshd: Accepted password for alice from 192.0.2.10 port 51112
sshd: Failed password for ubuntu from 198.51.100.8 port 51235
sshd: Failed password for root from 203.0.113.10 port 44025
sshd: Failed password for guest from 192.0.2.55 port 22022
sshd: Failed password for root from 203.0.113.10 port 44026
LOG

Command guide

log_analyzer.py — count failures and Counter IPs on YOUR sample

Command — copy this

cat > log_analyzer.py << 'PY'
import re
from collections import Counter

path = "sample_auth.log"
# Teaching extractor for this lab. Module 4 covers re.compile in depth.
# IPv4 here is a label in YOUR fiction — not a person to deanonymize.
ip_re = re.compile(r"from (\d+\.\d+\.\d+\.\d+)")
fails = Counter()
failure_lines = 0

with open(path, encoding="utf-8", errors="ignore") as f:
    for line in f:
        if "Failed password" not in line:
            continue
        failure_lines += 1
        m = ip_re.search(line)
        if m:
            fails[m.group(1)] += 1

print("failure_lines:", failure_lines)
print("unique_source_ips:", len(fails))
for ip, n in fails.most_common():
    print(f"{ip:16} {n}")
PY

Command — copy this

python3 log_analyzer.py

Optional command

python log_analyzer.py

Command guide

analyzer-notes.txt — YOUR counts, then chmod 600

Command — copy this

NOTES="$HOME/cyberlium-lab/analyzer-notes.txt"
{
  echo "=== LOG ANALYZER LAB ==="
  echo "path: $HOME/cyberlium-lab/sample_auth.log (fictional, I created it)"
  echo "failure_lines:"
  echo "unique_source_ips:"
  echo "ranked_table:"
  echo "  (paste python output — documentation IPs only)"
  echo "ethics: no production scrape; no scan/WHOIS of IPs; no Hydra on usernames"
  echo "stop_after: report written — no connect() to extracted addresses"
} > "$NOTES"

Command — copy this

chmod 600 "$HOME/cyberlium-lab/sample_auth.log" \
          "$HOME/cyberlium-lab/log_analyzer.py" \
          "$NOTES"

Windows without chmod: WSL/Git Bash, or restrict the files in your profile.

NEVER: scp prod auth.log into this folder NEVER: nmap $(awk '{print $1}' from the ranked table) NEVER: git add sample_auth.log if you ever mixed in real user lines

Mission: analyzer report + chmod 600 on log, script, and notes

Create or reuse fictional sample_auth.log in $HOME/cyberlium-lab. Run log_analyzer.py so you get a failure line count, a unique-IP count, and a Counter ranking. Save that summary to analyzer-notes.txt. chmod 600 the log, the script, and the notes. Do not scrape production. Do not scan or deanonymize extracted IPs. Do not spray usernames.

Stuck? Ask Cyberlium AI Mentor

If Counter versus a plain int still blurs, or if the ranked IPs feel like “targets,” ask for a hint — not a scanner. Try: "Hint only: why does Failed password filter first, why does Counter rank MY documentation IPs, and why must I chmod 600 instead of nmap the top talker?" You still fill analyzer-notes.txt. No Hydra, no prod logs, no people-finding.

You built the mini report: failure lines, unique sources, ranked IPs — on fiction you own, files mode 600, no fifth gate that connects. Counter is a tally, not a warrant. Next — Quiz — Automation — ten APPLY items on toil versus attacks, secrets versus random, parsers versus scrapes, then Module 4 opens with regex on sample lines.

Knowledge Check

1

APPLY: log_analyzer.py prints 203.0.113.10 with the highest Counter value. What did Counter do, and what do you not do?

Multiple choice

Knowledge Check

2

APPLY: True or False: chmod 600 on sample_auth.log, log_analyzer.py, and analyzer-notes.txt is appropriate because even a teaching log and your counts should not be world-readable on a shared PC, and the files must not become a dump of real user logs.

True or False

Knowledge Check

3

APPLY: A line has Failed password but the regex finds no IP. Another line is Accepted password from 192.0.2.10. Correct analyzer behavior?

Multiple choice

← Previous

Answer all 3 knowledge checks to continue. (0/3 answered)