Перейти к основному содержанию
Блог

Серверы

Логи и реагирование на инциденты: основы для небольшой команды

Что логировать, сколько хранить, централизация логов, оповещения и что делать в первый час инцидента. Практическое руководство по сохранению доказательств.

· 10 мин. чтения

Фото: The U.S. Army, Public domain · Wikimedia Commons

В небольшой команде нет отдельного отдела безопасности: разработчик, администратор сервера и тот, кто реагирует на инцидент, — часто одни и те же люди. Поэтому, когда что-то случается, больше всего времени уходит на поиск ответа на вопрос «что произошло?». Если логов нет, они хранились недолго или злоумышленник их удалил, ответа может и не найтись.

В этой статье разберём, что логировать, как хранить логи, когда отправлять оповещения и как действовать в первый час инцидента. Цель — не большой SOC, а минимальный порядок, который небольшая команда действительно способна выполнять.

В чём проблема

Обычно с логами ситуация такая:

  • логи веб-сервера и приложения есть, но их никто не читает;
  • важные события (вход, смена пароля, изменение роли) вообще не записываются;
  • логи через несколько дней удаляются при ротации;
  • логи лежат только на том же сервере — при взломе злоумышленник может их изменить или удалить;
  • и наоборот, в логи попадают пароли, токены и персональные данные.

Последний случай тоже опасен: файл лога сам становится источником утечки.

Почему это важно для экспертизы

В OWASP Top 10 (2021) есть отдельная категория: A09 «Security Logging and Monitoring Failures». OWASP ASVS также содержит требования к логированию событий безопасности, отсутствию секретов в логах и защите логов. На экспертизе это видно с двух сторон:

  1. Раскрытие информации. Доступные снаружи файлы storage/logs/laravel.log, error_log или debug.log, stack trace на страницах ошибок — всё это записывается как находки. Подробнее: debug-режим и раскрытие информации.
  2. Отсутствие мониторинга. Если попытки подбора пароля и несанкционированного доступа не обнаруживаются и не фиксируются, атака остаётся незамеченной.

Принцип: лог — единственный свидетель, который отвечает на вопросы после инцидента. Он должен быть полным, защищённым и чистым от секретов.

Что логировать

На уровне приложения

В каждой записи как минимум: время (в UTC или с явным часовым поясом), идентификатор пользователя, IP-адрес, тип события, результат (успех или нет), идентификатор запроса.

События, которые нужно логировать:

  • успешные и неуспешные входы, выход, блокировка;
  • смена пароля, email, номера телефона, сброс пароля;
  • изменение ролей и прав, добавление нового администратора;
  • запросы с отказом в доступе (403) — особенно попытки обратиться к объектам других пользователей;
  • важные бизнес-операции: оплата, подписание документа, экспорт данных;
  • многократные ошибки валидации и CSRF.

Что не логировать

Пароли, токены, идентификаторы сессий, полные номера карт, одноразовые коды, полный текст персональных данных. Запись тела запроса целиком часто приводит к попаданию таких данных в лог.

На уровне сервера

  • журналы доступа и ошибок веб-сервера (nginx access.log, error.log);
  • ошибки PHP-FPM и приложения;
  • входы по SSH (/var/log/auth.log или journalctl -u ssh);
  • входы в панель управления;
  • соединения, отклонённые firewall;
  • установка пакетов и системные изменения.

Примеры для Laravel и Node

В Laravel удобно завести отдельный канал для событий безопасности (config/logging.php):

'security' => [
    'driver' => 'daily',
    'path' => storage_path('logs/security.log'),
    'level' => 'info',
    'days' => 90,
],

Прослушивание событий входа:

Event::listen(\Illuminate\Auth\Events\Failed::class, function ($e) {
    Log::channel('security')->warning('login.failed', [
        'login' => $e->credentials['email'] ?? null,
        'ip' => request()->ip(),
        'ua' => substr((string) request()->userAgent(), 0, 200),
    ]);
});

Обратите внимание: записывается только логин, а не весь массив credentials — пароль в лог не попадает.

Пример для Node.js (pino) с автоматическим скрытием секретных полей:

const logger = require('pino')({
  redact: ['req.headers.authorization', 'req.headers.cookie', '*.password', '*.token'],
});
logger.info({ userId: user.id, ip: req.ip, event: 'login.success' });

Структурированные (JSON) логи значительно упрощают последующий поиск и анализ.

Проверьте сами

Убедитесь, что логи не открываются снаружи (только на своём сайте):

for p in storage/logs/laravel.log error_log debug.log wp-content/debug.log logs/error.log; do
  printf "%s " "$p"; curl -s -o /dev/null -w "%{http_code}\n" "https://example.uz/$p"
done

Поищите секреты в логах:

grep -riE "password|passwd|authorization: bearer|api_key|secret" /var/www/app/storage/logs | head

Посмотрите, сколько хранятся логи: настройки в /etc/logrotate.d/ и journalctl --disk-usage. И простой вопрос: сможете ли вы за пять минут выяснить, кто входил в панель администратора вчера в 03:00?

Срок хранения и защита

Срок хранения зависит от требований организации, но практичный вариант для небольшой команды: минимум несколько недель для быстрого поиска и несколько месяцев в архиве. Для некоторых отраслей могут действовать нормативные требования — уточните их у своего юриста.

Пример logrotate для логов nginx:

/var/log/nginx/*.log {
    daily
    rotate 90
    compress
    delaycompress
    missingok
    notifempty
    create 0640 www-data adm
    sharedscripts
    postrotate
        [ -f /run/nginx.pid ] && kill -USR1 $(cat /run/nginx.pid)
    endscript
}

Файлы логов должны быть доступны для чтения только нужным пользователям (0640) и лежать вне веб-каталога.

Централизация логов

Если логи есть только на самом сервере, взломщик может стереть следы. Поэтому логи нужно в реальном времени отправлять в другое место. Варианты для небольшой команды:

  • отправка на отдельный лог-сервер через rsyslog:
# /etc/rsyslog.d/90-remote.conf
*.* @@logs.internal.example:514
  • лёгкие решения вроде Grafana Loki + Promtail или Vector;
  • сервис логов облачного провайдера.

Важно: основной сервер должен иметь возможность только писать на лог-сервер, но не удалять. Синхронизируйте время сервера через NTP (timedatectl, chrony) — иначе события из разных источников невозможно сопоставить.

Оповещения

Оповещать обо всём — то же самое, что не оповещать ни о чём: команда быстро перестаёт обращать внимание. Начните с немногих, но точных правил:

  • много неудачных входов с одного IP или в один аккаунт за короткое время;
  • добавление нового администратора или изменение роли;
  • вход в панель администратора из новой страны или с неизвестного IP;
  • резкий рост ошибок 5xx;
  • появление нового файла .php в веб-каталоге (особенно внутри uploads);
  • неудачное завершение резервного копирования.

Оповещения должны идти в один канал (группа в Telegram, email), и все должны знать, кто дежурит. Для SSH fail2ban автоматически блокирует повторные попытки.

Первый час инцидента

Обнаружен признак инцидента: незнакомый администратор, странный файл, неожиданные запросы в логах. Самая частая ошибка — второпях выключить сервер или удалить файлы: доказательства теряются. Примерный порядок:

  1. Фиксируйте. Кто, когда и что увидел — записывайте со временем. Это станет основой отчёта.
  2. Сохраните доказательства. Скопируйте логи, подозрительные файлы и конфигурацию в другое место и запишите хеши:
tar -czf /root/ir/evidence_$(date +%F_%H%M).tar.gz /var/log/nginx /var/www/app/storage/logs
sha256sum /root/ir/evidence_*.tar.gz > /root/ir/evidence.sha256
ps auxf > /root/ir/processes.txt
ss -tunap > /root/ir/connections.txt
find /var/www -type f -mtime -7 -printf "%TY-%Tm-%Td %TH:%TM %p\n" | sort > /root/ir/recent_files.txt
  1. Ограничьте, но не уничтожайте. Заблокируйте подозрительный аккаунт, закройте путь к бэкдору на уровне веб-сервера, при необходимости переведите сайт в режим обслуживания. Подозрительные файлы не удаляйте — перенесите в карантин.
  2. Смените ключи. Пароль базы данных, API-токены и секреты приложения, пароли администраторов — меняйте их из чистой среды.
  3. Найдите точку входа. Необновлённый плагин, уязвимая библиотека, утёкший пароль? Пока точка входа не закрыта, очистка будет временной.
  4. Сообщите. Руководству, при необходимости клиентам и уполномоченным органам. Для государственных систем и серьёзных инцидентов может требоваться уведомление национального центра кибербезопасности.

Реальный пример можно посмотреть в статье разбор бэкдора в WordPress: там сначала были сохранены доказательства, затем вредоносные файлы помещены в карантин, а файлы ядра сверены с официальными контрольными суммами.

Короткий чек-лист

  • Логируются входы, смена пароля, изменения ролей и события 403
  • В логах нет паролей, токенов и полных персональных данных
  • Файлы логов лежат вне веб-каталога и не открываются снаружи
  • Определён срок хранения, настроен logrotate
  • Логи в реальном времени отправляются в другое место
  • Время сервера синхронизировано через NTP
  • Есть несколько точных правил оповещения и дежурный
  • Порядок реагирования на инциденты записан, команды для сбора доказательств готовы

Итог

Хорошая система логирования не предотвращает инцидент, но позволяет быстро его заметить и правильно отреагировать. В нашем процессе Claude AI агент просматривает точки логирования в коде приложения, конфигурацию логов и секреты, попадающие в логи, а специалист настраивает хранение, централизацию и правила оповещений.

Если хотите проверить, готовы ли ваши логи и порядок реагирования к экспертизе, оставьте заявку на сканирование. Мы поможем закрыть уязвимости до официальной проверки.