Логирование безопасности

Логирование безопасности — запись событий аутентификации, авторизации, изменений данных и аномалий с достаточным контекстом для обнаружения инцидентов, их расследования и соответствия регуляторным требованиям (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 и защищён от модификации

Связанные темы

Ресурсы