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

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

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

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

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

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

Нижче представлені кілька реальних прикладів, які демонструють конкретні форми, причини та наслідки вразливостей компілятора 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() публічного виду повертає (uint32) { повернути b; } }

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

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

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

SOL-2022-4 InlineAssemblyMemorySideEffects

Ця вразливість існує в компіляторах версій від 0.8.13 до 0.8.15. Розгляньте наступний код:

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

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

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

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

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

SOL-2022-6 AbiReencodingHeadOverflowWithStaticArrayCleanup

Ця вразливість впливає на компілятори версій від 0.5.8 до 0.8.16. Розгляньте наступний код:

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

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

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

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

Поради з безпеки

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

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

  • Використовуйте новішу версію компілятора Solidity. Хоча нові версії можуть вносити нові проблеми, але відомих проблем з безпекою зазвичай менше.
  • Поліпшити модульні тести. Більшість багів на рівні компілятора призводять до того, що результати виконання не відповідають очікуванням, ці проблеми важко виявити під час перевірки коду, але їх легко виявити під час тестування. Підвищення покриття коду може максимально уникнути таких проблем.
  • Уникайте використання інлайн-асемблера, складного кодування та декодування ABI тощо, не сліпо використовуйте нові функції та експериментальні можливості. Більшість історичних вразливостей пов'язані з цими складними операціями.

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

  • Не ігноруйте потенційні ризики безпеки, які можуть бути введені компілятором під час аудиту. Відповідна перевірка в Smart Contract Weakness Classification(SWC) – це SWC-102: Застаріла версія компілятора.
  • У процесі розробки SDL, спонукати команду розробників оновити версію компілятора, розглянути можливість впровадження автомат перевірки версії компілятора в CI/CD.
  • Не потрібно надмірно турбуватися про вразливості компілятора. Більшість вразливостей активуються лише в певних кодових моделях, використання контрактів, скомпільованих у вразливій версії, не обов'язково несе ризики, потрібно оцінювати в залежності від конкретних обставин.

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

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

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

Резюме

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

ETH2.9%
SOL5.09%
Переглянути оригінал
Ця сторінка може містити контент третіх осіб, який надається виключно в інформаційних цілях (не в якості запевнень/гарантій) і не повинен розглядатися як схвалення його поглядів компанією Gate, а також як фінансова або професійна консультація. Див. Застереження для отримання детальної інформації.
  • Нагородити
  • 5
  • Поділіться
Прокоментувати
0/400
0xInsomniavip
· 07-24 15:11
Вразливість на нижньому рівні, верхній рівень не рятує.
Переглянути оригіналвідповісти на0
0xSunnyDayvip
· 07-24 06:35
Хто ще наважиться сказати, що компілятори безпечні?
Переглянути оригіналвідповісти на0
BankruptcyArtistvip
· 07-24 06:29
Щодня шукаю вразливості, щодня банкротую.
Переглянути оригіналвідповісти на0
bridge_anxietyvip
· 07-24 06:23
Коефіцієнт складності експлуатації вразливостей збільшився!
Переглянути оригіналвідповісти на0
TokenDustCollectorvip
· 07-24 06:13
Безпекова уразливість є початком втрат для невдах.
Переглянути оригіналвідповісти на0
  • Закріпити