Security Logging and Monitoring

Advanced
12 min

Security Logging and Monitoring

Most breaches are discovered by someone outside the company, months after they began. OWASP's "Security Logging and Monitoring Failures" (A09) is on the list because the attacks in the earlier lessons all leave traces, and those traces are worthless if nobody records them, nobody can search them, or nobody is alerted when they appear.

In this lesson you will learn which events a security log must contain, how to structure logs so they are searchable and safe, how to keep secrets and injected text out of them, and how to turn logs into alerts and an audit trail you can rely on during an incident.

What to Log

The goal is to answer "who did what, to which resource, from where, and did it succeed" for every security-relevant action:

| Event category | Examples | Must include | |---|---|---| | Authentication | Login success and failure, logout, MFA enrolment, password reset | User identifier, IP, outcome | | Authorization | 403 responses, attempts to access another tenant's data | User, resource ID, route | | Input validation | Schema rejections, blocked file uploads, CSP reports | Field or rule, request ID | | Administrative | Role changes, config changes, data exports, user deletions | Actor, target, before and after values | | High-value transactions | Payments, refunds, API key creation | Amount or scope, actor, request ID |

Log failures as carefully as successes; a burst of 403 responses from one account is the clearest signal of probing you will get.

Structure Logs and Correlate Requests

Free-text log lines are hard to search and impossible to alert on reliably. Emit one JSON object per event with consistent field names, and attach a request ID to every line so a single request can be traced across services. The sample code does both with pino; the output looks like:

json
{"level":30,"time":1760000000000,"service":"shop-api","requestId":"5d2c…","ip":"203.0.113.9","event":"auth.login","outcome":"failure","email":"ada@example.com"}

Send the request ID back in a response header so support tickets can be matched to log lines, and forward it to downstream services in the same header.

Keep Secrets and Injection Out

Two things must never reach the log store: secrets and attacker-controlled formatting.

  • Redaction. Configure the logger to censor known secret paths (authorization and cookie headers, password, token, card numbers). Never log full request bodies by default.
  • Log injection. If user input containing newlines is written to a text log, an attacker can forge entire log entries. Structured JSON logging escapes newlines automatically; if you write plain text anywhere, strip \r and \n first.
  • Personal data minimisation. Log identifiers (user ID) rather than profiles (name, address), and set retention so personal data is not kept longer than necessary.
javascript
const safe = (s) => String(s).replace(/[\r\n]/g, " ").slice(0, 200);
javascript
fs.appendFileSync("audit.txt", `${new Date().toISOString()} login ${safe(req.body.email)}\n`);

From Logs to Alerts

A log nobody reads is a compliance artefact, not a control. Ship logs to a central system (a SIEM or a hosted log platform), then define alerts on the patterns that matter:

  • More than N failed logins for one account or from one IP in 10 minutes.
  • Any 403 spike, especially sequential IDs in the failing requests.
  • A new administrator, a disabled MFA, or a large data export outside business hours.
  • Errors from the signature check on webhooks, or CSP violation reports rising suddenly.

Route alerts to a channel someone actually watches, and test them by triggering each condition deliberately. Keep logs for at least 90 days (longer where regulation requires) in a separate account or system the application cannot modify, so an attacker who gains application access cannot erase their footprints. When an incident happens, "when did it start, which accounts, what was touched" are all answered from these logs filtered by request ID, user ID and time window.

Quick Quiz
Question 1 of 2

Why is structured JSON logging preferred over free-text lines for security events?

Key Takeaways

  • Log authentication, authorization, validation, administrative and high-value events with who, what, where and outcome.
  • Emit structured JSON with a request ID on every line and echo it in the response header.
  • Redact secrets at the logger, escape or strip newlines, and minimise personal data.
  • Centralise logs, alert on failed-login and 403 patterns, and store logs where the application cannot alter them.
  • Good logs are the raw material of incident response; without them there is nothing to investigate.

Next lesson: Server-Side Request Forgery (SSRF) — when your server is tricked into making requests on the attacker's behalf.

Security Logging and Monitoring - Cyber Security | CodeYourCraft | CodeYourCraft