Данные подменяли месяц: как найти последнюю чистую копию
Шифровальщик — это заметно: файлы переименованы, на рабочем столе записка с требованием выкупа, сервис лёг. С тихой подменой данных всё наоборот — атакующий месяцами правит записи в базе, подкидывает изменённые файлы, чуть смещает суммы или статусы, и ничего не падает. Обнаруживаете вы это случайно, спустя недели, а к тому моменту ваши ежедневные и еженедельные бэкапы уже переписали друг друга — искажённые данные есть везде, включая архивы. Разберём, как в такой ситуации искать последнюю действительно чистую точку и что должно быть настроено заранее, чтобы это вообще было возможно.
Содержание
Почему это опаснее шифровальщика
Ransomware решает за вас: он делает повреждение мгновенным и очевидным. Вы точно знаете момент компрометации — это момент, когда файлы стали нечитаемыми, — и восстанавливаетесь на бэкап, который был снят до него. Разбор похожего явного сценария есть в статье про шифровальщика, который зашёл по RDP с коротким паролем: там вся сложность в скорости реакции, а не в поиске момента.
Тихая подмена данных устроена ровно наоборот. Атакующий, получив доступ — через украденные учётные данные, уязвимость в приложении или скомпрометированную интеграцию, — не шифрует и не удаляет, а точечно правит: меняет реквизиты получателя в платёжных записях, подкручивает остатки на складе, вставляет бэкдор в конфиг, который выглядит как обычная строка. Каждое отдельное изменение выглядит как легитимная операция пользователя или синхронизация — потому что технически ей и является, просто выполненной не тем, кем должна была.
Обнаружение здесь почти всегда отложенное: расхождение находит бухгалтер при сверке, клиент жалуется на данные, которых не вводил, или мониторинг целостности (если он вообще настроен) выдаёт алерт спустя недели после первой подмены. К моменту обнаружения ваш RPO (recovery point objective) — то, насколько старую копию нужно поднять, чтобы она была чистой, — может исчисляться неделями или месяцами, а не часами, как при ransomware. И если retention бэкапов у вас 7 или 14 дней — чистой копии в архиве может просто не быть физически.
Первый шаг: очертить период компрометации
Прежде чем откатывать что-либо, нужна рабочая гипотеза — когда всё началось. Без этого вы либо откатитесь недостаточно далеко (и восстановите уже подменённые данные), либо слишком далеко (и потеряете недели легитимных изменений без необходимости).
Источники для реконструкции таймлайна:
- Логи аутентификации и доступа —
/var/log/auth.log(Debian/Ubuntu) илиjournalctl -u sshd, логи VPN, логи панели управления CMS/CRM. Ищите нетипичное: вход в нерабочее время, новый IP для существующей учётной записи, успешный вход после серии неудачных попыток. - Логи приложения и веб-сервера — запросы к административным эндпоинтам, необычные User-Agent, паттерны запросов, не похожие на действия обычного пользователя (например, одинаковый интервал между запросами — признак скрипта).
- История изменений на уровне СУБД, если включён аудит: PostgreSQL с расширением
pgaudit, MySQL с General Query Log или Audit Log Plugin, MongoDB сauditLog. Если аудит не был включён заранее — эта дверь для вас закрыта, и это стоит записать как урок на будущее. - Изменения в системе контроля версий, если конфиги и код лежат в git —
git log --all --since="2026-07-01" -- path/to/configпокажет, кто и когда трогал критичные файлы, даже если коммит был замаскирован под рутинное обновление.
Практический пример: если аномалию заметили в конце августа 2026 года, а последний доверенный аудит целостности проходил в начале месяца, разумная стартовая гипотеза — компрометация где-то между этими датами, и именно этот промежуток проверяется в первую очередь, а не весь год бэкапов подряд. Умение восстанавливать хронологию по разрозненным логам пригодится и при разборе самого факта взлома — принцип тот же, только фокус смещается с данных на точку входа.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверСверка контрольных сумм с эталонами
Для файлов (не строк в базе, а именно файлов — конфигов, статических ассетов, бинарников, дистрибутивов) контрольные суммы — самый быстрый способ найти момент изменения, если у вас есть с чем сравнивать.
Если для критичных файлов заранее считался хеш и хранился отдельно (не на том же сервере — иначе атакующий мог подменить и эталон тоже):
sha256sum /etc/nginx/nginx.conf /etc/app/config.yaml > /tmp/current.sha256
diff /tmp/current.sha256 /secure/storage/baseline.sha256
Если отдельного эталона не вели, но система была развёрнута из пакетов дистрибутива — можно свериться с контрольными суммами, которые предоставляет сам пакетный менеджер:
# Debian/Ubuntu — проверка изменённых файлов пакета
dpkg -V nginx
debsums -c
Для непрерывного контроля на будущее стоит развернуть систему мониторинга целостности файлов (FIM) — например, AIDE:
apt install aide
aideinit
# после инициализации базы — периодическая проверка
aide --check
AIDE хранит хеши файловой системы на момент инициализации и на каждой проверке показывает, что изменилось, добавилось или удалилось. Ключевой нюанс: база AIDE и её конфиг должны храниться вне проверяемого сервера (на отдельном read-only носителе или в другой системе), иначе атакующий с root-доступом просто пересчитает эталон под свежее, уже искажённое состояние — и проверка ничего не покажет.
Для данных внутри базы контрольные суммы файлов не помогут — нужны либо построчные хеши на уровне приложения (если они закладывались архитектурно), либо сверка с внешним источником истины: выгрузкой у контрагента, копией у клиента, распечаткой отчёта за нужный период, если она сохранилась вне вашей инфраструктуры.
История изменений: версионирование и аудит-логи
Если в системе есть версионирование или журналирование изменений — это самый надёжный путь найти точный момент подмены, потому что он показывает не просто «что сейчас не так», а «кто, когда и как именно изменил запись».
Для PostgreSQL — WAL-архивирование с возможностью point-in-time recovery позволяет поднять базу на состояние на любую секунду в прошлом, если WAL-файлы архивировались непрерывно и достаточно долго:
# restore_command в postgresql.conf на восстанавливаемом инстансе
restore_command = 'cp /archive/wal/%f %p'
recovery_target_time = '2026-08-14 09:00:00'
Это работает только если архивирование WAL было настроено заранее и архив не пересекается по сроку хранения с моментом компрометации — задним числом WAL не восстановить.
Для MySQL/MariaDB — аналогично работает бинарный лог (binlog) при включённом log_bin, через mysqlbinlog можно вычленить и просмотреть конкретные транзакции за период, не поднимая всю базу целиком.
На уровне приложения — если в схеме БД предусмотрены поля вроде updated_at, updated_by, или отдельная таблица аудита (audit trail), это часто самый быстрый способ: SELECT * FROM orders WHERE updated_at BETWEEN '2026-08-01' AND '2026-08-25' AND updated_by NOT IN (<список ожидаемых сервисных аккаунтов>) — такой запрос за минуты покажет подозрительные правки, если аудит вёлся честно (то есть в отдельной append-only таблице, куда у обычных ролей приложения нет прав на UPDATE/DELETE).
Если аудит-лога не было и версионирования тоже нет — единственный оставшийся путь это ручная бинарная сверка между поколениями бэкапов, которая описана в следующем разделе. Она медленнее и грубее, но работает даже без предварительной подготовки.
Постепенный откат к более старым бэкапам
Когда точной даты нет, работает стратегия бинарного поиска по цепочке бэкапов: не восстанавливать сразу самый старый архив (это может откатить на месяцы легитимных данных), а сужать диапазон шагами.
Общий алгоритм:
- Разверните подозреваемую копию в изолированной песочнице, не в проде — отдельный сервер или контейнер без доступа к боевой сети, чтобы случайно не перезаписать текущие данные и не дать атакующему (если у него ещё есть доступ) увидеть вашу деятельность.
- Прогоните на этой копии проверку целостности — тот же скрипт сверки контрольных сумм, ту же выборку по аудит-полям, тот же ручной просмотр критичных записей (балансы, реквизиты, список пользователей с правами администратора).
- Если копия чистая — двигайтесь к более свежей точке (например, следующему поколению бэкапа между текущей чистой и первой заведомо испорченной). Если грязная — откатывайтесь дальше в прошлое.
- Повторяйте, пока не найдёте границу: последний чистый снапшот и первый испорченный, между ними — окно компрометации.
Если бэкапы снимаются инструментом с поддержкой множества точек восстановления, это удобно делать без полного разворачивания каждой копии. Например, BorgBackup хранит дедуплицированные снапшоты и позволяет монтировать конкретный архив как файловую систему для быстрой сверки:
borg list /path/to/repo
borg mount /path/to/repo::2026-08-10 /mnt/check
diff -r /mnt/check/etc /etc
borg umount /mnt/check
Restic работает похожим образом через restic snapshots и restic mount.
Для баз данных «примонтировать» снапшот напрямую обычно нельзя — приходится поднимать временный инстанс СУБД из дампа или физической копии и гонять по нему проверочные запросы. Это дороже по времени, поэтому на практике комбинируют: сначала грубо сужают диапазон по датам файловых бэкапов и логам, а точную границу внутри базы находят уже прицельно, на одном-двух кандидатах, а не на всей цепочке.
Важный нюанс: если у бэкапа нет проверки целостности при создании (не только при восстановлении), сама резервная копия может быть повреждена независимо от атаки — стоит не путать битый архив со «свежей подменой». Про то, почему бэкап на том же сервере или без независимой проверки — плохая опора в кризис, есть отдельный разбор: антипаттерн — бэкап на том же сервере.
Почему длинный retention и версионирование решают всё
Всё описанное выше работает только при одном условии: чистая копия физически существует в каком-то бэкапе. Если retention — 7 или 14 дней, а компрометация длилась месяц, вы технически не сможете найти чистую точку, потому что её больше нет, даже теоретически, — она удалена по расписанию ротации.
Отсюда практический вывод для конфигурации бэкапов, актуальный именно для сценария тихой подмены, а не для быстрого сбоя диска:
| Что важно | Зачем именно против тихой подмены |
|---|---|
| Retention от 60-90 дней хотя бы для части копий | Даёт запас на «долгое» обнаружение — большинство скрытых компрометаций находят не в первую неделю |
| Grandfather-Father-Son (GFS) схема ротации | Хранит не только последние N дней, но и разреженные точки за месяцы — недельные и месячные архивы живут дольше ежедневных |
| Неизменяемость (immutable/WORM) хранилища бэкапов | Даже с правами root на проде нельзя переписать или удалить уже созданную копию — это же защищает и от шифровальщика |
| Отдельные учётные данные для бэкап-хранилища | Компрометация прод-сервера не даёт автоматически доступ к архиву бэкапов на удаление |
| Проверка целостности бэкапа сразу при создании | Отличает «бэкап битый сам по себе» от «бэкап содержит подмену» |
Базовое правило распределения копий по типам и местам хранения разобрано в статье про правило 3-2-1 для бэкапов недорого — оно решает задачу физической сохранности копии. Retention и неизменяемость — следующий шаг: копия должна не просто существовать где-то ещё, а существовать достаточно долго и быть защищена от переписывания даже тем, кто уже внутри инфраструктуры.
Практически это означает: ежедневные копии можно хранить неделю-две, но хотя бы недельные снапшоты имеет смысл держать 3-6 месяцев, а месячные — год. Дисковое пространство для этого стоит недорого по сравнению с ценой отсутствия чистой точки восстановления: на VPS с NVMe-хранилищем разница между 14 и 90 днями retention для типичной базы небольшого проекта — это обычно десятки гигабайт, а не порядки величины больше.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Как понять, что это именно тихая подмена, а не баг или кривое обновление?
Первый признак — данные меняются точечно и правдоподобно (не массово и не хаотично), а изменения коррелируют с активностью конкретной учётной записи или IP, не характерной для обычного рабочего процесса. Если сомневаетесь, разбор смежного вопроса — взлом или глюк: как отличить компрометацию от кривого обновления — поможет не потратить время на то, что окажется обычной программной ошибкой.
Что делать, если чистой копии нет вообще ни в одном бэкапе?
Тогда восстановление придётся делать вручную — сверяя записи с внешними источниками (выгрузками у контрагентов, копиями у клиентов, бумажными или почтовыми подтверждениями) и восстанавливая только то, что удаётся подтвердить. Это медленно и не покрывает всё, поэтому вывод один: длинный retention нужно настроить заранее, а не после инцидента.
Нужно ли менять пароли и ключи после того, как нашли чистую точку?
Да, обязательно, и это отдельная задача от поиска чистых данных — ротация всех учётных данных, к которым у атакующего теоретически был доступ за весь период компрометации, а не только тех, что использовались явно.
Можно ли автоматизировать сверку контрольных сумм на будущее?
Да — FIM-системы вроде AIDE или Tripwire, запущенные по расписанию с уведомлением в отдельный канал (не на тот же сервер), ловят изменения файлов практически сразу. Для баз данных ближайший аналог — триггеры аудита или CDC (change data capture) в отдельное append-only хранилище.
Сколько по времени занимает такой разбор на практике?
Сильно зависит от объёма данных и качества логов — от нескольких часов, если аудит-лог есть и точен, до нескольких дней при ручной бинарной сверке по цепочке бэкапов без вспомогательных инструментов. Точных цифр без знания вашей инфраструктуры никто честно не назовёт — ориентируйтесь на порядок, а не на конкретное число.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →