Аналіз вразливостей компілятора Solidity та стратегії реагування

Детальний аналіз вразливостей компілятора Solidity та стратегії реагування

Комп‘ютерний компілятор є одним з основних компонентів сучасних комп‘ютерних систем. Це комп‘ютерна програма, основна функція якої полягає в перетворенні вихідного коду високорівневої мови програмування в інструкції, які можуть виконуватись процесором комп‘ютера або віртуальною машиною.

Хоча більшість розробників і фахівців з безпеки зазвичай більшою мірою зосереджуються на безпеці коду програм, безпека самого компілятора також є важливою. Як комп'ютерна програма, компілятор також може містити вразливості у безпеці, які в деяких випадках можуть призвести до серйозних ризиків безпеки. Наприклад, браузер може бути вразливим через вразливості в JavaScript-движках під час компіляції та парсингу JavaScript-коду на стороні клієнта, що може призвести до того, що зловмисники скористаються цими вразливостями, коли користувач відвідує шкідливі веб-сторінки, зрештою отримуючи контроль над браузером жертви або навіть операційною системою.

Компілятор Solidity також має вразливості безпеки. Згідно з попередженнями з команди розробників Solidity, у кількох різних версіях компілятора Solidity були виявлені проблеми безпеки.

Уразливість компілятора Solidity

Основна роль компілятора Solidity полягає в перетворенні коду смарт-контракту на інструкційний код Ethereum Virtual Machine (EVM). Ці інструкційні коди EVM упаковуються в транзакції та завантажуються в Ethereum, врешті-решт їх інтерпретує та виконує EVM.

Слід зазначити, що вразливості компілятора Solidity відрізняються від вразливостей самого EVM. Вразливості EVM вказують на проблеми безпеки, що виникають під час виконання інструкцій віртуальної машини. Оскільки зловмисники можуть завантажувати будь-який код в Ethereum, якщо в EVM є вразливості безпеки, це вплине на всю мережу Ethereum, що може призвести до відмови в обслуговуванні (DoS) або навіть до захоплення всієї блокчейн-мережі зловмисниками. Проте, дизайн EVM відносно простий, основний код оновлюється нечасто, тому ймовірність виникнення таких проблем є досить низькою.

Вразливість компілятора Solidity полягає в проблемах, що виникають під час перетворення коду Solidity в код EVM. На відміну від браузера, який компілює та виконує JavaScript на клієнтському комп'ютері користувача, процес компіляції Solidity відбувається лише на комп'ютері розробника смарт-контрактів і не виконується в мережі Ethereum. Тому вразливості компілятора Solidity не впливають безпосередньо на саму мережу Ethereum.

Основною небезпекою вразливостей компілятора Solidity є те, що вони можуть призвести до невідповідності згенерованого коду EVM очікуванням розробника. Оскільки смарт-контракти в Ethereum зазвичай пов'язані з криптовалютними активами користувачів, будь-яка помилка в контракті, викликана компілятором, може призвести до втрати активів користувачів, що є серйозними наслідками.

Розробники та аудитори контрактів можуть в основному зосереджуватися на проблемах реалізації логіки коду контракту, а також на питаннях безпеки на рівні Solidity, таких як повторні виклики, переповнення цілих чисел тощо. Однак вразливості компілятора зазвичай важко виявити лише за допомогою простого аудиту вихідного коду контракту. Потрібно проводити аналіз у поєднанні з певною версією компілятора та специфічними кодовими патернами, щоб визначити, чи підлягає смарт-контракт впливу вразливостей компілятора.

Аналіз уразливостей компілятора Solidity та заходи реагування

Приклад вразливості компілятора Solidity

Ось кілька реальних прикладів вразливостей компілятора Solidity, що демонструють їх конкретні форми, причини та шкоду.

SOL-2016-9 HighOrderByteCleanStorage

Уразливість існувала в ранніх версіях компілятора Solidity (>=0.1.6 <0.4.4).

Розгляньте наступний код:

солідність контракт C { uint32 a = 0x12345678; uint32 b = 0; функція f() публічна { a = a + 1; } функція run() публічний перегляд повертає (uint) { повернути b; } }

змінна зберігання b не була змінена, тому функція run() повинна повертати значення за замовчуванням 0. Але в коді, згенерованому уразливим компілятором, run() повертає 1.

Не розуміючи вразливість цього компілятора, звичайним розробникам важко виявити цей баг через простий перегляд коду. Хоча цей приклад відносно простий і не призведе до особливих серйозних наслідків, якщо змінна b використовується для перевірки прав доступу, обліку активів та інших цілей, така невідповідність з очікуваннями може призвести до дуже серйозних наслідків.

Причина виникнення цього явища полягає в тому, що EVM використовує стекову віртуальну машину, кожен елемент у стеку має розмір 32 байти (, тобто розмір змінної uint256 ). З іншого боку, кожен слот у базовому зберіганні storage також має розмір 32 байти. Мова Solidity підтримує типи даних, нижчі за 32 байти, такі як uint32, і компілятор при обробці цих типів повинен відповідним чином очищати їх старші біти (clean up) для забезпечення коректності даних. У наведеній ситуації, коли додавання призводить до переповнення цілого числа, компілятор не правильно очистив старші біти результату, внаслідок чого старший біт 1 був записаний у storage, в результаті чого було перекрито значення змінної a, що призвело до зміни значення змінної b на 1.

SOL-2022-4 InlineAssemblyMemoryПобічні ефекти

Цей вразливість існує в компіляторах версій >=0.8.13 <0.8.15.

Розгляньте наступний код:

солідність контракт C { функція f() публічна чиста повертає (uint) { збірка { mstore(0, 0x42) } uint x; збірка { x := mload(0) } повернути x; } }

Компіллятор Solidity під час перетворення мови Solidity в EVM-код не лише виконує простий переклад, а й проводить глибокий аналіз контролю потоку та даних, реалізуючи різноманітні оптимізації компіляції для зменшення обсягу згенерованого коду та оптимізації споживання газу під час виконання. Такі оптимізації є поширеними в компіляторах різних високорівневих мов, але через складність ситуацій, які потрібно враховувати, легко можуть виникнути помилки або вразливості безпеки.

Вразливість наведеного коду походить від таких оптимізаційних операцій. Якщо в якомусь функції є код, який змінює дані за адресою пам'яті 0, але це дані не використовуються в подальшому, то насправді можна безпосередньо видалити код, що змінює пам'ять 0, тим самим заощадивши газ і не впливаючи на подальшу логіку програми.

Ця стратегія оптимізації сама по собі не має проблем, але в конкретній реалізації компілятора Solidity такі оптимізації застосовуються лише до окремого блоку assembly. У наведеному вище PoC коді запис і доступ до пам'яті 0 знаходяться в двох різних блоках assembly, тоді як компілятор аналізував і оптимізував лише окремий блок assembly. Оскільки в першому блоці assembly після запису пам'яті 0 немає жодної операції читання, це призводить до висновку, що команда запису є надлишковою, і її буде видалено, що викликає помилку. У вразливій версії функція f() поверне значення 0, хоча правильне значення, що повинно бути, - це 0x42.

SOL-2022-6 AbiReencodingHeadOverflowWithStaticArrayCleanup

Ця уразливість впливає на компілятори версій >= 0.5.8 < 0.8.16.

Розгляньте наступний код:

солідність контракт C { функція f(string[1] calldata a) public pure повертає (string memory) { повернути abi.decode(abi.encode(a), (строк[1]))[0]; } }

У нормальних умовах змінна a, яку повертає вищезгаданий код, повинна бути "aaaa". Але в уразливій версії вона повертає порожній рядок "".

Причиною цієї вразливості є те, що Solidity під час виконання операції abi.encode над масивами типу calldata неправильно очистила деякі дані, що призвело до зміни сусідніх інших даних і спричинило невідповідність даних після кодування та декодування.

Варто зазначити, що при виконанні зовнішніх викликів і генерації подій у Solidity, параметри неявно кодуються за допомогою abi.encode, тому ймовірність виникнення вищезгаданого вразливого коду буде вищою, ніж можна було б спочатку припустити.

Аналіз вразливостей компілятора Solidity та заходи реагування

Рекомендації з безпеки

Щодо загрози вразливостям компілятора Solidity, пропонуємо такі рекомендації для розробників і фахівців з безпеки:

Для розробників:

  • Використовуйте новішу версію компілятора Solidity. Хоча нові версії можуть впроваджувати нові проблеми з безпекою, відомих проблем з безпекою зазвичай менше, ніж у старих версіях.

  • Удосконалити юніт-тести. Більшість помилок на рівні компілятора призводять до невідповідності результатів виконання коду очікуванням. Ці проблеми важко виявити під час перевірки коду, але вони можуть легко виявитися на етапі тестування. Підвищення покриття коду може максимально зменшити ймовірність виникнення таких проблем.

  • Намагайтеся уникати використання вбудованих асемблерів, складних операцій кодування та декодування ABI для багатовимірних масивів та складних структур без чітких вимог, уникайте сліпого використання нових можливостей мови та експериментальних функцій. Більшість історичних вразливостей пов'язані з вбудованими асемблерами та операціями кодування ABI. Компілятори частіше можуть викликати помилки при обробці складних мовних особливостей. З іншого боку, розробники також можуть помилятися в використанні нових можливостей, що призводить до проблем безпеки.

Для безпеки персоналу:

  • Під час проведення безпечного аудиту коду Solidity не ігноруйте потенційні ризики безпеки, які можуть бути внесені компілятором. Відповідний пункт перевірки в Smart Contract Weakness Classification(SWC) - SWC-102: Застаріла версія компілятора.

  • У внутрішньому процесі розробки SDL, закликаємо команду розробників оновити версію компілятора Solidity та розглянути можливість впровадження автоматичної перевірки версії компілятора в процесі CI/CD.

  • Але не слід надміру панікувати через вразливості компілятора, більшість вразливостей компілятора спрацьовують лише в певних кодових патернах, і не кожен контракт, скомпільований за допомогою вразливої версії компілятора, обов'язково міститиме ризики безпеки, реальний вплив на безпеку потрібно оцінювати залежно від конкретної ситуації проекту.

Декілька корисних ресурсів:

  • Пости про Security Alerts, які регулярно публікує команда Solidity
  • Регулярно оновлюваний список помилок з офіційного репозиторію Solidity
  • Список помилок компіляторів різних версій. Можна автоматично вводити перевірку версії компілятора в процес CI/CD, щоб вказати на наявні у поточній версії уразливості безпеки. у правому верхньому куті сторінки Code значок трикутного знака оклику може вказувати на вразливості безпеки, пов'язані з поточною версією компілятора.

Аналіз вразливостей компілятора Solidity та заходи реагування

Підсумок

У цій статті розглядаються основні концепції компілятора, аналізуються вразливості компілятора Solidity, а також обговорюються потенційні безпекові ризики, які вони можуть спричинити в реальному середовищі розробки Ethereum. Крім того, надаються деякі практичні рекомендації для розробників і фахівців з безпеки. Завдяки розумінню та увазі до вразливостей компілятора можна більш комплексно забезпечити безпеку смарт-контрактів.

Переглянути оригінал
This page may contain third-party content, which is provided for information purposes only (not representations/warranties) and should not be considered as an endorsement of its views by Gate, nor as financial or professional advice. See Disclaimer for details.
  • Нагородити
  • 9
  • Поділіться
Прокоментувати
0/400
DAOplomacyvip
· 07-11 19:33
можливо, ще одна не зовсім оптимальна реалізація з точки зору управління...
Переглянути оригіналвідповісти на0
LightningLadyvip
· 07-11 19:11
Що ж, що в нас є кілька вразливостей компілятора.
Переглянути оригіналвідповісти на0
SandwichDetectorvip
· 07-10 06:32
То це ж наша робота.
Переглянути оригіналвідповісти на0
GateUser-00be86fcvip
· 07-08 20:59
Компилятор також повинен бути перевірений.
Переглянути оригіналвідповісти на0
CryptoTherapistvip
· 07-08 20:58
давайте візьмемо усвідомлений момент, щоб обробити цю тривогу компілятора... відчувається як класична травма системи, якщо чесно
Переглянути оригіналвідповісти на0
CryptoPhoenixvip
· 07-08 20:56
Джерело є більш первинним, ніж первинне. Падіння завжди призведе до відродження.
Переглянути оригіналвідповісти на0
OnlyOnMainnetvip
· 07-08 20:50
Знову доведеться ламати голову над кодом
Переглянути оригіналвідповісти на0
FrogInTheWellvip
· 07-08 20:47
На щастя, зараз код не пишеться на sol.
Переглянути оригіналвідповісти на0
GasGuzzlervip
· 07-08 20:30
Вразливий пес знову починає залучати людей для аудиту.
Переглянути оригіналвідповісти на0
Дізнатися більше
  • Закріпити