Логирование безопасности
Логирование безопасности — запись событий аутентификации, авторизации, изменений данных и аномалий с достаточным контекстом для обнаружения инцидентов, их расследования и соответствия регуляторным требованиям (audit trail).
Зачем нужно
Без логов нельзя обнаружить атаку, расследовать инцидент или ответить регулятору. OWASP A09:2021 "Security Logging Failures" — отдельная позиция в Top 10. 80% взломов обнаруживаются третьими сторонами, а не самими компаниями — часто из-за отсутствия мониторинга логов.
Где используется
- Аутентификация: успешный вход, провал, блокировка аккаунта
- Авторизация: попытки доступа к запрещённым ресурсам
- Административные действия: изменение ролей, удаление данных
- Финансовые операции: транзакции, изменения платёжных данных
Основной контент
Что логировать (security events)
// Успешный и неуспешный вход
logger.info({ event: 'auth.login.success', userId, ip, userAgent, timestamp: new Date });
logger.warn({ event: 'auth.login.failure', email, ip, reason: 'invalid_password' });
// Доступ к запрещённому ресурсу
logger.warn({ event: 'authz.denied', userId, resource: '/admin/users', ip });
// Критические действия
logger.info({ event: 'user.role_changed', actorId, targetUserId, oldRole, newRole });
logger.info({ event: 'user.password_changed', userId, ip });
logger.info({ event: 'data.export', userId, recordCount: 50000 });
Что НЕ логировать (защита PII)
// ПЛОХО — пароль, токены, PII в логах
logger.info({ password: req.body.password });
logger.debug({ authorization: req.headers.authorization }); // Bearer token!
logger.info({ creditCard: '4111-1111-1111-1111' });
// ХОРОШО — маскируем/исключаем
logger.info({ event: 'auth.attempt', email: maskEmail(email), ip });
function maskEmail(email) {
const [user, domain] = email.split('@');
return `${user[0]}***@${domain}`;
}
Структурированные логи с pino
const pino = require('pino');
const logger = pino({
level: process.env.LOG_LEVEL || 'info',
redact: {
paths: ['req.headers.authorization', 'body.password', 'body.token'],
censor: '[REDACTED]',
},
});
// Security event middleware
function logSecurityEvent(event, data) {
logger.info({
event,
timestamp: new Date.toISOString(),
...data,
});
}
// Использование
logSecurityEvent('auth.login.failure', {
email: req.body.email,
ip: req.ip,
attempts: failedAttempts,
});
Мониторинг и алертинг на security события
# Пример alert-правила (условная псевдо-конфигурация Grafana/Loki)
# Алёрт: >10 неудачных логинов с одного IP за 5 минут
sum(rate({app="backend"} |= "auth.login.failure" [5m])) by (ip) > 10
# Алёрт: попытка доступа к /admin без роли admin
{app="backend"} |= "authz.denied" |= "/admin"
Частые ошибки
- Логирование паролей, токенов или PII в plaintext — вторичная утечка через логи
- Логи только в stdout без централизованного хранилища — теряются при рестарте
- Отсутствие временных меток в UTC — трудно коррелировать события
- Нет алертов на security события — логи собираются, но никто не смотрит
- Изменяемые логи — лог должен быть append-only и защищён от модификации
Связанные темы
- _MOC Безопасность
- Incident Response -- план реагирования
- Rate Limiting и DDoS-защита
- Secure SDLC -- безопасный жизненный цикл