Раніше команда CertiK виявила в блокчейні Sui низку вразливостей, які викликають відмову в обслуговуванні. Серед цих вразливостей виділяється нова вразливість із сильним впливом. Ця вразливість може призвести до того, що вузли мережі Sui не зможуть обробляти нові транзакції, і ефект еквівалентний повному вимкненню всієї мережі.
Лише минулого понеділка CertiK отримав винагороду від SUI у розмірі 500 000 доларів США за виявлення цієї великої вразливості безпеки. CoinDesk, авторитетне ЗМІ в промисловості США, повідомило про подію, а потім основні ЗМІ також випустили відповідні новини після свого звіту.
Цю вразливість безпеки яскраво називають "Колесом хом'яка": її унікальний метод атаки відрізняється від відомих на даний момент атак. Зловмиснику потрібно лише передати корисне навантаження приблизно в 100 байтів, щоб запустити нескінченний цикл у вузлі перевірки Sui. , через що він не реагує. до нових транзакцій.
Крім того, збиток, спричинений атакою, може продовжуватися після перезапуску мережі та автоматично поширюватися в мережі Sui, унаслідок чого всі вузли не зможуть обробляти нові транзакції, як хом’яки, які нескінченно бігають на колесі. Тому ми називаємо цей унікальний тип атаки атакою «колесо хом’яка».
Виявивши помилку, CertiK повідомив про неї Sui через програму винагороди за помилки Sui. Sui також ефективно відреагував у перший раз, підтвердив серйозність уразливості та активно вжив відповідних заходів для усунення проблеми до запуску основної мережі. Окрім усунення цієї конкретної вразливості, Sui також реалізував профілактичні заходи для зменшення потенційної шкоди, яку може завдати ця вразливість.
Щоб подякувати команді CertiK за відповідальне розкриття інформації, Суї нагородив команду CertiK винагородою в розмірі 500 000 доларів США.
Деталі цієї критичної вразливості буде розкрито на технічному рівні нижче, а також буде з’ясовано першопричину та потенційний вплив уразливості.
Пояснення вразливості
Ключова роль валідаторів у Sui
Для ланцюжків блоків на основі мови Move, таких як Sui та Aptos, механізм захисту для запобігання зловмисним атакам корисного навантаження — це в основному технологія статичної перевірки. За допомогою технології статичної перевірки Sui може перевірити дійсність корисного навантаження, наданого користувачем, до того, як контракт буде випущено або оновлено. Валідатор надає серію перевірок для перевірки правильності структури та семантики.Тільки після проходження перевірки перевірки контракт увійде у віртуальну машину Move для виконання.
Шкідливі загрози корисного навантаження в ланцюжку руху
Мережа Sui надає новий набір моделей зберігання та інтерфейсів на основі оригінальної віртуальної машини Move, тому Sui має налаштовану версію віртуальної машини Move. Щоб підтримувати нові примітиви зберігання, Sui також представляє серію додаткових і налаштованих методів перевірки для перевірки безпеки ненадійних корисних даних, таких як захист об’єктів і функції доступу до глобальної пам’яті. Ці спеціальні перевірки відповідають унікальним функціям Sui, тому ми називаємо їх валідаторами Sui.
Порядок перевірки вантажів Суї
Як показано на малюнку вище, більшість перевірок у верифікаторі виконують структурну перевірку безпеки щодо CompiledModule (що представляє виконання наданого користувачем корисного навантаження контракту). Наприклад, використовуйте «Перевірку дублікатів», щоб переконатися, що в корисному навантаженні часу виконання немає повторюваних записів; використовуйте «Перевірку обмежень», щоб переконатися, що довжина кожного поля в корисному навантаженні часу виконання знаходиться в межах максимально дозволеного ліміту входу.
На додаток до структурних перевірок, статичні перевірки верифікатора все ще вимагають більш складних методів аналізу для забезпечення надійності ненадійних корисних навантажень на семантичному рівні.
Дізнайтеся про абстрактний інтерпретатор Move:
Лінійний та ітеративний аналіз
Абстрактний інтерпретатор, наданий Move, — це структура, спеціально розроблена для виконання складного аналізу безпеки байт-коду за допомогою абстрактної інтерпретації. Цей механізм робить процес верифікації більш детальним і точним, і кожен валідатор може визначати свій унікальний абстрактний стан для аналізу.
Під час запуску абстрактний інтерпретатор будує граф потоку керування (CFG) зі скомпільованих модулів. Кожен базовий блок у цих CFG підтримує набір станів, «стан попереднього замовлення» та «стан після замовлення». «Стан попереднього замовлення» забезпечує моментальний знімок стану програми перед виконанням базового блоку, тоді як «стан після замовлення» забезпечує опис стану програми після виконання базового блоку.
Коли абстрактний інтерпретатор не стикається зі стрибком (або циклом) у графі потоку керування, він дотримується простого лінійного принципу виконання: кожен базовий блок аналізується по черзі, а попередня інструкція обчислюється відповідно до семантики кожної інструкції в блок Послідовний стан і постпослідовний стан. Результатом є точний знімок стану кожного основного блоку під час виконання програми, що допомагає перевірити властивості безпеки програми.
Робочий процес абстрактного інтерпретатора Move
Однак процес стає складнішим, коли в потоці керування є петлі. Поява циклу означає, що граф потоку керування містить ребро стрибка назад Джерело ребра стрибка назад відповідає наступному стану поточного базового блоку, а цільовий базовий блок (голова циклу) переходу- back edge є попередньо проаналізованим. Таким чином, абстрактний інтерпретатор повинен ретельно об’єднати стани двох основних блоків, пов’язаних із стрибком назад.
Якщо виявлено, що об’єднаний стан відрізняється від існуючого стану попереднього замовлення базового блоку головки циклу, абстрактний інтерпретатор оновлює стан базового блоку головки циклу та перезапускає аналіз, починаючи з цього базового блоку. Цей ітеративний процес аналізу триватиме, доки попередній стан циклу не стабілізується. Іншими словами, цей процес повторюється до тих пір, поки стан попереднього замовлення базового блоку головки циклу більше не змінюється між ітераціями. Досягнення фіксованої точки означає, що аналіз циклу завершено.
Sui IDLeak Validator:
Індивідуальний аналіз абстрактної інтерпретації
На відміну від оригінального дизайну Move, блокчейн-платформа Sui представляє унікальну глобальну модель зберігання, орієнтовану на ціль. Примітною особливістю цієї моделі є те, що будь-яка структура даних із ключовим атрибутом (що зберігається в ланцюжку як індекс) повинна мати тип ID як перше поле структури. Поле ідентифікатора є незмінним і не може бути передано іншим об’єктам, оскільки кожен об’єкт повинен мати глобально унікальний ідентифікатор. Щоб забезпечити ці властивості, Sui створив набір спеціальної логіки аналізу поверх абстрактного інтерпретатора.
Верифікатор IDLeak, також відомий як id_leak_verifier, працює в поєднанні з абстрактним інтерпретатором для аналізу. Він має власний унікальний абстрактний домен, який називається AbstractState. Кожен AbstractState складається з AbstractValue, що відповідає декільком локальним змінним. AbstractValue відстежує стан кожної локальної змінної, щоб відстежити, чи є змінна ID абсолютно новою.
У процесі пакування структури валідатор IDLeak дозволяє запаковувати в структуру лише абсолютно новий ідентифікатор. Завдяки абстрактному аналізу інтерпретації валідатори IDLeak можуть вичерпно відстежувати стан локального потоку даних, щоб гарантувати, що жодні існуючі ідентифікатори не передаються іншим об’єктам структури.
Проблема неузгодженості обслуговування стану валідатора Sui IDLeak
Валідатор IDLeak інтегровано з абстрактним інтерпретатором Move шляхом реалізації функції AbstractState::join. Ця функція відіграє невід'ємну роль в державному управлінні, особливо в об'єднанні та оновленні державних цінностей.
Розгляньте детально ці функції, щоб зрозуміти їхню роботу:
У AbstractState::join функція приймає інший AbstractState як вхідні дані та намагається об’єднати його локальний стан із локальним станом поточного об’єкта. Для кожної локальної змінної у стані введення він порівнює значення цієї змінної з її поточним значенням у локальному стані (за замовчуванням використовується AbstractValue::Other, якщо не знайдено). Якщо два значення не рівні, він встановить позначку «changed» як основу для того, чи змінився результат злиття кінцевого стану, і оновить значення локальної змінної в локальному стані, викликавши AbstractValue::join.
У AbstractValue::join функція порівнює своє значення з іншим AbstractValue. Якщо вони рівні, він поверне передане значення. Якщо не дорівнює, повертає AbstractValue::Other.
Однак ця логіка підтримки стану містить приховану проблему невідповідності. Хоча AbstractState::join поверне результат, який вказує, що об’єднаний стан змінився (JoinResult::Changed) на основі різниці між новим і старим значеннями, об’єднане оновлене значення стану все ще може залишатися незмінним.
Ця проблема невідповідності спричинена порядком операцій: рішення змінити стан у AbstractState::join відбувається до оновлення стану (AbstractValue::join), і це рішення не відображає реальний результат оновлення стану.
Крім того, у AbstractValue::join AbstractValue::Other відіграє вирішальну роль у результаті злиття. Наприклад, якщо старе значення — AbstractValue::Other, а нове — AbstractValue::Fresh, оновлене значення стану все ще буде AbstractValue::Other, навіть якщо старе та нове значення відрізняються, сам стан залишається незмінним. після оновлення.
Приклад: неузгодженість з’єднань із збереженням стану
Це створює неузгодженість: результат об’єднання стану базового блоку вважається «зміненим», але саме значення об’єднаного стану не змінилося. У процесі аналізу абстрактного тлумачення такі невідповідності можуть мати серйозні наслідки. Ми розглядаємо поведінку абстрактного інтерпретатора, коли цикл виникає в графі потоку керування (CFG):
Коли зустрічається цикл, абстрактний інтерпретатор використовує ітеративний метод аналізу, щоб об’єднати стан цільового базового блоку переходу назад і поточного базового блоку. Якщо об’єднаний стан зміниться, абстрактний інтерпретатор повторно проаналізує, починаючи з цільового переходу.
Однак, якщо операція об’єднання аналізу абстрактної інтерпретації помилково позначає результат об’єднання стану як «зміна», хоча насправді значення внутрішньої змінної стану не змінилося, це призведе до нескінченного повторного аналізу, що призведе до нескінченний цикл.
Подальше використання невідповідностей
Запускає нескінченний цикл у валідаторі Sui IDLeak
Використовуючи цю невідповідність, зловмисник може побудувати зловмисний граф потоку керування, який вводить валідатори IDLeak у нескінченний цикл. Цей ретельно побудований граф потоку керування складається з трьох основних блоків: BB1 і BB2, BB3. Варто зазначити, що ми навмисно ввели ребро зворотного стрибка з BB3 на BB2, щоб створити цикл.
Зловмисний статус CFG+ може призвести до внутрішнього нескінченного циклу в валідаторі IDLeak
Процес починається з BB2, де для AbstractValue певної локальної змінної встановлено значення ::Other. Після виконання BB2 потік переходить до BB3, де для тієї ж змінної встановлено значення ::Fresh. Наприкінці BB3 є край стрибка назад, який стрибає на BB2.
Вищезазначені невідповідності відіграють ключову роль в абстрактній інтерпретації цього прикладу. Коли обробляється ребро переходу назад, абстрактний інтерпретатор намагається з’єднати стан після замовлення BB3 (зі змінною «::Fresh») зі станом попереднього замовлення BB2 (зі змінною «::Other»). Функція AbstractState::join помічає різницю між старими та новими значеннями та встановлює прапорець "зміна", щоб вказати, що BB2 потрібно повторно проаналізувати.
Однак домінуюча поведінка «::Other» у AbstractValue::join означає, що після об’єднання AbstractValue фактичне значення змінної стану BB2 все ще є «::Other», а результат злиття стану не змінився. .
Отже, щойно цей циклічний процес починається, тобто коли валідатори продовжують повторно аналізувати BB2 і всі наступні базові вузли блоку (в даному випадку BB3), він продовжується нескінченно. Нескінченний цикл споживає всі доступні цикли ЦП, унеможливлюючи обробку та відповідь на нові транзакції, що зберігається під час перезапуску валідатора.
Використовуючи цю вразливість, вузли перевірки працюють нескінченно, як хом’яки на колесі в нескінченному циклі, не в змозі обробити нові транзакції. Тому ми називаємо цей унікальний тип атаки атакою «колесо хом’яка».
Атака «колесо хом’яка» може фактично зупинити валідатори Sui, що, у свою чергу, може вивести з ладу всю мережу Sui.
Зрозумівши причину вразливості та процес ініціювання, ми створили конкретний приклад за допомогою наведеної нижче симуляції байт-коду Move і успішно запустили вразливість у симуляції в реальному середовищі:
У цьому прикладі показано, як запустити вразливість у реальному середовищі за допомогою ретельно створеного байт-коду. Зокрема, зловмисник може запустити нескінченний цикл у валідаторі IDLeak, споживаючи всі цикли ЦП вузла Sui з корисним навантаженням лише близько 100 байт, ефективно запобігаючи обробці нових транзакцій і викликаючи відмову в обслуговуванні в мережі Sui.
Атака «Hamster Wheel» продовжує завдавати шкоди мережі Sui
Програма винагороди за помилки Sui має суворі правила щодо оцінки рівнів уразливості, головним чином на основі ступеня шкоди для всієї мережі. Уразливості, які відповідають «критичному» рейтингу, повинні вимикати всю мережу та ефективно запобігати підтвердженню нових транзакцій, а також вимагають хардфорка, щоб вирішити проблему; (середній)» або «високий ризик (високий)».
Уразливість «колесо хом’яка», виявлена командою CertiK Skyfall, може вимкнути всю мережу Sui, і вимагає офіційного випуску нової версії для оновлення та відновлення. Зрештою Sui оцінив вразливість як «Критичну» на основі її критичності. Щоб краще зрозуміти серйозний вплив атаки «колесо хом’яка», нам необхідно зрозуміти складну архітектуру серверної системи Sui, особливо весь процес публікації або оновлення транзакцій у ланцюжку.
Огляд взаємодії для надсилання транзакцій у Sui
Спочатку транзакції користувача надсилаються через зовнішній RPC і передаються до внутрішніх служб після базової перевірки. Сервіс Sui відповідає за подальшу перевірку корисних даних вхідних транзакцій. Після успішної перевірки підпису користувача транзакція перетворюється на сертифікат транзакції (що містить інформацію про транзакцію та підпис Суї).
Ці сертифікати транзакцій є фундаментальною частиною роботи мережі Sui і можуть поширюватися між різними вузлами перевірки в мережі. Для транзакцій створення/оновлення контракту, перш ніж їх можна буде завантажити в ланцюжок, вузол перевірки викличе верифікатор Sui, щоб перевірити та перевірити дійсність структури контракту/семантики цих сертифікатів. Саме під час цього критичного етапу перевірки вразливість «нескінченного циклу» може бути запущена та використана.
Коли уразливість була запущена, це призвело до переривання процесу перевірки на невизначений термін, фактично перешкоджаючи здатності системи обробляти нові транзакції та спричиняючи повне відключення мережі. Крім того, ситуація зберігалася після перезапуску вузла, що означало, що традиційні засоби пом’якшення були далеко неадекватними. Після того, як уразливість спрацює, буде завдано "безперервної шкоди" та залишиться тривалий вплив на всю мережу Sui.
Рішення Sui
Після відгуку від CertiK Sui своєчасно підтвердив уразливість і випустив виправлення для усунення критичної вади. Виправлення забезпечує узгодженість між змінами стану та прапорцями після змін, усуваючи критичний ефект атаки «колесо хом’яка».
Щоб усунути вищезгадану невідповідність, виправлення Sui включає невелике, але критичне налаштування функції AbstractState::join. Цей патч усуває логіку визначення результату злиття стану перед виконанням AbstractValue::join. Натомість спочатку виконайте функцію AbstractValue::join для злиття стану та встановіть злиття, порівнюючи остаточний результат оновлення з початковим значенням стану (старе _value) Позначка для змін.
Таким чином, результат об’єднання станів буде відповідати результату справжнього оновлення, і під час аналізу не відбуватиметься нескінченний цикл.
Окрім усунення цієї конкретної вразливості, Sui також розгорнув засоби пом’якшення, щоб зменшити вплив майбутніх уразливостей валідатора. Відповідно до відповіді Sui у звіті про помилку, пом’якшення включає функцію під назвою Denylist.
«Однак валідатори мають файл конфігурації вузла, який дозволяє їм тимчасово відхиляти певні класи транзакцій. Цю конфігурацію можна використовувати для тимчасового вимкнення обробки випусків і оновлень пакетів. Через цю помилку Sui запускається перед підписанням випуску або оновлення пакета tx валідатори, у той час як список заборони зупинить роботу валідатора та видалить зловмисну передачу, тимчасова заборона цих типів передачі є 100% ефективним пом’якшенням (хоча це тимчасово порушить службу для людей, які намагаються випустити або оновити код).
До речі, у нас уже деякий час є цей файл конфігурації списку заборонених пересилань, але ми також додали подібний механізм для сертифікатів як подальше пом’якшення вашої раніше повідомленої вразливості «цикл перевірки». Завдяки цьому механізму ми матимемо більше гнучкості проти цієї атаки: ми використовуватимемо конфігурацію списку заборонених сертифікатів, щоб змусити валідатори забути про погані сертифікати (порушуючи нескінченний цикл), і конфігурацію списку заборонених TX, щоб заборонити публікацію/оновлення, тим самим запобігаючи створенню нові транзакції зловмисної атаки. Дякуємо, що змусили нас подумати про це!
Валідатор має обмежену кількість «тактів» (на відміну від газу) для перевірки байт-коду перед підписанням транзакції, і якщо весь байт-код, виданий у транзакції, не можна перевірити за таку кількість тактів, валідатор відмовиться підписати транзакцію, запобігаючи . його від виконання в мережі. Раніше вимірювання застосовувалося лише до вибраного набору комплексних проходів перевірки. Щоб боротися з цим, ми поширюємо вимірювання на кожен валідатор, щоб гарантувати обмеження на роботу, яку виконує валідатор під час процесу перевірки кожного тику. Ми також виправили потенційну помилку нескінченного циклу в валідаторі витоку ідентифікатора. "
--Пояснення від розробників Sui про виправлення помилок
Загалом Denylist дозволяє валідаторам тимчасово уникати використання вразливостей у валідаторах і ефективно запобігати потенційній шкоді, спричиненій деякими зловмисними транзакціями, вимикаючи процес випуску або оновлення. Коли пом’якшувальні заходи Denylist набувають чинності, вузли гарантують, що вони можуть продовжувати роботу, жертвуючи власними функціями контракту публікації/оновлення.
Підсумуйте
У цій статті ми ділимося технічними деталями атаки «Hamster Wheel», виявленої командою CertiK Skyfall, пояснюючи, як цей новий тип атаки використовує ключові вразливості, щоб спричинити повне припинення роботи мережі Sui. Крім того, ми також уважно вивчили своєчасну відповідь Sui для вирішення цієї критичної проблеми та поділилися виправленням уразливості та подальшими методами пом’якшення подібних уразливостей.
Переглянути оригінал
Контент має виключно довідковий характер і не є запрошенням до участі або пропозицією. Інвестиційні, податкові чи юридичні консультації не надаються. Перегляньте Відмову від відповідальності , щоб дізнатися більше про ризики.
Технічні деталі та поглиблений аналіз останньої вразливості Sui "колесо хом'яка".
Раніше команда CertiK виявила в блокчейні Sui низку вразливостей, які викликають відмову в обслуговуванні. Серед цих вразливостей виділяється нова вразливість із сильним впливом. Ця вразливість може призвести до того, що вузли мережі Sui не зможуть обробляти нові транзакції, і ефект еквівалентний повному вимкненню всієї мережі.
Лише минулого понеділка CertiK отримав винагороду від SUI у розмірі 500 000 доларів США за виявлення цієї великої вразливості безпеки. CoinDesk, авторитетне ЗМІ в промисловості США, повідомило про подію, а потім основні ЗМІ також випустили відповідні новини після свого звіту.
Цю вразливість безпеки яскраво називають "Колесом хом'яка": її унікальний метод атаки відрізняється від відомих на даний момент атак. Зловмиснику потрібно лише передати корисне навантаження приблизно в 100 байтів, щоб запустити нескінченний цикл у вузлі перевірки Sui. , через що він не реагує. до нових транзакцій.
Крім того, збиток, спричинений атакою, може продовжуватися після перезапуску мережі та автоматично поширюватися в мережі Sui, унаслідок чого всі вузли не зможуть обробляти нові транзакції, як хом’яки, які нескінченно бігають на колесі. Тому ми називаємо цей унікальний тип атаки атакою «колесо хом’яка».
Виявивши помилку, CertiK повідомив про неї Sui через програму винагороди за помилки Sui. Sui також ефективно відреагував у перший раз, підтвердив серйозність уразливості та активно вжив відповідних заходів для усунення проблеми до запуску основної мережі. Окрім усунення цієї конкретної вразливості, Sui також реалізував профілактичні заходи для зменшення потенційної шкоди, яку може завдати ця вразливість.
Щоб подякувати команді CertiK за відповідальне розкриття інформації, Суї нагородив команду CertiK винагородою в розмірі 500 000 доларів США.
Деталі цієї критичної вразливості буде розкрито на технічному рівні нижче, а також буде з’ясовано першопричину та потенційний вплив уразливості.
Пояснення вразливості
Ключова роль валідаторів у Sui
Для ланцюжків блоків на основі мови Move, таких як Sui та Aptos, механізм захисту для запобігання зловмисним атакам корисного навантаження — це в основному технологія статичної перевірки. За допомогою технології статичної перевірки Sui може перевірити дійсність корисного навантаження, наданого користувачем, до того, як контракт буде випущено або оновлено. Валідатор надає серію перевірок для перевірки правильності структури та семантики.Тільки після проходження перевірки перевірки контракт увійде у віртуальну машину Move для виконання.
Шкідливі загрози корисного навантаження в ланцюжку руху
Мережа Sui надає новий набір моделей зберігання та інтерфейсів на основі оригінальної віртуальної машини Move, тому Sui має налаштовану версію віртуальної машини Move. Щоб підтримувати нові примітиви зберігання, Sui також представляє серію додаткових і налаштованих методів перевірки для перевірки безпеки ненадійних корисних даних, таких як захист об’єктів і функції доступу до глобальної пам’яті. Ці спеціальні перевірки відповідають унікальним функціям Sui, тому ми називаємо їх валідаторами Sui.
Порядок перевірки вантажів Суї
Як показано на малюнку вище, більшість перевірок у верифікаторі виконують структурну перевірку безпеки щодо CompiledModule (що представляє виконання наданого користувачем корисного навантаження контракту). Наприклад, використовуйте «Перевірку дублікатів», щоб переконатися, що в корисному навантаженні часу виконання немає повторюваних записів; використовуйте «Перевірку обмежень», щоб переконатися, що довжина кожного поля в корисному навантаженні часу виконання знаходиться в межах максимально дозволеного ліміту входу.
На додаток до структурних перевірок, статичні перевірки верифікатора все ще вимагають більш складних методів аналізу для забезпечення надійності ненадійних корисних навантажень на семантичному рівні.
Дізнайтеся про абстрактний інтерпретатор Move:
Лінійний та ітеративний аналіз
Абстрактний інтерпретатор, наданий Move, — це структура, спеціально розроблена для виконання складного аналізу безпеки байт-коду за допомогою абстрактної інтерпретації. Цей механізм робить процес верифікації більш детальним і точним, і кожен валідатор може визначати свій унікальний абстрактний стан для аналізу.
Під час запуску абстрактний інтерпретатор будує граф потоку керування (CFG) зі скомпільованих модулів. Кожен базовий блок у цих CFG підтримує набір станів, «стан попереднього замовлення» та «стан після замовлення». «Стан попереднього замовлення» забезпечує моментальний знімок стану програми перед виконанням базового блоку, тоді як «стан після замовлення» забезпечує опис стану програми після виконання базового блоку.
Коли абстрактний інтерпретатор не стикається зі стрибком (або циклом) у графі потоку керування, він дотримується простого лінійного принципу виконання: кожен базовий блок аналізується по черзі, а попередня інструкція обчислюється відповідно до семантики кожної інструкції в блок Послідовний стан і постпослідовний стан. Результатом є точний знімок стану кожного основного блоку під час виконання програми, що допомагає перевірити властивості безпеки програми.
Робочий процес абстрактного інтерпретатора Move
Однак процес стає складнішим, коли в потоці керування є петлі. Поява циклу означає, що граф потоку керування містить ребро стрибка назад Джерело ребра стрибка назад відповідає наступному стану поточного базового блоку, а цільовий базовий блок (голова циклу) переходу- back edge є попередньо проаналізованим. Таким чином, абстрактний інтерпретатор повинен ретельно об’єднати стани двох основних блоків, пов’язаних із стрибком назад.
Якщо виявлено, що об’єднаний стан відрізняється від існуючого стану попереднього замовлення базового блоку головки циклу, абстрактний інтерпретатор оновлює стан базового блоку головки циклу та перезапускає аналіз, починаючи з цього базового блоку. Цей ітеративний процес аналізу триватиме, доки попередній стан циклу не стабілізується. Іншими словами, цей процес повторюється до тих пір, поки стан попереднього замовлення базового блоку головки циклу більше не змінюється між ітераціями. Досягнення фіксованої точки означає, що аналіз циклу завершено.
Sui IDLeak Validator:
Індивідуальний аналіз абстрактної інтерпретації
На відміну від оригінального дизайну Move, блокчейн-платформа Sui представляє унікальну глобальну модель зберігання, орієнтовану на ціль. Примітною особливістю цієї моделі є те, що будь-яка структура даних із ключовим атрибутом (що зберігається в ланцюжку як індекс) повинна мати тип ID як перше поле структури. Поле ідентифікатора є незмінним і не може бути передано іншим об’єктам, оскільки кожен об’єкт повинен мати глобально унікальний ідентифікатор. Щоб забезпечити ці властивості, Sui створив набір спеціальної логіки аналізу поверх абстрактного інтерпретатора.
Верифікатор IDLeak, також відомий як id_leak_verifier, працює в поєднанні з абстрактним інтерпретатором для аналізу. Він має власний унікальний абстрактний домен, який називається AbstractState. Кожен AbstractState складається з AbstractValue, що відповідає декільком локальним змінним. AbstractValue відстежує стан кожної локальної змінної, щоб відстежити, чи є змінна ID абсолютно новою.
У процесі пакування структури валідатор IDLeak дозволяє запаковувати в структуру лише абсолютно новий ідентифікатор. Завдяки абстрактному аналізу інтерпретації валідатори IDLeak можуть вичерпно відстежувати стан локального потоку даних, щоб гарантувати, що жодні існуючі ідентифікатори не передаються іншим об’єктам структури.
Проблема неузгодженості обслуговування стану валідатора Sui IDLeak
Валідатор IDLeak інтегровано з абстрактним інтерпретатором Move шляхом реалізації функції AbstractState::join. Ця функція відіграє невід'ємну роль в державному управлінні, особливо в об'єднанні та оновленні державних цінностей.
Розгляньте детально ці функції, щоб зрозуміти їхню роботу:
У AbstractState::join функція приймає інший AbstractState як вхідні дані та намагається об’єднати його локальний стан із локальним станом поточного об’єкта. Для кожної локальної змінної у стані введення він порівнює значення цієї змінної з її поточним значенням у локальному стані (за замовчуванням використовується AbstractValue::Other, якщо не знайдено). Якщо два значення не рівні, він встановить позначку «changed» як основу для того, чи змінився результат злиття кінцевого стану, і оновить значення локальної змінної в локальному стані, викликавши AbstractValue::join.
У AbstractValue::join функція порівнює своє значення з іншим AbstractValue. Якщо вони рівні, він поверне передане значення. Якщо не дорівнює, повертає AbstractValue::Other.
Однак ця логіка підтримки стану містить приховану проблему невідповідності. Хоча AbstractState::join поверне результат, який вказує, що об’єднаний стан змінився (JoinResult::Changed) на основі різниці між новим і старим значеннями, об’єднане оновлене значення стану все ще може залишатися незмінним.
Ця проблема невідповідності спричинена порядком операцій: рішення змінити стан у AbstractState::join відбувається до оновлення стану (AbstractValue::join), і це рішення не відображає реальний результат оновлення стану.
Крім того, у AbstractValue::join AbstractValue::Other відіграє вирішальну роль у результаті злиття. Наприклад, якщо старе значення — AbstractValue::Other, а нове — AbstractValue::Fresh, оновлене значення стану все ще буде AbstractValue::Other, навіть якщо старе та нове значення відрізняються, сам стан залишається незмінним. після оновлення.
Приклад: неузгодженість з’єднань із збереженням стану
Це створює неузгодженість: результат об’єднання стану базового блоку вважається «зміненим», але саме значення об’єднаного стану не змінилося. У процесі аналізу абстрактного тлумачення такі невідповідності можуть мати серйозні наслідки. Ми розглядаємо поведінку абстрактного інтерпретатора, коли цикл виникає в графі потоку керування (CFG):
Коли зустрічається цикл, абстрактний інтерпретатор використовує ітеративний метод аналізу, щоб об’єднати стан цільового базового блоку переходу назад і поточного базового блоку. Якщо об’єднаний стан зміниться, абстрактний інтерпретатор повторно проаналізує, починаючи з цільового переходу.
Однак, якщо операція об’єднання аналізу абстрактної інтерпретації помилково позначає результат об’єднання стану як «зміна», хоча насправді значення внутрішньої змінної стану не змінилося, це призведе до нескінченного повторного аналізу, що призведе до нескінченний цикл.
Подальше використання невідповідностей
Запускає нескінченний цикл у валідаторі Sui IDLeak
Використовуючи цю невідповідність, зловмисник може побудувати зловмисний граф потоку керування, який вводить валідатори IDLeak у нескінченний цикл. Цей ретельно побудований граф потоку керування складається з трьох основних блоків: BB1 і BB2, BB3. Варто зазначити, що ми навмисно ввели ребро зворотного стрибка з BB3 на BB2, щоб створити цикл.
Зловмисний статус CFG+ може призвести до внутрішнього нескінченного циклу в валідаторі IDLeak
Процес починається з BB2, де для AbstractValue певної локальної змінної встановлено значення ::Other. Після виконання BB2 потік переходить до BB3, де для тієї ж змінної встановлено значення ::Fresh. Наприкінці BB3 є край стрибка назад, який стрибає на BB2.
Вищезазначені невідповідності відіграють ключову роль в абстрактній інтерпретації цього прикладу. Коли обробляється ребро переходу назад, абстрактний інтерпретатор намагається з’єднати стан після замовлення BB3 (зі змінною «::Fresh») зі станом попереднього замовлення BB2 (зі змінною «::Other»). Функція AbstractState::join помічає різницю між старими та новими значеннями та встановлює прапорець "зміна", щоб вказати, що BB2 потрібно повторно проаналізувати.
Однак домінуюча поведінка «::Other» у AbstractValue::join означає, що після об’єднання AbstractValue фактичне значення змінної стану BB2 все ще є «::Other», а результат злиття стану не змінився. .
Отже, щойно цей циклічний процес починається, тобто коли валідатори продовжують повторно аналізувати BB2 і всі наступні базові вузли блоку (в даному випадку BB3), він продовжується нескінченно. Нескінченний цикл споживає всі доступні цикли ЦП, унеможливлюючи обробку та відповідь на нові транзакції, що зберігається під час перезапуску валідатора.
Використовуючи цю вразливість, вузли перевірки працюють нескінченно, як хом’яки на колесі в нескінченному циклі, не в змозі обробити нові транзакції. Тому ми називаємо цей унікальний тип атаки атакою «колесо хом’яка».
Атака «колесо хом’яка» може фактично зупинити валідатори Sui, що, у свою чергу, може вивести з ладу всю мережу Sui.
Зрозумівши причину вразливості та процес ініціювання, ми створили конкретний приклад за допомогою наведеної нижче симуляції байт-коду Move і успішно запустили вразливість у симуляції в реальному середовищі:
У цьому прикладі показано, як запустити вразливість у реальному середовищі за допомогою ретельно створеного байт-коду. Зокрема, зловмисник може запустити нескінченний цикл у валідаторі IDLeak, споживаючи всі цикли ЦП вузла Sui з корисним навантаженням лише близько 100 байт, ефективно запобігаючи обробці нових транзакцій і викликаючи відмову в обслуговуванні в мережі Sui.
Атака «Hamster Wheel» продовжує завдавати шкоди мережі Sui
Програма винагороди за помилки Sui має суворі правила щодо оцінки рівнів уразливості, головним чином на основі ступеня шкоди для всієї мережі. Уразливості, які відповідають «критичному» рейтингу, повинні вимикати всю мережу та ефективно запобігати підтвердженню нових транзакцій, а також вимагають хардфорка, щоб вирішити проблему; (середній)» або «високий ризик (високий)».
Уразливість «колесо хом’яка», виявлена командою CertiK Skyfall, може вимкнути всю мережу Sui, і вимагає офіційного випуску нової версії для оновлення та відновлення. Зрештою Sui оцінив вразливість як «Критичну» на основі її критичності. Щоб краще зрозуміти серйозний вплив атаки «колесо хом’яка», нам необхідно зрозуміти складну архітектуру серверної системи Sui, особливо весь процес публікації або оновлення транзакцій у ланцюжку.
Огляд взаємодії для надсилання транзакцій у Sui
Спочатку транзакції користувача надсилаються через зовнішній RPC і передаються до внутрішніх служб після базової перевірки. Сервіс Sui відповідає за подальшу перевірку корисних даних вхідних транзакцій. Після успішної перевірки підпису користувача транзакція перетворюється на сертифікат транзакції (що містить інформацію про транзакцію та підпис Суї).
Ці сертифікати транзакцій є фундаментальною частиною роботи мережі Sui і можуть поширюватися між різними вузлами перевірки в мережі. Для транзакцій створення/оновлення контракту, перш ніж їх можна буде завантажити в ланцюжок, вузол перевірки викличе верифікатор Sui, щоб перевірити та перевірити дійсність структури контракту/семантики цих сертифікатів. Саме під час цього критичного етапу перевірки вразливість «нескінченного циклу» може бути запущена та використана.
Коли уразливість була запущена, це призвело до переривання процесу перевірки на невизначений термін, фактично перешкоджаючи здатності системи обробляти нові транзакції та спричиняючи повне відключення мережі. Крім того, ситуація зберігалася після перезапуску вузла, що означало, що традиційні засоби пом’якшення були далеко неадекватними. Після того, як уразливість спрацює, буде завдано "безперервної шкоди" та залишиться тривалий вплив на всю мережу Sui.
Рішення Sui
Після відгуку від CertiK Sui своєчасно підтвердив уразливість і випустив виправлення для усунення критичної вади. Виправлення забезпечує узгодженість між змінами стану та прапорцями після змін, усуваючи критичний ефект атаки «колесо хом’яка».
Щоб усунути вищезгадану невідповідність, виправлення Sui включає невелике, але критичне налаштування функції AbstractState::join. Цей патч усуває логіку визначення результату злиття стану перед виконанням AbstractValue::join. Натомість спочатку виконайте функцію AbstractValue::join для злиття стану та встановіть злиття, порівнюючи остаточний результат оновлення з початковим значенням стану (старе _value) Позначка для змін.
Таким чином, результат об’єднання станів буде відповідати результату справжнього оновлення, і під час аналізу не відбуватиметься нескінченний цикл.
Окрім усунення цієї конкретної вразливості, Sui також розгорнув засоби пом’якшення, щоб зменшити вплив майбутніх уразливостей валідатора. Відповідно до відповіді Sui у звіті про помилку, пом’якшення включає функцію під назвою Denylist.
«Однак валідатори мають файл конфігурації вузла, який дозволяє їм тимчасово відхиляти певні класи транзакцій. Цю конфігурацію можна використовувати для тимчасового вимкнення обробки випусків і оновлень пакетів. Через цю помилку Sui запускається перед підписанням випуску або оновлення пакета tx валідатори, у той час як список заборони зупинить роботу валідатора та видалить зловмисну передачу, тимчасова заборона цих типів передачі є 100% ефективним пом’якшенням (хоча це тимчасово порушить службу для людей, які намагаються випустити або оновити код).
До речі, у нас уже деякий час є цей файл конфігурації списку заборонених пересилань, але ми також додали подібний механізм для сертифікатів як подальше пом’якшення вашої раніше повідомленої вразливості «цикл перевірки». Завдяки цьому механізму ми матимемо більше гнучкості проти цієї атаки: ми використовуватимемо конфігурацію списку заборонених сертифікатів, щоб змусити валідатори забути про погані сертифікати (порушуючи нескінченний цикл), і конфігурацію списку заборонених TX, щоб заборонити публікацію/оновлення, тим самим запобігаючи створенню нові транзакції зловмисної атаки. Дякуємо, що змусили нас подумати про це!
Валідатор має обмежену кількість «тактів» (на відміну від газу) для перевірки байт-коду перед підписанням транзакції, і якщо весь байт-код, виданий у транзакції, не можна перевірити за таку кількість тактів, валідатор відмовиться підписати транзакцію, запобігаючи . його від виконання в мережі. Раніше вимірювання застосовувалося лише до вибраного набору комплексних проходів перевірки. Щоб боротися з цим, ми поширюємо вимірювання на кожен валідатор, щоб гарантувати обмеження на роботу, яку виконує валідатор під час процесу перевірки кожного тику. Ми також виправили потенційну помилку нескінченного циклу в валідаторі витоку ідентифікатора. "
--Пояснення від розробників Sui про виправлення помилок
Загалом Denylist дозволяє валідаторам тимчасово уникати використання вразливостей у валідаторах і ефективно запобігати потенційній шкоді, спричиненій деякими зловмисними транзакціями, вимикаючи процес випуску або оновлення. Коли пом’якшувальні заходи Denylist набувають чинності, вузли гарантують, що вони можуть продовжувати роботу, жертвуючи власними функціями контракту публікації/оновлення.
Підсумуйте
У цій статті ми ділимося технічними деталями атаки «Hamster Wheel», виявленої командою CertiK Skyfall, пояснюючи, як цей новий тип атаки використовує ключові вразливості, щоб спричинити повне припинення роботи мережі Sui. Крім того, ми також уважно вивчили своєчасну відповідь Sui для вирішення цієї критичної проблеми та поділилися виправленням уразливості та подальшими методами пом’якшення подібних уразливостей.