iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

A09 Logging / Monitoring

A09 is Security Logging & Monitoring Failures. You can’t respond to what you can’t see. Without auth + admin + data-access logs, a breach has no detection path and a multi-month dwell time.

Structured logs + immutable storage + SIEM hooks

EXAMPLE
# 1) STRUCTURED logs (JSON) so SIEMs and grep both work
import json, logging, sys, time

logger = logging.getLogger('app')
handler = logging.StreamHandler(sys.stdout)
handler.setFormatter(logging.Formatter('%(message)s'))
logger.addHandler(handler)
logger.setLevel(logging.INFO)

def event(level, event_type, **fields):
    payload = {
        'ts':     int(time.time() * 1000),
        'level':  level,
        'event':  event_type,
        **fields,
    }
    logger.info(json.dumps(payload, default=str))

# Auth events
event('info',  'auth.login.success',  user_id=u.id, ip=request.remote_addr, ua=request.headers.get('User-Agent'))
event('warn',  'auth.login.failed',    email=email,   ip=request.remote_addr, reason='wrong_password')
event('info',  'auth.logout',          user_id=u.id)
event('info',  'auth.password_change', user_id=u.id)
event('info',  'auth.mfa.enabled',      user_id=u.id)

# Authorisation failures (denied attempts → high-signal)
event('warn',  'authz.denied', user_id=u.id, target=resource, action=action)

# Admin / sensitive data
event('info',  'admin.user.role_changed', actor=admin.id, target=u.id, from='member', to='admin')
event('info',  'data.export',              actor=u.id, rows=42, dataset='users')

# Anything you'd want to investigate later
event('error', 'integration.stripe.timeout', request_id=rid, took_ms=5210)

# 2) WHAT TO LOG (NIST 800-92 / OWASP cheat sheet)
#    [ ] All authentication events (success + failure + lockouts)
#    [ ] All authorization failures
#    [ ] Admin actions + role / permission changes
#    [ ] Privileged data exports / bulk reads
#    [ ] Crypto failures (verify, decrypt failed, signature mismatch)
#    [ ] Webhook signature failures
#    [ ] Integration errors > some rate threshold
#    Do NOT log: passwords, tokens, full PAN, full PII bodies

# 3) Ship logs OFF the host
#    - CloudWatch / Datadog / Splunk / ELK / Grafana Loki
#    - Immutable, retention ≥ 90 days (longer for regulated industries)

# 4) Alert on signals
#    - 5 failed logins from one IP in 5 min
#    - any 'authz.denied' on /admin/*
#    - sudden burst of 500s with SQL in the message
#    - 'data.export' outside business hours

# 5) Forward to a SIEM
#    AWS — CloudWatch → Kinesis Firehose → S3 + Athena + EventBridge → Lambda alerts
#    Cloud-agnostic — Vector / Fluent Bit → Loki / Elastic / Splunk

Why it matters

A09 is the OWASP entry that turns “breach” into “known issue.” The same code reviews catch SQLi; only logging catches the credential-stuffing wave the day it starts.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
// A09 Security Logging & Monitoring Failures — you don't know you've been breached.
// Fix: structured logs, immutable retention, alerts on auth/crypto failures, IR runbooks.
Try it Yourself »

Discussion

Loading…