Анализ уязвимостей компилятора Solidity и стратегии противодействия
Компилятор является одним из основных компонентов современных компьютерных систем, его основная функция заключается в преобразовании исходного кода высокоуровневого языка программирования в исполняемый код инструкций, понятный низкоуровневому CPU или виртуальной машине.
Хотя большинство разработчиков и специалистов по безопасности обычно больше сосредоточены на безопасности кода приложений, безопасность самого компилятора также имеет важное значение. Как компьютерная программа, компилятор также может иметь уязвимости, которые в некоторых случаях могут представлять серьезные риски безопасности.
Например, в браузере, в процессе компиляции и выполнения кода JavaScript на стороне клиента, из-за уязвимостей движка разбора JavaScript злоумышленники могут использовать эти уязвимости для удаленного выполнения кода, когда пользователь посещает вредоносные веб-страницы, в конечном итоге получая контроль над браузером жертвы или даже операционной системой. Кроме того, ошибки компилятора C++ также могут привести к серьезным последствиям, таким как удаленное выполнение кода.
В компиляторе Solidity также имеются уязвимости безопасности. Согласно предупреждениям о безопасности от команды разработчиков Solidity, в нескольких версиях компилятора Solidity обнаружены уязвимости.
Уязвимость компилятора Solidity
Роль компилятора Solidity заключается в преобразовании кода смарт-контракта в машинный код инструкций Ethereum Virtual Machine (EVM), который упаковывается и загружается на Ethereum через транзакции, а затем интерпретируется и выполняется EVM.
Важно отметить, что уязвимости компилятора Solidity отличаются от уязвимостей самого EVM. Уязвимости EVM относятся к проблемам безопасности, возникающим при выполнении инструкций виртуальной машины, которые могут повлиять на всю сеть Ethereum. В то время как уязвимости компилятора Solidity относятся к проблемам, возникающим при преобразовании Solidity в код EVM, которые не влияют непосредственно на саму сеть Ethereum.
Одна из опасностей уязвимости компилятора Solidity заключается в том, что это может привести к несоответствию сгенерированного EVM-кода ожиданиям разработчиков смарт-контрактов. Поскольку смарт-контракты на Ethereum обычно связаны с криптовалютными активами пользователей, любые ошибки, вызванные компилятором, могут привести к потерям активов пользователей и вызвать серьезные последствия.
Разработчики и аудиторы контрактов могут сосредоточиться на проблемах реализации логики кода контракта, а также на вопросах безопасности на уровне Solidity, таких как повторный вход и переполнение целых чисел. Однако уязвимости компилятора Solidity трудно обнаружить только с помощью аудита логики исходного кода контракта. Необходимо совместно анализировать конкретные версии компилятора и определенные модели кода, чтобы определить, подвержен ли смарт-контракт уязвимостям компилятора.
Пример уязвимости компилятора Solidity
Вот несколько примеров реальных уязвимостей компилятора Solidity, которые демонстрируют конкретные формы, причины и последствия.
SOL-2016-9 ВысокийПорядокБайтовОчисткиХранилища
Уязвимость существует в более ранних версиях компилятора Solidity (>=0.1.6 <0.4.4).
Рассмотрим следующий код:
солидность
контракт C {
uint32 a = 0x12345678;
uint32 b = 0;
функция run() возвращает (uint256) {
a += 1;
вернуть b;
}
}
Переменная хранения b не была изменена, поэтому функция run() должна возвращать значение по умолчанию 0. Однако в коде, сгенерированном уязвимой версией компилятора, функция run() будет возвращать 1.
Такая ситуация, не соответствующая ожиданиям, может привести к серьезным последствиям, если переменная b используется для проверки прав доступа, учета активов и других целей.
Причина возникновения этой ситуации заключается в том, что EVM использует элементы стека размером 32 байта, в то время как Solidity поддерживает более мелкие типы данных, такие как uint32. Компилятор при обработке этих типов должен очищать старшие разряды, но не правильно обрабатывает их при переполнении целого числа, что приводит к записи 1 бита старшего разряда в соседнюю переменную b.
Уязвимость существует в компиляторах версий от 0.8.13 до 0.8.15.
Рассмотрим следующий код:
солидность
контракт C {
функция f() публичная чистая возвращает (uint) {
ассемблер {
mstore(0, 0x42)
}
uint x;
ассемблер {
x := mload(0)
}
вернуть x;
}
}
Уязвимость возникает из-за оптимизации компиляции. Компилятор анализирует и оптимизирует отдельные блоки ассемблера; если операция записи в память не будет прочитана позже, она будет удалена для экономии газа. Однако записи и чтения памяти в приведенном выше коде находятся в двух разных блоках ассемблера, и компилятор ошибочно считает первую запись избыточной и удаляет ее, что приводит к тому, что функция f() возвращает 0 вместо правильного 0x42.
Уязвимость затрагивает компиляторы версии от 0.5.8 до 0.8.16.
Рассмотрите следующий код:
солидность
контракт C {
функция f(bytes4[] calldata a) внешняя чистая возвращает (bytes4[] память) {
return abi.decode(abi.encode(a), (bytes4[]));
}
}
В нормальных условиях этот код должен возвращать переменную a. Но в уязвимой версии, если ввести "aaaa", будет возвращен пустой массив.
Это произошло из-за того, что Solidity неправильно очистил некоторые данные при выполнении операции abi.encode над массивами типа calldata, что привело к изменению соседних данных и к несоответствию данных после кодирования и декодирования.
Стоит отметить, что при выполнении внешних вызовов и эмитации событий в Solidity параметры неявно кодируются с помощью abi.encode, поэтому вероятность появления таких уязвимостей может быть выше, чем предполагается.
Рекомендации по безопасности
В связи с уязвимостями компилятора Solidity, разработчикам и специалистам по безопасности рекомендуется следующее:
Для разработчиков:
Используйте более новую версию компилятора Solidity. Новые версии обычно исправляют известные проблемы безопасности.
Усовершенствовать тестовые случаи модулей. Большинство ошибок на уровне компилятора могут приводить к тому, что результаты выполнения кода не соответствуют ожиданиям; повышение покрытия тестами может максимально избежать таких проблем.
По возможности избегайте использования встроенного ассемблера, сложного ABI кодирования и декодирования и других операций, не следует слепо использовать новые функции и экспериментальные возможности. Большинство уязвимостей компилятора связано с этими сложными операциями.
Для безопасных сотрудников:
При аудите кода Solidity не игнорируйте потенциальные риски безопасности, которые могут быть вызваны компилятором.
Внутри процесса разработки настоятельно рекомендуется команде разработчиков обновить версию компилятора Solidity, можно рассмотреть возможность внедрения автоматической проверки версии компилятора в процессе CI/CD.
Не стоит чрезмерно беспокоиться о уязвимостях компилятора, большинство уязвимостей срабатывают только в определенных кодовых паттернах, и необходимо оценить реальное влияние в зависимости от конкретной ситуации проекта.
Некоторые полезные ресурсы:
Регулярные предупреждения о безопасности от команды Solidity
Список ошибок, регулярно обновляемый официальным репозиторием Solidity
Список ошибок компилятора для всех версий
В правом верхнем углу страницы кода контракта на Etherscan треугольный восклицательный знак может указывать на существующие уязвимости в текущей версии компилятора.
Таким образом, уязвимость компилятора Solidity является значительным риском безопасности при разработке смарт-контрактов. Разработчики и специалисты по безопасности должны быть бдительными и принимать соответствующие меры для снижения потенциальных угроз, связанных с такими уязвимостями.
Посмотреть Оригинал
На этой странице может содержаться сторонний контент, который предоставляется исключительно в информационных целях (не в качестве заявлений/гарантий) и не должен рассматриваться как поддержка взглядов компании Gate или как финансовый или профессиональный совет. Подробности смотрите в разделе «Отказ от ответственности» .
10 Лайков
Награда
10
8
Поделиться
комментарий
0/400
BlockDetective
· 07-07 07:59
Снова попал в ловушку, обновление gkd
Посмотреть ОригиналОтветить0
liquidation_surfer
· 07-06 14:45
Снова возникло куча ошибок.
Посмотреть ОригиналОтветить0
GasFeeCrier
· 07-04 08:26
Официальная версия, которую все время обновляют, кто-то кто-то
Посмотреть ОригиналОтветить0
DoomCanister
· 07-04 08:24
Пора идти исправлять код.
Посмотреть ОригиналОтветить0
Token_Sherpa
· 07-04 08:23
ngmi если ты не проверяешь версии компилятора, если честно... видел слишком много историй о крахах
Посмотреть ОригиналОтветить0
PonziDetector
· 07-04 08:21
Снова пришло время охоты на уязвимости, которое я так люблю.
Анализ уязвимостей компилятора Solidity и стратегии реагирования
Анализ уязвимостей компилятора Solidity и стратегии противодействия
Компилятор является одним из основных компонентов современных компьютерных систем, его основная функция заключается в преобразовании исходного кода высокоуровневого языка программирования в исполняемый код инструкций, понятный низкоуровневому CPU или виртуальной машине.
Хотя большинство разработчиков и специалистов по безопасности обычно больше сосредоточены на безопасности кода приложений, безопасность самого компилятора также имеет важное значение. Как компьютерная программа, компилятор также может иметь уязвимости, которые в некоторых случаях могут представлять серьезные риски безопасности.
Например, в браузере, в процессе компиляции и выполнения кода JavaScript на стороне клиента, из-за уязвимостей движка разбора JavaScript злоумышленники могут использовать эти уязвимости для удаленного выполнения кода, когда пользователь посещает вредоносные веб-страницы, в конечном итоге получая контроль над браузером жертвы или даже операционной системой. Кроме того, ошибки компилятора C++ также могут привести к серьезным последствиям, таким как удаленное выполнение кода.
В компиляторе Solidity также имеются уязвимости безопасности. Согласно предупреждениям о безопасности от команды разработчиков Solidity, в нескольких версиях компилятора Solidity обнаружены уязвимости.
Уязвимость компилятора Solidity
Роль компилятора Solidity заключается в преобразовании кода смарт-контракта в машинный код инструкций Ethereum Virtual Machine (EVM), который упаковывается и загружается на Ethereum через транзакции, а затем интерпретируется и выполняется EVM.
Важно отметить, что уязвимости компилятора Solidity отличаются от уязвимостей самого EVM. Уязвимости EVM относятся к проблемам безопасности, возникающим при выполнении инструкций виртуальной машины, которые могут повлиять на всю сеть Ethereum. В то время как уязвимости компилятора Solidity относятся к проблемам, возникающим при преобразовании Solidity в код EVM, которые не влияют непосредственно на саму сеть Ethereum.
Одна из опасностей уязвимости компилятора Solidity заключается в том, что это может привести к несоответствию сгенерированного EVM-кода ожиданиям разработчиков смарт-контрактов. Поскольку смарт-контракты на Ethereum обычно связаны с криптовалютными активами пользователей, любые ошибки, вызванные компилятором, могут привести к потерям активов пользователей и вызвать серьезные последствия.
Разработчики и аудиторы контрактов могут сосредоточиться на проблемах реализации логики кода контракта, а также на вопросах безопасности на уровне Solidity, таких как повторный вход и переполнение целых чисел. Однако уязвимости компилятора Solidity трудно обнаружить только с помощью аудита логики исходного кода контракта. Необходимо совместно анализировать конкретные версии компилятора и определенные модели кода, чтобы определить, подвержен ли смарт-контракт уязвимостям компилятора.
Пример уязвимости компилятора Solidity
Вот несколько примеров реальных уязвимостей компилятора Solidity, которые демонстрируют конкретные формы, причины и последствия.
SOL-2016-9 ВысокийПорядокБайтовОчисткиХранилища
Уязвимость существует в более ранних версиях компилятора Solidity (>=0.1.6 <0.4.4).
Рассмотрим следующий код:
солидность контракт C { uint32 a = 0x12345678; uint32 b = 0; функция run() возвращает (uint256) { a += 1; вернуть b; } }
Переменная хранения b не была изменена, поэтому функция run() должна возвращать значение по умолчанию 0. Однако в коде, сгенерированном уязвимой версией компилятора, функция run() будет возвращать 1.
Такая ситуация, не соответствующая ожиданиям, может привести к серьезным последствиям, если переменная b используется для проверки прав доступа, учета активов и других целей.
Причина возникновения этой ситуации заключается в том, что EVM использует элементы стека размером 32 байта, в то время как Solidity поддерживает более мелкие типы данных, такие как uint32. Компилятор при обработке этих типов должен очищать старшие разряды, но не правильно обрабатывает их при переполнении целого числа, что приводит к записи 1 бита старшего разряда в соседнюю переменную b.
SOL-2022-4 ВстроеннаяАссемблернаяПамятьПобочныеЭффекты
Уязвимость существует в компиляторах версий от 0.8.13 до 0.8.15.
Рассмотрим следующий код:
солидность контракт C { функция f() публичная чистая возвращает (uint) { ассемблер { mstore(0, 0x42) } uint x; ассемблер { x := mload(0) } вернуть x; } }
Уязвимость возникает из-за оптимизации компиляции. Компилятор анализирует и оптимизирует отдельные блоки ассемблера; если операция записи в память не будет прочитана позже, она будет удалена для экономии газа. Однако записи и чтения памяти в приведенном выше коде находятся в двух разных блоках ассемблера, и компилятор ошибочно считает первую запись избыточной и удаляет ее, что приводит к тому, что функция f() возвращает 0 вместо правильного 0x42.
SOL-2022-6 AbiReencodingHeadOverflowWithStaticArrayCleanup
Уязвимость затрагивает компиляторы версии от 0.5.8 до 0.8.16.
Рассмотрите следующий код:
солидность контракт C { функция f(bytes4[] calldata a) внешняя чистая возвращает (bytes4[] память) { return abi.decode(abi.encode(a), (bytes4[])); } }
В нормальных условиях этот код должен возвращать переменную a. Но в уязвимой версии, если ввести "aaaa", будет возвращен пустой массив.
Это произошло из-за того, что Solidity неправильно очистил некоторые данные при выполнении операции abi.encode над массивами типа calldata, что привело к изменению соседних данных и к несоответствию данных после кодирования и декодирования.
Стоит отметить, что при выполнении внешних вызовов и эмитации событий в Solidity параметры неявно кодируются с помощью abi.encode, поэтому вероятность появления таких уязвимостей может быть выше, чем предполагается.
Рекомендации по безопасности
В связи с уязвимостями компилятора Solidity, разработчикам и специалистам по безопасности рекомендуется следующее:
Для разработчиков:
Для безопасных сотрудников:
Некоторые полезные ресурсы:
Таким образом, уязвимость компилятора Solidity является значительным риском безопасности при разработке смарт-контрактов. Разработчики и специалисты по безопасности должны быть бдительными и принимать соответствующие меры для снижения потенциальных угроз, связанных с такими уязвимостями.