Аналіз вразливостей компілятора Solidity та стратегії реагування
Компілятор є одним із основних компонентів сучасних комп'ютерних систем, і його основна функція полягає в перетворенні вихідного коду мов програмування високого рівня в інструкційний код, виконуваний процесором комп'ютера або віртуальною машиною.
Хоча більшість розробників і фахівців з безпеки зазвичай більше зосереджені на безпеці коду додатків, безпека самого компілятора також є важливою. Як комп'ютерна програма, компілятор також може містити уразливості безпеки, що в деяких випадках може призвести до серйозних ризиків безпеки.
Наприклад, у браузері, під час компіляції та виконання 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 HighOrderByteCleanStorage
Ця вразливість існує в більш ранніх версіях компілятора 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 InlineAssemblyMemoryПобічні ефекти
Ця вразливість існує у компіляторах версій від 0.8.13 до 0.8.15.
Розгляньте наступний код:
солідність
контракт C {
функція f() публічна чиста повертає (uint) {
збірка {
mstore(0, 0x42)
}
uint x;
збірка {
x := mload(0)
}
повернути x;
}
}
Ця вразливість виникає через оптимізацію компіляції. Компилятор аналізує та оптимізує окремі блоки assembly, якщо певна операція запису в пам'ять не буде прочитана пізніше, вона буде видалена для економії gas. Але в наведеному коді операції запису та читання в пам'ять знаходяться в двох різних блоках assembly, компілятор помилково вважає перше записування зайвим і видаляє його, в результаті функція 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 та стратегії реагування
Компілятор є одним із основних компонентів сучасних комп'ютерних систем, і його основна функція полягає в перетворенні вихідного коду мов програмування високого рівня в інструкційний код, виконуваний процесором комп'ютера або віртуальною машиною.
Хоча більшість розробників і фахівців з безпеки зазвичай більше зосереджені на безпеці коду додатків, безпека самого компілятора також є важливою. Як комп'ютерна програма, компілятор також може містити уразливості безпеки, що в деяких випадках може призвести до серйозних ризиків безпеки.
Наприклад, у браузері, під час компіляції та виконання 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 HighOrderByteCleanStorage
Ця вразливість існує в більш ранніх версіях компілятора 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 InlineAssemblyMemoryПобічні ефекти
Ця вразливість існує у компіляторах версій від 0.8.13 до 0.8.15.
Розгляньте наступний код:
солідність контракт C { функція f() публічна чиста повертає (uint) { збірка { mstore(0, 0x42) } uint x; збірка { x := mload(0) } повернути x; } }
Ця вразливість виникає через оптимізацію компіляції. Компилятор аналізує та оптимізує окремі блоки assembly, якщо певна операція запису в пам'ять не буде прочитана пізніше, вона буде видалена для економії gas. Але в наведеному коді операції запису та читання в пам'ять знаходяться в двох різних блоках assembly, компілятор помилково вважає перше записування зайвим і видаляє його, в результаті функція 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 є безпечною загрозою, яку не можна ігнорувати під час розробки смарт-договорів. Розробники та фахівці з безпеки повинні бути насторожі та вжити відповідних заходів для зменшення потенційних загроз, які можуть виникнути через такі вразливості.