Incident response для Solana-програми відрізняється від традиційного backend-плану однією критичною деталлю: після розгортання програма працює на загальнодоступному кластері, і ви не можете просто «перезапустити сервіс» або «закрити порт». Єдині реальні важелі впливу — це upgrade authority, freeze authority та архітектурні рішення, закладені до розгортання. Нижче — покрокова схема, яка дозволяє діяти системно, а не реактивно.
План дій при виявленні вразливості
План не замінює аудит коду, але структурує дії команди в перші хвилини після підтвердження інциденту. Його треба підготувати до розгортання, а не в момент кризи.
Оцінка масштабу та впливу
Перше завдання — визначити, чи вразливість вже експлуатується, і який стан облікових записів (accounts) під загрозою. Для Solana-програм це означає кілька конкретних кроків:
- Ідентифікувати тип вразливості. Це логічна помилка в бізнес-логіці (неправильний розрахунок балансів), проблема з авторизацією (відсутня перевірка підпису чи PDA), переповнення цілого числа (integer overflow) чи неконтрольований CPI-виклик у сторонню програму? Тип визначає швидкість деградації.
- Перевірити ланцюг транзакцій. Використовуйте RPC-провайдера з доступом до повної історії транзакцій (getSignaturesForAddress, getTransaction із параметром maxSupportedTransactionVersion). Знайдіть першу підозрілу транзакцію та оцініть обсяг скомпрометованих коштів або даних.
- Оцінити стан відповідних облікових записів. Чи змінилися дані в PDA-акаунтах програми? Чи є спроби закрити (close) критичні акаунти? Це визначає, чи достатньо зупинити програму, чи потрібна міграція стану.
- Визначити межу впливу. Чи стосується вразливість лише певних інструкцій, чи будь-яка взаємодія з програмою небезпечна? Це ключове для рішення про фріз.
Очікуваний результат цього етапу — структурована записка: тип вразливості, перша транзакція-підозра, орієнтовний збиток, перелік уражених акаунтів, чи продовжується активна експлуатація.
Комунікація з користувачами
У Solana-екосистемі користувачі — це не лише кінцеві клієнти, а й інші протоколи, які інтегрували вашу програму через CPI. Комунікація має бути двоканальною:
- Публічний канал (Discord, X, офіційний форум): коротке повідомлення без технічних деталей експлуатації. Формат: «Виявлено аномалію в роботі програми [назва/адреса]. Узаємодію тимчасово обмежено. Розслідування триває. Ваші кошти не під загрозою / ситуація уточнюється». Не публікуйте деталі вразливості, поки патч не задеплоєно.
- Приватний канал для інтеграторів (CPI-партнери): повідомлення з конкретикою — яка інструкція уражена, чи безпечно продовжувати виклики вашої програми, чи потрібно зупинити власні сервіси. Це критично, бо сторонній протокол може продовжувати генерувати транзакції, що потрапляють у вашу уражену інструкцію.
Типова помилка — мовчати «до вирішення». У DeFi-контексті мовчання сприймається як приховування, а інтегратори можуть самостійно приймати рішення, що погіршить ситуацію (наприклад, спробувати масово вивести ліквідність, що створить додаткове навантаження на уражену програму).
Фріз програми як екстрений захід
Фріз (freeze) — це механізм Solana-runtime, який блокує виконання будь-яких інструкцій програми. Він працює на рівні кластера: коли програму заморожено, усі транзакції, що посилаються до неї, відхиляються з помилкою.
Передумова: програма була задеплоєна із вказаним freeze authority. Якщо freeze authority не було встановлено або воно було передано на нульовий акаунт, фріз неможливий — це архітектурне рішення, яке неможливо змінити постфактум.
Як перевірити наявність freeze authority: викличте `solana program show <program_id>` через CLI. У виводі шукайте рядок `Freeze Authority`. Якщо там вказано адресу — фріз можливий. Якщо порожнє значення або відсутнє — ні.</program_id>
Процедура фрізу:
- Переконайтеся, що ключ freeze authority доступний (ключова пара у безпечному сховищі, HSM або multisig).
- Виконайте команду фрізу через CLI або програмно. Точний синтаксис залежить від версії Solana CLI — перевірте актуальну документацію `solana program freeze --help` у вашому середовищі.
- Перевірте результат: відправте тестову транзакцію до замороженої програми. Очікуваний результат — транзакція відхиляється з відповідною помилкою виконання.
Ризики фрізу:
- Усі користувачі втрачають доступ до своїх даних у рамках програми. Якщо програма керує ліквідністю або позиціями, користувачі не зможуть закрити їх до розморожування.
- Якщо вашу програму викликають через CPI інші протоколи, їхні транзакції також падатимуть. Це може спричинити каскадний збій.
- Фріз є публічною подією. Він сигналізує про серйозну проблему і може викликати паніку.
Коли фріз доречний: активна експлуатація вразливості, що призводить до безперервного втручання в стан акаунтів; вразливість у критичній інструкції, яку неможливо обійти архітектурно.
Коли фріз недоречний: вразливість обмежена невеликою групою акаунтів і не поширюється; фріз завдасть більше шкоди, ніж сама вразливість; ви можете швидко задеплоїти патч через upgrade authority.
План відкату: розмороження виконується тією ж freeze authority через відповідну команду. Після розмороження програма одразу стає доступною для виконання. Переконайтеся, що перед розморожуванням задеплоєно виправлену версію (якщо використовуєте upgrade authority) або що вразливість усунуто іншим шляхом.
Відновлення після інциденту
Відновлення в Solana не означає «відкотити базу даних». Ланцюг транзакцій незмінний. Тому відновлення — це завжди рух вперед: патч, міграція стану, компенсація.
Крок 1. Патч через upgrade authority. Якщо програма задеплоєна з upgrade authority (що є стандартом для більшості non-immutable програм), ви можете задеплоїти виправлену версію на ту саму адресу. Перед деплоєм:
- Переконайтеся, що патч не ламає існуючий стан акаунтів (збережена сумісність даних).
- Пройдіть повний цикл тестування на devnet із копією реального стану (експорт акаунтів через `solana account` і імпорт на devnet для тестування міграції).
- Якщо патч змінює структуру даних акаунтів, реалізуйте міграцію як окрему інструкцію у новій версії програми.
Крок 2. Міграція стану (якщо потрібна). Якщо вразливість пошкодила дані акаунтів, нова версія програми має містити інструкцію для відновлення коректного стану. Це може бути:
- Перерахунок балансів на основі історії транзакцій (offchain-скрипт формує список корекцій, потім мультисиг підписує транзакції міграції).
- Закриття пошкоджених акаунтів і створення нових (якщо бізнес-логіка це дозволяє).
Крок 3. Верифікація. Після розгортання патчу:
- Виконайте тестові транзакції через RPC-провайдера, щоб підтвердити, що інструкція працює коректно.
- Перевірте, що уражена інструкція більше не дозволяє експлуатацію (повторіть вектор атаки в контрольованих умовах на devnet).
- Якщо програма була заморожена — розморозьте після підтвердження працездатності патчу.
Обмеження: якщо програма була задеплоєна як immutable (без upgrade authority), патч через оновлення неможливий. Єдиний шлях — розгортання нової програми на нову адресу та міграція користувачів. Це окремий інфраструктурний процес, який виходить за межі incident response і має бути передбачений на етапі архітектури.
Постінцидентний аналіз
Постінцидентний аналіз (post-mortem) у контексті Solana-програми фокусується на двох вимірах: чому вразливість потрапила в production і чому системи моніторингу не виявили її раніше.
Технічна частина аналізу:
- Коренева причина. Конкретна помилка в коді (наприклад, відсутня перевірка `ctx.accounts.signer.is_signer`), а не розпливчасте «людський фактор». Вкажіть файл, рядок, коміт.
- Чому аудит не знайшов. Чи був проведений зовнішній аудит? Чи охоплював він саме цей шлях виконання? Чи були в аудиторів обмежені scope або час?
- Чому тести не виявили. Чи був написаний інтеграційний тест для цього вектора? Чи покривали unit-тести граничні значення? Чи використовувався фаззинг?
- Чому моніторинг не спрацював. Чи були налаштовані алерти на аномальну активність (різкий сплеск транзакцій, незвичні суми, дивні патерни викликів інструкцій)? Чи збирали ви метрики взагалі?
Організаційна частина аналізу:
- Час реагування. Від першої підозрілої транзакції до підтвердження інциденту, від підтвердження до фрізу/патчу, від патчу до повного відновлення. Порівняйте з плановими показниками.
- Доступ до ключів. Чи був freeze authority доступний у потрібний момент? Чи зайняло отримання доступу забагато часу (наприклад, очікування збору multisig)?
- Ролі та відповідальність. Хто приймав рішення про фріз? Чи був чіткий owner процесу, чи це було колективне безладдя?
Конкретні зміни після аналізу: кожен висновок має трансформуватися в завдання з відповідальним і дедлайном. Типові результати постінцидентного аналізу для Solana-програм:
- Додавання інтеграційних тестів для виявленого вектора атаки.
- Впровадження моніторингу аномальної активності через RPC-підписки (websocket-підписки на логи транзакцій програми).
- Перегляд процесу зберігання ключів upgrade/freezer authority (перехід на HSM або таймлок-мультисиг, якщо ще не використовується).
- Розширення scope наступного аудиту.
- Додавання в CI/CD перевірки на типові вразливості (наприклад, lint-правила для відсутніх перевірок signer у Anchor-програмах).
Постінцидентний аналіз не має бути звинувачувальним документом. Його мета — перетворити інцидент на конкретні інженерні покращення, які зменшують ймовірність повторення та скорочують час реагування в майбутньому.