One line per request
A web server writes one line per HTTP request in the combined format: client IP, timestamp, the request line ("GET /path HTTP/1.1"), the status code, the bytes sent, the referrer and the user-agent. Take a look:
head -n 4 /srv/soc-data/web/access.logIn the terminal
student@vulntech:~$ head -n 4 /srv/soc-data/web/access.log 10.10.10.33 - - [10/Mar/2026:07:55:10 +0000] "GET / HTTP/1.1" 200 512 "-" "Mozilla/5.0 (X11; Linux x86_64) Firefox/115.0" 10.10.10.33 - - [10/Mar/2026:07:55:11 +0000] "GET /about HTTP/1.1" 200 552 "-" "Mozilla/5.0 (X11; Linux x86_64) Firefox/115.0" 10.10.10.33 - - [10/Mar/2026:07:55:12 +0000] "GET /products HTTP/1.1" 200 592 "-" "Mozilla/5.0 (X11; Linux x86_64) Firefox/115.0" 10.10.10.33 - - [10/Mar/2026:07:55:13 +0000] "GET /contact HTTP/1.1" 200 632 "-" "Mozilla/5.0 (X11; Linux x86_64) Firefox/115.0"
The status code is the 9th field. 200 is success; 404 is "not found". A normal user hits pages that exist; a scanner blindly requests hundreds of guessed paths and racks up 404s:
awk '$9==404{print $1}' /srv/soc-data/web/access.log | sort | uniq -c | sort -rnIn the terminal
student@vulntech:~$ awk '$9==404{print $1}' /srv/soc-data/web/access.log | sort | uniq -c | sort -rn 8 203.0.113.66
Tip: One IP owning nearly all the
404s is a scanner's signature. Compare it with the attacker IP you already found in the auth log — is it the same actor?