Ранее команда CertiK обнаружила серию уязвимостей отказа в обслуживании в блокчейне Sui. Среди этих уязвимостей выделяется новая уязвимость с высоким уровнем воздействия. Эта уязвимость может привести к тому, что узлы сети Sui не смогут обрабатывать новые транзакции, а эффект будет эквивалентен полному отключению всей сети.
Буквально в прошлый понедельник CertiK получила вознаграждение в размере 500 000 долларов США от SUI за обнаружение этой серьезной уязвимости в системе безопасности. 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
Однако процесс усложняется, когда в потоке управления есть циклы. Появление цикла означает, что граф потока управления содержит ребро возврата, источник которого соответствует последующему состоянию текущего базового блока, а целевой базовый блок (головка цикла) перехода задний край — это ранее проанализированный. Поэтому абстрактному интерпретатору необходимо тщательно объединить состояния двух базовых блоков, связанных с возвратом.
Если обнаруживается, что объединенное состояние отличается от существующего состояния предварительного порядка базового блока заголовка цикла, абстрактный интерпретатор обновляет состояние базового блока заголовка цикла и перезапускает анализ, начиная с этого базового блока. Этот итеративный процесс анализа будет продолжаться до тех пор, пока предварительное состояние цикла не стабилизируется. Другими словами, этот процесс повторяется до тех пор, пока состояние предварительного порядка базового блока начала цикла не перестанет меняться между итерациями. Достижение фиксированной точки означает, что анализ цикла завершен.
Sui IDLeak Validator: индивидуальный анализ абстрактной интерпретации
В отличие от оригинального дизайна Move, блокчейн-платформа Sui представляет уникальную модель глобального хранилища, ориентированную на «цель». Примечательной особенностью этой модели является то, что любая структура данных с ключевым атрибутом (хранящимся в цепочке как индекс) должна иметь тип ID в качестве первого поля структуры. Поле ID неизменяемое и не может быть передано другим объектам, так как каждый объект должен иметь глобально уникальный ID. Чтобы обеспечить эти свойства, Суи построил набор пользовательской логики анализа поверх абстрактного интерпретатора.
Верификатор IDLeak, также известный как id_leak_verifier, работает в сочетании с абстрактным интерпретатором для анализа. У него есть собственный уникальный AbstractDomain, который называется AbstractState. Каждое AbstractState состоит из AbstractValue, соответствующих нескольким локальным переменным. AbstractValue отслеживает состояние каждой локальной переменной, чтобы отслеживать, является ли переменная ID совершенно новой.
В процессе упаковки структуры валидатор 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, используя все циклы ЦП узла Sui с полезной нагрузкой всего около 100 байт, эффективно предотвращая обработку новых транзакций и вызывая отказ в обслуживании в сети Sui.
Атака «Колесо хомяка» в сети Sui постоянный вред
Программа Sui Bug Bounty имеет строгие правила оценки уровней уязвимости, в основном на основе степени вреда для всей сети. Уязвимости, которые соответствуют «критическому» рейтингу, должны отключать всю сеть и эффективно предотвращать новые подтверждения транзакций, а также требовать хард-форка для устранения проблемы; (средний)» или «высокий риск (высокий)» уязвимости.
Уязвимость «колесо хомяка», обнаруженная командой CertiK Skyfall, может отключить всю сеть Sui и требует официального выпуска новой версии для обновления и исправления. Суи в конечном итоге оценил уязвимость как «критическую» на основе ее критичности. Чтобы лучше понять серьезное влияние, вызванное атакой «колесо хомяка», нам необходимо понять сложную архитектуру серверной системы Sui, особенно весь процесс публикации или обновления транзакций в цепочке.
Обзор взаимодействий для отправки транзакций в Sui
Первоначально пользовательские транзакции отправляются через внешний RPC и передаются внутренним службам после базовой проверки. Серверная служба Sui отвечает за дальнейшую проверку полезной нагрузки входящих транзакций. После успешной проверки подписи пользователя транзакция преобразуется в сертификат транзакции (содержащий информацию о транзакции и подпись Суи).
Эти сертификаты транзакций являются фундаментальной частью работы сети Sui и могут распространяться среди различных узлов проверки в сети. Для транзакций создания/обновления контракта, прежде чем их можно будет загрузить в цепочку, узел проверки вызовет верификатор Sui, чтобы проверить действительность структуры контракта/семантики этих сертификатов. Именно на этом критическом этапе проверки можно активировать и использовать уязвимость «бесконечный цикл».
Когда уязвимость сработала, процесс проверки был прерван на неопределенный срок, что фактически затруднило способность системы обрабатывать новые транзакции и привело к полному отключению сети. Вдобавок ко всему, ситуация сохранялась после перезапуска узла, а это означало, что традиционные меры по смягчению последствий были далеко не адекватными. Как только уязвимость сработает, будет нанесен «постоянный ущерб», который окажет длительное влияние на всю сеть Sui.
Решение Sui
Получив обратную связь от CertiK, Sui своевременно подтвердил наличие уязвимости и выпустил исправление для устранения критической уязвимости. Исправление обеспечивает согласованность между изменениями состояния и флагами после изменения, устраняя критический эффект атаки «Колесо хомяка».
Чтобы устранить вышеупомянутое несоответствие, исправление Sui включает небольшую, но важную настройку функции AbstractState::join. Этот патч убирает логику определения результата слияния состояний перед выполнением AbstractValue::join.Вместо этого сначала выполните функцию AbstractValue::join для слияния состояний и задайте слияние, сравнивая окончательный результат обновления с исходным значением состояния (старым _value) Флаг для изменений.
Таким образом, результат слияния состояний будет соответствовать результату реального обновления, и в процессе анализа не возникнет бесконечный цикл.
В дополнение к устранению этой конкретной уязвимости Sui также развернула меры по уменьшению влияния будущих уязвимостей валидатора. Согласно ответу Суи в отчете об ошибке, смягчение включает функцию под названием Denylist.
«Однако у валидаторов есть файл конфигурации узла, который позволяет им временно отклонять определенные классы транзакций. Эту конфигурацию можно использовать для временного отключения обработки выпусков и обновлений пакетов. Из-за этой ошибки Sui запускается перед подписанием tx обновления выпуска или пакета. валидаторов, в то время как список запрещенных остановит запуск валидатора и удалит вредоносный tx, временное занесение этих типов tx в черный список является 100% эффективным средством смягчения последствий (хотя это временно нарушит обслуживание людей, пытающихся выпустить или обновить код).
Между прочим, у нас уже некоторое время есть этот файл конфигурации списка запрещенных TX, но мы также добавили аналогичный механизм для сертификатов в качестве последующего смягчения вашей ранее обнаруженной уязвимости «цикл проверки». Благодаря этому механизму у нас будет больше гибкости против этой атаки: мы будем использовать конфигурацию списка запрещенных сертификатов, чтобы валидаторы забыли о плохих сертификатах (разорвав бесконечный цикл), и конфигурацию списка запрещенных TX, чтобы запретить публикацию/обновление, тем самым предотвращая создание новые транзакции вредоносных атак. Спасибо, что заставили нас задуматься об этом!
Валидатор имеет ограниченное количество «тиков» (отличное от газа) для проверки байт-кода перед подписанием транзакции, и если весь байт-код, выданный в транзакции, не может быть проверен за это количество тиков, валидатор откажется подписывать транзакцию, предотвращая это от выполнения в сети. Раньше измерение применялось только к выбранному набору сложных проходов валидатора. Чтобы бороться с этим, мы распространяем измерения на каждого валидатора, чтобы гарантировать ограничение на работу, которую валидатор выполняет в процессе проверки каждого тика. Мы также исправили потенциальную ошибку бесконечного цикла в валидаторе утечки идентификаторов. "
--Инструкции от разработчиков Sui по исправлению ошибок
В целом, Denylist позволяет валидаторам временно избегать использования уязвимостей в валидаторах и эффективно предотвращать потенциальный ущерб, вызванный некоторыми вредоносными транзакциями, путем отключения процесса выпуска или обновления. Когда меры по смягчению последствий Denylist вступают в силу, узлы гарантируют, что они могут продолжать работать, жертвуя своими собственными функциями публикации/обновления контракта.
Подведем итог
В этой статье мы делимся техническими подробностями атаки «Колесо хомяка», обнаруженной командой CertiK Skyfall, и объясняем, как этот новый тип атаки использует ключевые уязвимости, чтобы вызвать полное отключение сети Sui. Кроме того, мы также внимательно изучили своевременную реакцию Sui на исправление этой критической проблемы и поделились исправлением уязвимости и последующими методами устранения аналогичных уязвимостей.
Посмотреть Оригинал
Содержание носит исключительно справочный характер и не является предложением или офертой. Консультации по инвестициям, налогообложению или юридическим вопросам не предоставляются. Более подробную информацию о рисках см. в разделе «Дисклеймер».
Углубленный анализ технических деталей последней уязвимости «Колесо хомяка» в публичной сети Sui.
Ранее команда CertiK обнаружила серию уязвимостей отказа в обслуживании в блокчейне Sui. Среди этих уязвимостей выделяется новая уязвимость с высоким уровнем воздействия. Эта уязвимость может привести к тому, что узлы сети Sui не смогут обрабатывать новые транзакции, а эффект будет эквивалентен полному отключению всей сети.
Буквально в прошлый понедельник CertiK получила вознаграждение в размере 500 000 долларов США от SUI за обнаружение этой серьезной уязвимости в системе безопасности. 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
Однако процесс усложняется, когда в потоке управления есть циклы. Появление цикла означает, что граф потока управления содержит ребро возврата, источник которого соответствует последующему состоянию текущего базового блока, а целевой базовый блок (головка цикла) перехода задний край — это ранее проанализированный. Поэтому абстрактному интерпретатору необходимо тщательно объединить состояния двух базовых блоков, связанных с возвратом.
Если обнаруживается, что объединенное состояние отличается от существующего состояния предварительного порядка базового блока заголовка цикла, абстрактный интерпретатор обновляет состояние базового блока заголовка цикла и перезапускает анализ, начиная с этого базового блока. Этот итеративный процесс анализа будет продолжаться до тех пор, пока предварительное состояние цикла не стабилизируется. Другими словами, этот процесс повторяется до тех пор, пока состояние предварительного порядка базового блока начала цикла не перестанет меняться между итерациями. Достижение фиксированной точки означает, что анализ цикла завершен.
Sui IDLeak Validator: индивидуальный анализ абстрактной интерпретации
В отличие от оригинального дизайна Move, блокчейн-платформа Sui представляет уникальную модель глобального хранилища, ориентированную на «цель». Примечательной особенностью этой модели является то, что любая структура данных с ключевым атрибутом (хранящимся в цепочке как индекс) должна иметь тип ID в качестве первого поля структуры. Поле ID неизменяемое и не может быть передано другим объектам, так как каждый объект должен иметь глобально уникальный ID. Чтобы обеспечить эти свойства, Суи построил набор пользовательской логики анализа поверх абстрактного интерпретатора.
Верификатор IDLeak, также известный как id_leak_verifier, работает в сочетании с абстрактным интерпретатором для анализа. У него есть собственный уникальный AbstractDomain, который называется AbstractState. Каждое AbstractState состоит из AbstractValue, соответствующих нескольким локальным переменным. AbstractValue отслеживает состояние каждой локальной переменной, чтобы отслеживать, является ли переменная ID совершенно новой.
В процессе упаковки структуры валидатор 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, используя все циклы ЦП узла Sui с полезной нагрузкой всего около 100 байт, эффективно предотвращая обработку новых транзакций и вызывая отказ в обслуживании в сети Sui.
Атака «Колесо хомяка» в сети Sui постоянный вред
Программа Sui Bug Bounty имеет строгие правила оценки уровней уязвимости, в основном на основе степени вреда для всей сети. Уязвимости, которые соответствуют «критическому» рейтингу, должны отключать всю сеть и эффективно предотвращать новые подтверждения транзакций, а также требовать хард-форка для устранения проблемы; (средний)» или «высокий риск (высокий)» уязвимости.
Уязвимость «колесо хомяка», обнаруженная командой CertiK Skyfall, может отключить всю сеть Sui и требует официального выпуска новой версии для обновления и исправления. Суи в конечном итоге оценил уязвимость как «критическую» на основе ее критичности. Чтобы лучше понять серьезное влияние, вызванное атакой «колесо хомяка», нам необходимо понять сложную архитектуру серверной системы Sui, особенно весь процесс публикации или обновления транзакций в цепочке.
Обзор взаимодействий для отправки транзакций в Sui
Первоначально пользовательские транзакции отправляются через внешний RPC и передаются внутренним службам после базовой проверки. Серверная служба Sui отвечает за дальнейшую проверку полезной нагрузки входящих транзакций. После успешной проверки подписи пользователя транзакция преобразуется в сертификат транзакции (содержащий информацию о транзакции и подпись Суи).
Эти сертификаты транзакций являются фундаментальной частью работы сети Sui и могут распространяться среди различных узлов проверки в сети. Для транзакций создания/обновления контракта, прежде чем их можно будет загрузить в цепочку, узел проверки вызовет верификатор Sui, чтобы проверить действительность структуры контракта/семантики этих сертификатов. Именно на этом критическом этапе проверки можно активировать и использовать уязвимость «бесконечный цикл».
Когда уязвимость сработала, процесс проверки был прерван на неопределенный срок, что фактически затруднило способность системы обрабатывать новые транзакции и привело к полному отключению сети. Вдобавок ко всему, ситуация сохранялась после перезапуска узла, а это означало, что традиционные меры по смягчению последствий были далеко не адекватными. Как только уязвимость сработает, будет нанесен «постоянный ущерб», который окажет длительное влияние на всю сеть Sui.
Решение Sui
Получив обратную связь от CertiK, Sui своевременно подтвердил наличие уязвимости и выпустил исправление для устранения критической уязвимости. Исправление обеспечивает согласованность между изменениями состояния и флагами после изменения, устраняя критический эффект атаки «Колесо хомяка».
Чтобы устранить вышеупомянутое несоответствие, исправление Sui включает небольшую, но важную настройку функции AbstractState::join. Этот патч убирает логику определения результата слияния состояний перед выполнением AbstractValue::join.Вместо этого сначала выполните функцию AbstractValue::join для слияния состояний и задайте слияние, сравнивая окончательный результат обновления с исходным значением состояния (старым _value) Флаг для изменений.
Таким образом, результат слияния состояний будет соответствовать результату реального обновления, и в процессе анализа не возникнет бесконечный цикл.
В дополнение к устранению этой конкретной уязвимости Sui также развернула меры по уменьшению влияния будущих уязвимостей валидатора. Согласно ответу Суи в отчете об ошибке, смягчение включает функцию под названием Denylist.
«Однако у валидаторов есть файл конфигурации узла, который позволяет им временно отклонять определенные классы транзакций. Эту конфигурацию можно использовать для временного отключения обработки выпусков и обновлений пакетов. Из-за этой ошибки Sui запускается перед подписанием tx обновления выпуска или пакета. валидаторов, в то время как список запрещенных остановит запуск валидатора и удалит вредоносный tx, временное занесение этих типов tx в черный список является 100% эффективным средством смягчения последствий (хотя это временно нарушит обслуживание людей, пытающихся выпустить или обновить код).
Между прочим, у нас уже некоторое время есть этот файл конфигурации списка запрещенных TX, но мы также добавили аналогичный механизм для сертификатов в качестве последующего смягчения вашей ранее обнаруженной уязвимости «цикл проверки». Благодаря этому механизму у нас будет больше гибкости против этой атаки: мы будем использовать конфигурацию списка запрещенных сертификатов, чтобы валидаторы забыли о плохих сертификатах (разорвав бесконечный цикл), и конфигурацию списка запрещенных TX, чтобы запретить публикацию/обновление, тем самым предотвращая создание новые транзакции вредоносных атак. Спасибо, что заставили нас задуматься об этом!
Валидатор имеет ограниченное количество «тиков» (отличное от газа) для проверки байт-кода перед подписанием транзакции, и если весь байт-код, выданный в транзакции, не может быть проверен за это количество тиков, валидатор откажется подписывать транзакцию, предотвращая это от выполнения в сети. Раньше измерение применялось только к выбранному набору сложных проходов валидатора. Чтобы бороться с этим, мы распространяем измерения на каждого валидатора, чтобы гарантировать ограничение на работу, которую валидатор выполняет в процессе проверки каждого тика. Мы также исправили потенциальную ошибку бесконечного цикла в валидаторе утечки идентификаторов. "
--Инструкции от разработчиков Sui по исправлению ошибок
В целом, Denylist позволяет валидаторам временно избегать использования уязвимостей в валидаторах и эффективно предотвращать потенциальный ущерб, вызванный некоторыми вредоносными транзакциями, путем отключения процесса выпуска или обновления. Когда меры по смягчению последствий Denylist вступают в силу, узлы гарантируют, что они могут продолжать работать, жертвуя своими собственными функциями публикации/обновления контракта.
Подведем итог
В этой статье мы делимся техническими подробностями атаки «Колесо хомяка», обнаруженной командой CertiK Skyfall, и объясняем, как этот новый тип атаки использует ключевые уязвимости, чтобы вызвать полное отключение сети Sui. Кроме того, мы также внимательно изучили своевременную реакцию Sui на исправление этой критической проблемы и поделились исправлением уязвимости и последующими методами устранения аналогичных уязвимостей.