Module B06
Logging sécurisé & Audit
OWASP A09 — ce qu'il faut logger, ce qu'il ne faut jamais logger, détection d'anomalies.
01 OWASP A09 — Security Logging Failures
OWASP A09 (2021) — "Security Logging and Monitoring Failures" — identifie l'absence ou l'insuffisance de logging comme une vulnérabilité critique. Sans logs, il est impossible de détecter une attaque, d'y répondre, et d'en analyser les causes.
| Évènement critique à logger | Informations à inclure |
|---|---|
| Tentative de login échouée | timestamp, IP, user-agent, email/username tentés |
| Login réussi | timestamp, IP, user-agent, userId |
| Changement de mot de passe | timestamp, IP, userId, source (user/admin/reset) |
| Accès refusé (403) | timestamp, IP, URL, userId, raison |
| Erreur de validation JWT | timestamp, IP, erreur, token tronqué |
| Suppression/modification de données sensibles | timestamp, userId, ressource, ancienne valeur |
| Rate limit atteint (429) | timestamp, IP, endpoint, compteur |
02 Ce qu'il ne faut jamais logger
// ❌ JAMAIS logger : logger.info({ password: req.body.password }); // Mot de passe en clair logger.info({ token: req.headers.authorization }); // Bearer token complet logger.info({ card: req.body.cardNumber }); // Numéro de carte logger.info({ ssn: user.socialSecurityNumber }); // Données personnelles sensibles logger.info({ secret: process.env.JWT_SECRET }); // Variables d'env logger.info(`DB connected: ${process.env.DATABASE_URL}`); // URL avec credentials // ✅ Ce qu'on peut logger : logger.info({ userId: user.id, action: 'login', ip: req.ip }); logger.warn({ userId: user.id, action: 'password_change', source: 'user' }); logger.error({ code: err.code, message: err.message }); // Pas le stack trace en prod
⚠️ Masquer les données sensibles dans les logs :
card: '****1234', token: token.substring(0,10) + '...'03 Niveaux de log et structure JSON
const pino = require('pino'); const logger = pino({ level: process.env.LOG_LEVEL || 'info', redact: ['req.headers.authorization', 'req.body.password', '*.creditCard'], // Auto-redact formatters: { level(label) { return { level: label }; } } }); // Log structuré JSON logger.warn({ event: 'auth.login_failed', ip: req.ip, userId: req.body.email, userAgent: req.headers['user-agent'], timestamp: new Date().toISOString(), }, 'Tentative de connexion échouée');
| Niveau | Usage | Exemple |
|---|---|---|
fatal | Crash de l'application | DB inaccessible |
error | Erreur critique non récupérée | Exception non catchée |
warn | Comportement suspect | Login échoué, 429 |
info | Évènements normaux importants | Login réussi, démarrage |
debug | Détails de debug | Dev uniquement |
trace | Trace complète | Diagnostic performance |
04 Détection d'anomalies via les logs
Les logs permettent de détecter des patterns d'attaque en analysant les volumes, fréquences et séquences d'évènements.
// Middleware de sécurité — comptage des échecs const failedLogins = new Map(); app.post('/auth/login', (req, res, next) => { const key = req.ip + ':' + (req.body.email || ''); const attempts = (failedLogins.get(key) || 0) + 1; failedLogins.set(key, attempts); if (attempts >= 5) { logger.warn({ event: 'brute_force_detected', ip: req.ip, attempts, key }, 'Brute force potentiel'); } next(); });
| Pattern | Indicateur | Seuil alerte |
|---|---|---|
| Brute force login | 5+ 401 depuis même IP/email en 15min | → Block IP + alerte |
| Scan de routes | 10+ 404 depuis même IP en 1min | → Rate limit + log |
| Exfiltration | Volume de données > X fois la moyenne | → Alerte SIEM |
| Privilege escalation | Accès ressource admin par user normal | → Alerte immédiate |
| Token abuse | Même token utilisé depuis 2 IPs différentes | → Invalidation token |
05 Log management en production
| Stack | Composants | Usage |
|---|---|---|
| ELK Stack | Elasticsearch + Logstash + Kibana | Analyse, visualisation, alertes |
| Grafana Loki | Loki + Promtail + Grafana | Agrégation légère, corrélation métriques |
| Datadog | Agent Datadog + APM + Logs | SaaS, APM intégré, alertes |
| CloudWatch | AWS CloudWatch Logs + Insights | AWS natif, serverless |
| Splunk | Indexer + Search Head | Enterprise, SIEM |
Rétention et conformité
# Logs de sécurité — conservation minimum recommandée Authentication events: 12 mois (RGPD, PCI-DSS) Access logs: 90 jours Error logs: 30 jours Audit trail: 7 ans (comptabilité, compliance) # Ne jamais purger les logs d'incident avant investigation
💡 Log injection : un attaquant peut injecter des newlines dans ses inputs pour créer de faux logs. Toujours échapper ou encoder les inputs avant de les logger.