Монитор даёт вам минуты. Что с ними делать, решено заранее или не решено вовсе. В случаях этой серии время терялось редко между блокчейном и алертом. Оно терялось между алертом и человеком с нужным ключом, который делает нужное.
Несколько таймингов, все из публичных разборов и наших ончейн-проверок1:
- IoTeX ioTube, февраль 2026. Первым признаком был
OwnershipTransferredв 01:07:35. Команда узнала в 08:01, почти через семь часов. Почти весь ущерб пришёлся на это окно. - Orbit Bridge, декабрь 2023. Хранилище вычистили пятью переводами за 17 минут. Мост отключили примерно через час после первого перевода.
- Ronin Bridge, август 2024. У команды был выключатель паузы. Им воспользовались через 38 минут после первого вывода и через 86 минут после апгрейда, который всё вызвал.
- WazirX, июль 2024. Упавший вызов к Safe случился за 3–4,5 минуты до апгрейда Safe на код атакующего. После этого у владельцев не осталось контроля.
- PlayDapp, февраль 2024. Между двумя волнами у команды было 66 часов, и вторую остановить не вышло: роли токена нельзя было отозвать.
Четыре из пяти случаев про людей и устройство контрактов, а не про обнаружение. Эта часть о них.
Как выглядят первые пять минут
Возьмём алерт «владелец хранилища сменился» в 02:14. Пять минут должны идти примерно так.
| Минута | Что происходит | Что должно уже существовать |
|---|---|---|
| 0 | Алерт приходит на телефон, который шумит | Канал, который читают ночью |
| 0–1 | Один человек говорит «беру», и никто не ждёт другого | Названный ответственный за алерт |
| 1–3 | Это наше? Плановая передача или нет? | Способ проверить: календарь, чат с подписантами |
| 3–5 | Если не наше: тянуть рычаг | Ключ, устройство и человек, который может им воспользоваться прямо сейчас |
Места, где ломается, известны. Сообщение никто не видит. Двое видят, и каждый считает, что у другого. Видящий ничего не может сделать. Тот, кто может, спит с выключенными уведомлениями. Всё ниже закрывает одно из этих мест.
1. Знайте, у кого ключ паузы
Напишите по строке на контракт: что его останавливает и кто может сделать это прямо сейчас.
| Контракт | Рычаг | У кого | Время на применение |
|---|---|---|---|
| Хранилище | pause() | ||
| Токен | отозвать роль, чёрный список | ||
| Шлюз | пауза через контракт-стража | ||
| Safe (владелец перечисленного) | заменить владельцев, изменить порог |
Заполните пустые клетки честно. Типичные ответы неприятны:
- Ключ паузы лежит в том же мультисиге, что и апгрейды, нужны пять подписантов, и четверо спят. Многие команды это разделяют: узкая роль паузы у небольшой группы или у одного горячего ключа, а широкие полномочия на апгрейд за медленным мультисигом. Пауза — рычаг, который должно быть легко потянуть, и он не должен уметь двигать деньги. У Ronin было именно так: отдельный PauseEnforcer с одним вызовом
triggerPause(). - Паузы нет. Тогда рычаг другой: отозвать роль, убрать минтера, откатить код апгрейдом. Если нет и этого, рычаг — следующий раздел.
- Рычага нет в самом коде. Токен PlayDapp использовал роли OpenZeppelin 2.x, где нельзя отозвать чужую роль минтера. Команда убрала свои роли, у атакующего его роли остались, и выход был в миграции токена2. У WazirX после апгрейда Safe не было способа вернуть его себе3. Проверяйте это до запуска. После это уже миграция.
SmartAlert проверяет это за вас: на странице контракта есть блок «Что вы сможете сделать при инциденте» — пауза, владелец (один ключ или Safe N из M), кто может заменить код, минтер OpenZeppelin 2.x, которого нельзя отозвать. Под каждым предупреждением — кнопка правила.
2. Шлите алерты людям, которые могут действовать
Алерт в канале, который никто не читает, — это журнал. Решите по каждому правилу, куда он идёт.
- Critical — в канал, который шумит ночью: владелец, апгрейд, роли, пауза, правила по состоянию. Telegram бесплатен. Slack, Discord, вебхуки, PagerDuty и почта — на платных тарифах.
- Warning — в канал, который читают в рабочее время: малый запас газа, упавшая транзакция Safe, необычная частота. Это важно, но звонка не требует.
- Добавьте нужных людей. Алерт полезен тому, кто может ответить «это наше?», и тому, у кого ключ. Если это разные люди, канал нужен обоим.
- Эскалируйте, если никто не взял. На Pro и выше у правила может быть один шаг эскалации: если за 5, 10, 15, 30 или 60 минут никто не принял алерт («Взял, разбираюсь»), он уходит во второй канал, например в PagerDuty или другому человеку. Для критичного алерта мы выбрали бы 5 или 10 минут. Принятие останавливает таймер и записывает, кто взял.
Не отправляйте всё на пейджер. Канал, который срабатывает на каждый всплеск, приучает людей его глушить, как в части 11. Читают немногие правила, у каждого из которых понятное действие.
3. Заморозка денег ниже по течению
У некоторых инцидентов рычага нет: ключ потерян, Safe больше не ваш, вывод случился одной транзакцией. Остаётся одно: затруднить вывод украденных денег в обычные.
- Биржи. Украденное обычно уходит на биржу или в мост, чтобы обменять. Биржа может заморозить депозит, если услышит вовремя и поверит сообщению. Заведите контакт службы безопасности на тех биржах, которыми пользуются ваши клиенты, и шлите туда адреса атакующего.
- Эмитенты централизованных токенов. Эмитенты стейблкоинов вроде USDT и USDC могут заморозить адрес. Они действуют по проверенному запросу, поэтому как до них достучаться, надо знать заранее.
- Группы реагирования. SEAL 911 помогали Ronin с реакцией4. Знайте, как связаться с такой группой.
У UXLINK владельцев убрали за 1–2,5 минуты до первого вывода, так что к моменту, когда мог прийти алерт, законные владельцы уже были отрезаны5. В таких случаях команде остаются звонки биржам и эмитентам. Держите список там, где его можно открыть в три часа ночи: имена, контакт для каждого, что отправлять (адреса, хеши транзакций, суммы).
4. Ночной тест
Всё выше — теория, пока не отработало хотя бы раз.
- Проверьте канал. В SmartAlert у каждого канала есть кнопка теста, она шлёт тестовое сообщение. Нажмите её для каждого канала и каждого человека. Это подтверждает, что адрес и токен верны, и больше ничего.
- Проведите учения ночью, без предупреждения. Вызовите безвредный алерт: например, правило на вашем тестовом контракте с порогом, который вы пересечёте намеренно. Засеките время. Кто увидел, сколько до «беру», сколько до того, как обладатель ключа подтвердил, что может потянуть рычаг.
- Почините найденное. Обычные находки: телефон в беззвучном режиме, человек, который может поставить паузу, в самолёте, никто не знает, где устройство с ключом стража.
Встроенной функции «учения» в SmartAlert нет, поэтому тест — это правило, которое вы заводите для этой цели и потом удаляете. Делайте раз в квартал и после каждого прихода или ухода человека из дежурной группы.
Чего пять минут не исправят
Если всё происходит одной транзакцией, пяти минут нет. См. часть 8: там нужна защита до события, а не реакция после.
Как поймать
Алерты, с которых начинается реакция, и severity, которую мы бы выбрали:
- Админские события, Critical: ownership-transferred, role-granted, proxy-upgraded, safe-owners-changed. В канал, который читают ночью, с шагом эскалации на 5 или 10 минут.
- Состояние, Critical: contract-state-paused и правило по состоянию на каждый параметр безопасности (часть 10).
- Выводы, Critical: large-transfer-usd и treasury-below-usd. Они сообщают размер потери, часто уже после ухода первых денег.
- Safe, Warning или Critical: правило на упавшую
execTransactionи «разрешённые отправители» наExecutionSuccess(часть 9). - Киперы, Warning: keeper-gas-runway, low-balance-no-topup.
- Проведите ночной тест, описанный выше.
Вся серия
Блок 1. Как устроен контракт
Блок 2. Как контракты ломают
- Кража админского ключа: IoTeX, PlayDapp, Zoth
- Почему мосты — главная цель
- Манипуляция оракулом и цены, флэш-займы
- Взлом одной транзакцией и чего мониторинг не может
Блок 3. Как следить
- Что мониторить после аудита
- События и состояние
- Фиксированный порог или норма по часам
- Реагирование (эта часть)
Коротко: найдите двери, следите, кто ими пользуется и что меняется без события, ставьте границы, которые идут за контрактом, и заранее решите, кто тянет рычаг.
Источники
- 1.IoTeX: IoTeX, ioTube bridge incident update. Orbit: Orbit Chain, official statement. Ronin: SmartAlert, ончейн-разбор. WazirX: Rekt, WazirX; связь упавшего вызова с атакой — наш вывод. PlayDapp: Halborn, Explained: The PlayDapp hack. ↩
- 2.Halborn, Explained: The PlayDapp hack. ↩
- 3.Rekt, WazirX. ↩
- 4.Three Sigma, analysis of the Ronin Network exploit. ↩
- 5.UXLINK в X, заявление об инциденте; Rekt, UXLINK. ↩