Добавить Автора
Ранее команда CertiK обнаружила ряд уязвимостей типа «отказ в обслуживании» в блокчейне Sui. Среди этих уязвимостей выделяется новая уязвимость с высоким уровнем воздействия. Эта уязвимость может привести к тому, что узлы сети Sui не смогут обрабатывать новые транзакции, что приведет к полному отключению всей сети.
Буквально в прошлый понедельник компания CertiK получила награду SUI в размере 500 000 долларов за обнаружение этой серьезной уязвимости безопасности. CoinDesk, авторитетное СМИ в отрасли США, сообщило об инциденте, а затем крупные СМИ поддержали его сообщение и опубликовали соответствующие новости.
Эту уязвимость безопасности называют «колесом хомяка»: ее уникальный метод атаки отличается от известных в настоящее время атак. Злоумышленнику достаточно отправить полезную нагрузку размером около 100 байт, чтобы запустить бесконечный цикл в узле проверки Sui, что делает его неработоспособным. для реагирования на новые транзакции.
Кроме того, ущерб, нанесенный атакой, может сохраняться после перезапуска сети и может автоматически распространяться в сети Sui, в результате чего все узлы, как хомяк, бесконечно бегающий на колесе, не могут обрабатывать новые транзакции. Вот почему мы называем этот уникальный тип атаки атакой «колеса хомяка».

Обнаружив уязвимость, CertiK сообщила об этом Sui через программу вознаграждения за ошибки Sui. Суй также эффективно отреагировал как можно скорее, подтвердил серьезность уязвимости и активно принял соответствующие меры для устранения проблемы до запуска основной сети. Помимо исправления этой конкретной уязвимости, Sui приняла превентивные меры по снижению потенциального ущерба, который может нанести эта уязвимость.
Чтобы поблагодарить команду CertiK за ответственное раскрытие информации, Суй наградил команду CertiK бонусом в размере 500 000 долларов США.
Следующие технические подробности этой критической уязвимости будут раскрыты для выяснения основной причины и потенциального воздействия уязвимости.
Подробное объяснение уязвимостей
Ключевая роль валидаторов в Sui
Для блокчейнов, основанных на языке Move, таких как Sui и Aptos, гарантийным механизмом предотвращения атак вредоносной полезной нагрузки является в основном технология статической проверки. С помощью технологии статической проверки Sui может проверять достоверность полезной нагрузки, отправленной пользователями, прежде чем контракт будет выпущен или обновлен. Валидатор предоставляет ряд проверок для обеспечения правильности структуры и семантики. Только после прохождения проверок и проверок контракт поступает на виртуальную машину Move для исполнения.

Угрозы вредоносной полезной нагрузки в цепочке Move
Цепочка Sui предоставляет новый набор моделей хранения и интерфейсов поверх исходной виртуальной машины Move, поэтому у Sui есть настроенная версия виртуальной машины Move. Для поддержки новых примитивов хранения Sui дополнительно вводит ряд дополнительных настраиваемых проверок безопасности ненадежных полезных данных, таких как безопасность объектов и доступ к глобальному хранилищу. Эти специальные проверки соответствуют уникальным функциям Sui, поэтому мы называем их валидаторами Sui.

Порядок Суи по проверке нагрузки
Как показано на рисунке выше, большинство проверок в валидаторе выполняют проверку безопасности на структурном уровне в отношении CompiledModule (который представляет собой запуск полезных данных контракта, предоставленных пользователем). Например, используйте «Проверку дубликатов», чтобы убедиться в отсутствии повторяющихся записей в полезных данных среды выполнения; используйте «Проверку ограничений», чтобы убедиться, что длина каждого поля в полезных данных среды выполнения находится в пределах допустимого предела записей.
Помимо проверок на структурном уровне, статическая проверка верификатора по-прежнему требует более сложных методов анализа, чтобы обеспечить надежность недоверенной полезной нагрузки на семантическом уровне.
Узнайте об абстрактном интерпретаторе Move:
Линейный и итеративный анализ
Абстрактный интерпретатор, предоставляемый Move, — это платформа, специально разработанная для выполнения сложного анализа безопасности байт-кода посредством абстрактной интерпретации. Этот механизм делает процесс проверки более совершенным и точным, и каждый проверяющий может определить свое уникальное абстрактное состояние для анализа.
При запуске выполнения абстрактный интерпретатор строит граф потока управления (CFG) из скомпилированных модулей. Каждый базовый блок в этих конфигурациях поддерживает набор состояний, а именно «состояние предварительного заказа» и «состояние после заказа». «Состояние предварительного заказа» обеспечивает снимок состояния программы до выполнения базового блока, а «состояние после заказа» обеспечивает описание состояния программы после выполнения базового блока.
Когда абстрактный интерпретатор не обнаруживает скачков (или циклов) в графе потока управления, он следует простому линейному принципу выполнения: каждый базовый блок анализируется по очереди, а предыдущая инструкция вычисляется на основе семантики каждой инструкции в блоке. последовательное состояние и постпоследовательное состояние. Результатом является точный снимок состояния каждого базового уровня блока программы во время выполнения, что помогает проверить свойства безопасности программы.

Переместить рабочий процесс абстрактного интерпретатора
Однако этот процесс усложняется, когда в потоке управления имеются петли. Появление цикла означает, что граф потока управления содержит ребро отскока. Источник ребра отскока соответствует последующему состоянию текущего базового блока, а целевой базовый блок (заголовок цикла) ребра отскока является ранее проанализированным. Состояние предварительного заказа базового блока, поэтому абстрактному интерпретатору необходимо тщательно объединить состояния двух базовых блоков, связанные с переходом.
Если обнаруживается, что объединенное состояние отличается от существующего предварительного состояния базового блока головы цикла, абстрактный интерпретатор обновляет состояние базового блока головы цикла и перезапускает анализ, начиная с этого базового блока. Этот итеративный процесс анализа продолжается до тех пор, пока предварительное состояние цикла не станет стабильным. Другими словами, этот процесс повторяется до тех пор, пока состояние предварительного заказа базового блока в начале цикла больше не будет меняться между итерациями. Достижение фиксированной точки означает, что анализ цикла завершен.
Sui IDLeak валидатор:
Индивидуальный анализ абстрактной интерпретации
В отличие от оригинального дизайна Move, блокчейн-платформа Sui представляет уникальную модель глобального хранения, ориентированную на «цели». Примечательной особенностью этой модели является то, что любая структура данных с ключевым атрибутом (хранящимся как индекс в цепочке) должна иметь тип идентификатора в качестве первого поля структуры. Поле ID является неизменяемым и не может быть перенесено на другие цели, поскольку каждый объект должен иметь глобально уникальный идентификатор. Чтобы обеспечить эти свойства, Суй создал набор собственной логики анализа поверх абстрактного интерпретатора.

Верификатор IDLeak, также известный как id_leak_verifier, работает совместно с абстрактным интерпретатором для выполнения анализа. Он имеет свой собственный уникальный AbstractDomain, называемый AbstractState. Каждое AbstractState состоит из AbstractValue, соответствующего множеству локальных переменных. Отслеживайте состояние каждой локальной переменной с помощью AbstractValue, чтобы отслеживать, является ли переменная идентификатора новой.
В процессе упаковки структуры валидатор IDLeak позволяет упаковать в структуру только новый идентификатор. Посредством анализа абстрактной интерпретации валидатор IDLeak может полностью отслеживать состояние локального потока данных, чтобы гарантировать, что существующие идентификаторы не передаются другим объектам структуры.
Проблема несогласованности обслуживания состояния валидатора Sui IDLeak
Валидатор IDLeak интегрирован с абстрактным интерпретатором Move путем реализации функции AbstractState::join. Эта функция играет важную роль в управлении состоянием, особенно при слиянии и обновлении значений состояния.
Подробно изучите эти функции, чтобы понять их работу:

В AbstractState::join функция принимает на вход другое AbstractState и пытается объединить его локальное состояние с локальным состоянием текущего объекта. Для каждой локальной переменной во входном состоянии он сравнивает значение переменной с ее текущим значением в локальном состоянии (если оно не найдено, по умолчанию используется AbstractValue::Other). Если два значения не равны, он установит флаг «изменено» в качестве основы для определения того, изменился ли конечный результат слияния состояния, и обновит значение локальной переменной в локальном состоянии, вызвав 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, используя полезную нагрузку размером всего около 100 байт для использования всех циклов ЦП узла Sui, эффективно предотвращая обработку новых транзакций и вызывая отказ в обслуживании в сети Sui. .
Постоянный вред атак «колесо хомяка» в сети Sui
Программа Sui по вознаграждению за обнаружение ошибок имеет строгие правила оценки уровней уязвимости, в основном основанные на степени ущерба для всей сети. Уязвимость, которая соответствует «критическому» рейтингу, должна отключать всю сеть и эффективно предотвращать подтверждение новых транзакций, а также требует хард-форка для устранения проблемы, если уязвимость может привести только к отказу в обслуживании некоторых сетевых узлов; уязвимости имеют рейтинг не более «среднего риска» (среднего)» или «высокого риска (высокого)».
Уязвимость «колесо хомяка», обнаруженная командой CertiK Skyfall, может отключить всю сеть Sui и требует официального выпуска новой версии для ее обновления и исправления. Учитывая серьезность уязвимости, Суй в конечном итоге оценил ее как «критическую». Чтобы лучше понять серьезное влияние атаки «колесо хомяка», нам необходимо понять сложную архитектуру внутренней системы Sui, особенно весь процесс выпуска или обновления внутрисетевых транзакций.

Обзор взаимодействия для отправки транзакций в Sui
Первоначально пользовательские транзакции передаются через внешний RPC и передаются во внутреннюю службу после базовой проверки. Серверная служба Sui отвечает за дальнейшую проверку полезной нагрузки входящей транзакции. После успешной проверки подписи пользователя транзакция преобразуется в сертификат транзакции (содержащий информацию о транзакции, а также подпись Суи).
Эти сертификаты транзакций являются фундаментальной частью работы сети Sui и могут распространяться между различными узлами проверки в сети. Для транзакций создания/обновления контракта узел проверки вызывает валидатор Sui для проверки и подтверждения действительности структуры/семантики контракта этих сертификатов, прежде чем его можно будет поместить в цепочку. Именно на этом критическом этапе проверки может быть активирована и использована уязвимость «бесконечного цикла».
При срабатывании уязвимости процесс проверки прерывается на неопределенный срок, что фактически ограничивает способность системы обрабатывать новые транзакции и приводит к полному отключению сети. Что еще хуже, ситуация все еще существует после перезапуска узла, а это означает, что традиционных мер по смягчению последствий недостаточно. Как только эта уязвимость сработает, произойдет «постоянный ущерб», оставляющий долгосрочное воздействие на всю сеть Sui.
Решение Суи
После получения отзыва от CertiK Суй оперативно подтвердил наличие уязвимости и выпустил исправление для ее устранения. Исправление обеспечивает согласованность между изменениями состояния и флагами после изменения, устраняя критическое воздействие атак типа «колесо хомяка».

Чтобы устранить указанное выше несоответствие, исправление Sui включает небольшую, но важную корректировку функции AbstractState::join. Этот патч удаляет логику определения результата слияния состояний перед выполнением AbstractValue::join. Вместо этого он сначала выполняет функцию AbstractValue::join для выполнения слияния состояний и устанавливает, происходит ли слияние, путем сравнения окончательного результата обновления с исходным состоянием. значение (old_value).
Таким образом, результат слияния состояний будет соответствовать результату реального обновления, и в процессе анализа не возникнет бесконечного цикла.
Помимо исправления этой конкретной уязвимости, Sui предпринял меры по снижению воздействия будущих уязвимостей валидатора. Согласно ответу Суи в отчете об ошибке, устранение проблемы включает в себя функцию Denylist.
«Однако у валидаторов есть файл конфигурации узла, который позволяет им временно отклонять определенные категории транзакций. Эту конфигурацию можно использовать для временного отключения обработки выпусков и обновлений пакетов. Из-за этой ошибки необходимо запускать Sui перед подписанием выпуска или пакета. обновить tx, в то время как список запретов остановит работу валидатора и удалит вредоносную передачу, временно запретить внесение в список этих типов передачи является 100% эффективным средством смягчения последствий (хотя это временно нарушит обслуживание для любого, кто пытается выпустить или обновить код).
Между прочим, этот файл конфигурации списка запрета передачи уже давно у нас есть, но мы также добавили аналогичный механизм для сертификатов в качестве последующего устранения уязвимости «бесконечный цикл валидатора», о которой вы сообщали ранее. При наличии этого механизма у нас будет больше гибкости при этой атаке: мы будем использовать конфигурацию списка запрещенных сертификатов, чтобы заставить валидатор забыть о плохих сертификатах (разрыв бесконечного цикла), а также конфигурацию списка запрещенных TX для отключения выпусков/обновлений. тем самым предотвращая создание новых транзакций вредоносных атак. Спасибо, что заставили нас задуматься об этом!
Валидатор имеет ограниченное количество «тиков» (в отличие от газа) для проверки байт-кода перед подписанием транзакции. Если весь байт-код, выданный в транзакции, не может быть проверен за такое количество тиков, валидатор откажется подписывать транзакцию, предотвращая ее выполнение в сети. Раньше измерение работало только для избранного набора сложных проходов валидатора. Чтобы решить эту проблему, мы расширяем измерение для каждого валидатора, чтобы гарантировать наличие ограничений на работу, выполняемую валидатором во время процесса проверки каждого тика. Мы также исправили потенциальную ошибку бесконечного цикла в валидаторе утечки идентификаторов. "
--Инструкции от разработчиков Sui по исправлению ошибок
В целом Denylist позволяет валидаторам временно обходить эксплойты в валидаторах и эффективно предотвращать потенциальный ущерб, вызванный некоторыми вредоносными транзакциями, путем отключения процесса выпуска или обновления. Когда меры по смягчению последствий Denylist вступают в силу, узлы гарантируют, что они могут продолжать работать, жертвуя своими собственными функциями контракта публикации/обновления.

Подвести итог
В этой статье мы делимся техническими подробностями атаки «колесо хомяка», обнаруженной командой CertiK Skyfall, и объясняем, как этот новый тип атаки использует ключевые уязвимости, приводя к полному отключению сети Sui. Кроме того, мы также внимательно рассмотрели своевременную реакцию Суи на устранение этой критической проблемы и поделились исправлением уязвимости и последующими методами устранения подобных уязвимостей.
