Upptäckt — loggning och övervakning
Observera
Gå tillbaka till din labbmiljö och gör om momenten från Lab 1, 3 och 5 — men titta den här gången i serverns loggar i stället för i webbläsaren:
tail -f /var/log/nginx/access.log
tail -f /var/log/auth.log
Vad koden gör — förklaring rad för rad
Två kommandon som visar loggarna medan de skrivs, så att du ser dina egna försök dyka upp i realtid.
- tail
- Visar slutet av en fil — de senaste raderna.
- -f
- Follow. Fortsätt visa nya rader allteftersom de skrivs, i stället för att avsluta. Avbryt med Ctrl+C.
- /var/log/nginx/access.log
- Webbserverns logg över varje begäran som kommit in.
- /var/log/auth.log
- Systemets logg över inloggningar och behörighetshändelser.
Insikten som ska landa: angreppsförsök ser ut som något i loggarna. Upprepade 401-svar, ovanligt många 404:or i följd, långa eller märkliga parametrar, förfrågningar utan normal User-Agent, åtkomst vid udda tidpunkter.
Analysera
De flesta organisationer loggar tillräckligt men granskar för lite. Skillnaden mellan en incident som upptäcks på några timmar och en som upptäcks efter månader ligger sällan i loggningen i sig, utan i att någon eller något faktiskt tittar.
Bygg försvaret
1. Logga rätt saker. Autentiseringshändelser (både lyckade och misslyckade), behörighetsnekanden, ändringar av konton och roller, administrativa åtgärder, samt fel på serversidan. Varje post bör innehålla tidsstämpel med tidszon, källadress, användaridentitet, åtgärd och resultat.
2. Logga aldrig lösenord, sessionstoken, personnummer eller kortuppgifter. Loggar sprids ofta vidare till system med lägre skyddsnivå.
3. Strukturerad loggning gör det möjligt att söka maskinellt:
logger.info("auth_failure", extra={
"anvandare": anvandarnamn,
"kall_ip": request.META["REMOTE_ADDR"],
"resultat": "nekad",
"orsak": "felaktigt_losenord",
})
Vad koden gör — förklaring rad för rad
Strukturerad loggning i Python. Skillnaden mot en vanlig textrad är att varje uppgift ligger i ett eget namngivet fält, vilket gör loggen sökbar maskinellt.
- logger.info(
- Skriv en loggpost på nivån info. Andra nivåer är bland annat warning och error.
- "auth_failure"
- Ett kort, fast händelsenamn. Samma namn varje gång gör det enkelt att räkna och larma på.
- extra={...}
- De strukturerade fälten. Klammerparenteserna håller en uppsättning nyckel–värde-par.
- "kall_ip": request.META["REMOTE_ADDR"]
- Hämtar avsändarens adress ur anropet och sparar den under ett eget fältnamn.
- "resultat": "nekad"
- Utfallet som eget fält, så att en larmregel kan räkna antalet nekade försök per konto utan att läsa fritext.
4. Centralisera och skrivskydda. Loggar som bara ligger på den komprometterade maskinen kan ändras. Skicka dem vidare till en separat logginsamlare.
5. Skriv larmregler. Börja enkelt och förfina:
- Fler än tio misslyckade inloggningar mot samma konto inom fem minuter.
- Lyckad inloggning från ett land verksamheten inte verkar i.
- Nytt konto som tilldelas administratörsroll.
- Serverfel (5xx) som ökar kraftigt jämfört med normalläget.
6. Bestäm lagringstid i förväg. Trettio dagar räcker sällan för att utreda en incident som upptäcks sent; sex till tolv månader är vanligt, men det styrs också av vilka personuppgifter som finns i loggarna och vad GDPR tillåter.
Verifiera
Testa varje larmregel i labbet genom att framkalla det beteende den ska fånga. En larmregel som aldrig testats är en gissning.
Dokumentera
Skriv en kort "detection runbook": för varje larm, vad betyder det, vilka steg tar man först, och när eskalerar man?
Reflektionsfrågor: Varför är falsklarm ett verkligt problem och inte bara en olägenhet? Hur balanserar man känslighet mot användbarhet?
Kunskapskontroll
Välj ett svar per fråga. Du får återkoppling direkt, och avsnittet markeras som klart när alla frågor är besvarade.
1Var brister de flesta organisationer när det gäller loggning?
2Vilket av följande får aldrig skrivas till en logg?
3Vad är en larmregel som aldrig har testats?
Detection — logging and monitoring
Observe
Go back to your lab and repeat the exercises from Labs 1, 3 and 5 — but this time watch the server logs instead of the browser:
tail -f /var/log/nginx/access.log
tail -f /var/log/auth.log
What this code does — line by line
Two commands showing the logs as they are written, so you watch your own attempts appear in real time.
- tail
- Shows the end of a file — the most recent lines.
- -f
- Follow. Keep showing new lines as they are written, rather than exiting. Stop with Ctrl+C.
- /var/log/nginx/access.log
- The web server's log of every request that came in.
- /var/log/auth.log
- The system's log of logins and authorization events.
The insight to land: attack attempts look like something in the logs. Repeated 401 responses, an unusual run of 404s, long or odd parameters, requests without a normal User-Agent, access at strange hours.
Analyze
Most organizations log enough and review too little. The difference between an incident detected within hours and one detected after months rarely lies in the logging itself, but in whether someone or something is actually looking.
Build the defense
1. Log the right things. Authentication events (both successful and failed), authorization denials, account and role changes, administrative actions, and server-side errors. Each entry should carry a timestamp with timezone, source address, user identity, action and outcome.
2. Never log passwords, session tokens, national ID numbers or card details. Logs frequently get copied onward into systems with weaker protection.
3. Structured logging makes machine search possible:
logger.info("auth_failure", extra={
"user": username,
"source_ip": request.META["REMOTE_ADDR"],
"outcome": "denied",
"reason": "bad_password",
})
What this code does — line by line
Structured logging in Python. The difference from an ordinary line of text is that each detail sits in its own named field, which makes the log searchable by machine.
- logger.info(
- Write a log entry at info level. Other levels include warning and error.
- "auth_failure"
- A short, fixed event name. The same name every time makes it easy to count and alert on.
- extra={...}
- The structured fields. The braces hold a set of key–value pairs.
- "source_ip": request.META["REMOTE_ADDR"]
- Takes the sender's address from the request and stores it under its own field name.
- "outcome": "denied"
- The outcome as its own field, so an alert rule can count denied attempts per account without reading free text.
4. Centralize and make append-only. Logs that live only on the compromised machine can be altered. Ship them to a separate log collector.
5. Write alert rules. Start simple and refine:
- More than ten failed logins against the same account within five minutes.
- A successful login from a country the business does not operate in.
- A new account being granted an administrator role.
- Server errors (5xx) rising sharply against the baseline.
6. Decide retention in advance. Thirty days is rarely enough to investigate an incident discovered late; six to twelve months is common, but this is also governed by what personal data the logs contain and what GDPR permits.
Verify
Test each alert rule in the lab by producing the behavior it is meant to catch. An untested alert rule is a guess.
Document
Write a short detection runbook: for each alert, what does it mean, what are the first steps, and when do you escalate?
Reflection: Why are false positives a real problem rather than just an annoyance? How do you balance sensitivity against usability?
Knowledge check
Pick one answer per question. You get feedback immediately, and the unit is marked complete once every question is answered.
1Where do most organizations fall short on logging?
2Which of the following must never be written to a log?
3What is an alert rule that has never been tested?