Засоби аналізу безпеки смарт-контрактів
Раніше ми писали про угоди в цифрову епоху, розкривши основи роботи та безпеки смарт-контрактів. Сьогодні, у продовження теми безпеки смарт-контрактів, ми ділимося з вами нашим оглядом найпоширеніших інструментів для аудиту смарт-контрактів.
Наразі наша мета – порівняти найбільш популярні програмні інструменти для аналізу безпеки смарт-контрактів. Для цього ми використали смарт-контракти, що визнано безпечними з високим ступенем ймовірності (далі для простоти – свідомо безпечні або безпечні смарт-контракти), а також свідомо вразливі, або просто вразливі смарт-контракти. Загалом для аналізу було використано 20 смарт-контрактів DeFi із блокчейн-мережі Ethereum, написаних на мові програмування Solidity.
В якості безпечних смарт-контрактів ми відібрали лише ті контракти, що мали звіти з професійного аудиту безпеки, розроблені авторитетними аудиторами. За допомогою ресурсу etherscan.io було визначено 10 смарт-контрактів, що мали одну або більше успішно проведених транзакцій, а також виправлені вразливості, які вказані у професійних незалежних аудиторських звітах. Нижче наведений список цих свідомо безпечних смарт-контрактів.
Назва смарт-контракту | Адреса смарт-контракту |
BAToken | 0x0D8775F648430679A709E98d2b0Cb6250d2887EF |
HumanStandardToken | 0x0F4CA92660Efad97a9a70CB0fe969c755439772C |
HBToken | 0x6f259637dcD74C767781E37Bc6133cd6A68aa161 |
NPXSToken | 0xA15C7Ebe1f07CaF6bFF097D8a589fb8AC49Ae5B3 |
FunctionXToken | 0x8c15Ef5b4B21951d50E53E4fbdA8298FFAD25057 |
BlockWRKICO | 0x0407B4c4eAEd35CE3C5B852bDFA1640B09EeEDF4 |
ThePoolz | 0x000BaB4F6b5560d7942AC88cf0233b6028B5B465 |
EternalStorageProxy | 0x69c707d975e8d883920003CC357E556a4732CD03 |
Layerx | 0xfe56E974C1C85e9351325fb2D62963A022Ad624F |
sHakka | 0xd9958826Bce875A75cc1789D5929459E6ff15040 |
Також, для визначення ефективності засобів аудиту, ми обрали смарт-контракти з загально відомими верифікованими вразливостями. Ці смарт-контракти були спеціально розроблені крипто-ентузіастами для цілей тестування, навчання тощо.
Список свідомо вразливих смарт-контрактів:
Тип вразливості | Назва смарт-контракту |
Access control | Unprotected0 |
Arithmetic | OverflowSingleTx |
Bad randomness | Lottery |
Denial of service | DosSimple |
Front running | FindThisHash |
Reentrancy | ReentrancySimple |
Short addresses | ShortAddressExample |
Time manipulation | Roulette |
Unchecked low-level calls | Lotto |
Other | NaiveReceiver |
Для проведення аудиту смарт-контрактів та аналізу результатів ми відібрали три найбільш поширених та актуальних інструменти з відкритим вихідним кодом, а саме:
- Mythril
- Securify
- Slither
Ми встановили їх на віртуальну машину Oracle VirtualBox під управлінням Linux Ubuntu 21.10. Також, для нормальної роботи інструментів ми встановили платформу Docker, мови програмування Python 3 та низку бібліотек Python. Ми використовували виключно консольні версії засобів аудиту.
Суть нашого дослідження полягає у визначенні ефективності інструментального аудиту смарт-контрактів шляхом аналізу кожним інструментом безпечних смарт-контрактів та вразливих смарт-контрактів. Для безпечних смарт-контрактів будь-які вразливості, знайдені інструментами та не вказані у звітах з незалежного аудиту, будуть вважатися помилковими спрацьовуваннями (похибка першого роду, false positive). Для вразливих смарт-контрактів невиявлені відомі вразливості будуть вважатися пропусками подій (похибками другого роду, false negative).
Додатково ми перевірили, чи зможуть інструменти знайти вразливості, які було виправлено в безпечних смарт-контрактах за результатами незалежних аудиторських звітів. Ми були практично впевнені, що вразливостей не буде знайдено, але така перевірка підвищить об’єктивність аналізу.
Для загальної оцінки ефективності роботи інструментів ми використовували наступні характеристики їхньої роботи:
- Кількість помилково виявлених вразливостей.
- Кількість помилково не виявлених (пропущених) вразливостей.
- Час виконання аудиту.
- Можливість пошуку шляхів оптимізації витрат газу.
- Додатковий функціонал та деталізація отриманих результатів.
Далі розглянемо детальніше кожен з інструментів аудиту.
Що таке Mythril, і як він працює
Mythril – один із найпоширеніших інструментів для аудиту байт-коду віртуальних машин Ethereum. Тестування смарт-контрактів відбувається конколічним методом, що включає в себе символьне виконання, SMT обчислення та taint-аналіз (аналіз зіпсованості). За допомогою інструмента Mythril можна знайти такі вразливості, як переповнення чисельних значень, перезапис власника, повторний запуск виконання функції тощо. Нижче наведено приклад звіту Mythril.
==== Unprotected Selfdestruct ====
SWC ID: 106
Severity: High
Contract: KillBilly
Function name: commencekilling()
PC address: 354
Estimated Gas Usage: 574 - 999
The contract can be killed by anyone.
Anyone can kill this contract and withdraw its balance to an arbitrary address.
--------------------
In file: killbilly.sol:22
selfdestruct(msg.sender)
Окрім мережі Ethereum, інструмент також здатний аналізувати смарт-контракти мереж, які підтримують EVM. Серед них: Hedera, Quorum, Vechain, Roostock, Tron та інші.
Для запуску аналізу необхідно виконати команду «myth analyze ExampleName.sol». Також є можливість вказати максимальну кількість тестових транзакцій, які треба виконати, та максимальну тривалість виконання аналізу в секундах. Для цього до команди запуску необхідно додати параметри «-t» та «–execution-timeout» відповідно.
Інструмент надає досить докладний та зручний звіт з аудиту. Це дозволяє легко знайти виділену частину коду в оригінальному файлі та перевірити потенційні вразливості вручну. Mythril не має можливостей пошуку шляхів економії витрати газу.
Що таке Securify, і як він працює
Securify – інструмент аудиту безпеки смарт-контрактів, розроблений Ethereum Foundation і ChainSecurity у 2017 році. Від початку запуску проєкту з використанням Securify було проскановано більше ніж 22 тисячі смарт-контрактів Ethereum. Це допомогло їхнім розробникам виправити велику кількість уразливостей різних рівнів ризику.
Securify статично аналізує байт-код віртуальних машин Ethereum та отримує всю інформацію про алгоритм роботи та потік даних у ньому. Цей процес повністю автоматизований за допомогою Souffle, мови програмування, що створювалася для статичного аналізу програмного забезпечення Oracle й інших. Після цього відбувається перевірка отриманих фактів для пошуку вразливостей та надання рекомендації щодо їх виправлення.
Нижче зображено основні етапи роботи інструменту Securify:
Аналіз відбувається у три основні етапи:
- Парсинг байт-коду EVM та його декомпіляція у форму, придатну до аналізу.
- Визначення семантичних фактів про смарт-контракт.
- Поєднання шаблонів та правил для визначення вразливих місць.
Для старту аудиту локально збереженого смарт-контракту необхідно виконати наступну команду:
securify <contract_source>.sol [–use-patterns Pattern1]
Також можна сканувати смарт-контракти напряму в мережі Ethereum:
securify <contract_address> –from-blockchain [–key <key-file>]
Після виконання однієї з цих команд можна отримати такий звіт:
Severity: CRITICAL
Pattern: Transaction Order Affects Execution of Ether Transfer
Description: Ether transfers whose execution can be manipulated by
other transactions must be inspected for unintended
behavior.
Type: Violation
Contract: Layerx
Line: 383
Source:
>
> if(rwds.eth > 0) { msg.sender.transfer(rwds.eth); }
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> }
Severity: HIGH
Pattern: Unhandled Exception
Description: The return value of statements that may return error
values must be explicitly checked.
Type: Warning
Contract: Layerx
Line: 270
Source:
> require(payment > 0, 'Payment must be greater than 0.');
> require(UNILAYER.balanceOf(msg.sender) >= payment, 'Holder does not have enough tokens.');
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> require(UNILAYER.allowance(msg.sender, address(this)) >= payment, 'Call Approve function firstly.');
Звіт Securify надає інформацію про рівні ризику вразливостей, назви шаблонів, які спрацювали, типи повідомлень про вразливості, назву смарт-контракту та фрагмент потенційно вразливого коду.
Інструмент Securify показує непогані результати за відносно короткий проміжок часу. У своєму арсеналі має 37 шаблонів різних типів уразливостей, що вигідно вирізняє цей інструмент серед конкурентів. Securify здатний визначати прості помилки в логіці, але не має можливості пошуку шляхів економії та оптимізації витрат газу.
Що таке Slither, і як він працює
Slither – інструмент для статичного аналізу коду смарт-контрактів. Окрім автоматичного пошуку вразливостей, Slither здатний знаходити можливості оптимізації коду та візуалізувати алгоритм роботи, що допомагає аудиторам краще та швидше зрозуміти, як саме влаштований смарт-контракт. Інструмент має можливість працювати з такими фреймворками, як Truffle, Hardhat, Embark і Dapp без додаткових налаштувань.
Алгоритм роботи Slither:
- Представлення вихідного коду у вигляді абстрактного синтаксичного дерева за допомогою компілятора Solidity.
- Побудова графіка наслідування елементів, графіка потоку керування та списку всіх виразів смарт-контракту.
- Зображення коду смарт-контракту у вигляді внутрішньої репрезентативної мови Slither, що спрощує аналіз.
- Уся отримана інформація передається до модулів пошуку вразливостей.
- Аудит та надання звіту.
Нижче представлено схематичне зображення алгоритму роботи Slither:
Встановити інструмент можна з використанням Pypi, завантаживши з репозиторію Github, чи як частину образу Docker під назвою eth-security-toolbox. Для початку аудиту необхідно виконати наступну команду: slither examplename.sol.
Приклад звіту Slither:
C.increment() (etheno-examples/ConstantinopleGasUsage/constantinople.sol#7-11) ignores return value by address(this).call(abi.encodeWithSignature(setStored(int256),newValue)) (etheno-examples/ConstantinopleGasUsage/constantinople.sol#10)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-low-level-calls
Pragma version^0.5.4 (etheno-examples/ConstantinopleGasUsage/constantinople.sol#1) allows old versions
solc-0.5.5 is known to contain severe issues (https://solidity.readthedocs.io/en/latest/bugs.html)Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity
Low level call in C.increment() (etheno-examples/ConstantinopleGasUsage/constantinople.sol#7-11):
- address(this).call(abi.encodeWithSignature(setStored(int256),newValue)) (etheno-examples/ConstantinopleGasUsage/constantinople.sol#10)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#low-level-calls
setStored(int256) should be declared external:
- C.setStored(int256) (etheno-examples/ConstantinopleGasUsage/constantinople.sol#4-6)
increment() should be declared external:
- C.increment() (etheno-examples/ConstantinopleGasUsage/constantinople.sol#7-11)
echidna_() should be declared external:
- C.echidna_() (etheno-examples/ConstantinopleGasUsage/constantinople.sol#12-14)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#public-function-that-could-be-declared-external
Звіт складається з детальних описів знайдених вразливостей, рядків у коді, в яких знаходяться вразливі функції, та посилань на зовнішні ресурси з рекомендаціями. Рівень ризику вразливості можна визначити за кольором: червоний – критичний та високий, жовтий – середній рівень, зелений – низький рівень.
В цілому, Slither виявився простим у використанні, з великим набором додаткових інструментів. Є можливість короткого опису всіх функцій смарт-контракту, що значно спрощує і прискорює ручний пошук вразливостей і аналіз результатів автоматичного аудиту. Крім того, інструмент надає рекомендації, які можуть покращити загальний рівень безпеки смарт-контракту, такі як обмеження версії pragma, видалення з коду невикористаних змінних та інші. Slither також пропонує пошук шляхів оптимізації коду та економії газу, що досить рідко зустрічається серед таких інструментів. Результати роботи інструменту задовільні, а звіт – інформативний та зрозумілий.
Порівняння результатів
Результати аудиту безпечних смарт-контрактів.
Назва безпечного смарт-контракту | Кількість помилкових спрацьовувань | Час виконання аудиту (секунди) | ||||
Mythril | Securify | Slither | Mythril | Securify | Slither | |
BAToken | 2 | 4 | 3 | 5 | 112 | 2 |
BlockWRKICO | 3 | 0 | 2 | 27 | 9 | 2 |
EternalStorageProxy | 0 | 3 | 2 | 1 | 30 | 1 |
FunctionXToken | 2 | 2 | 2 | 5 | 2 | 1 |
HBToken | 0 | 5 | 1 | 16 | 118 | 1 |
LayerX | 2 | 0 | 3 | 2 | 2 | 2 |
NPXSToken | 2 | 10 | 1 | 3 | 316 | 3 |
sHakka | 0 | 0 | 1 | 2 | 2 | 2 |
ThePoolz | 1 | 1 | 3 | 5 | 5 | 1 |
HumanStandardToken | 1 | 0 | 2 | 2 | 3 | 2 |
Разом | 13 | 25 | 20 | 68 | 599 | 17 |
У результаті проведення аудиту інструмент Mythril допустив від 1 до 3 помилкових спрацьовувань в 7 з 10 безпечних смарт-контрактів, Securify – від 1 до 10 помилкових спрацьовувань в 6 з 10 безпечних смарт-контрактів. Усі виявлені вразливості мали рівні ризику Warning та Informational, що розцінюється як низький рівень ризику.
Slither допустив від 1 до 3 помилкових спрацьовувань у всіх 10 безпечних смарт-контрактах. До того ж деяким із спрацьовувань було призначено середній та високий рівень ризику.
Результати аудиту уразливих смарт-контрактів.
Назва вразливого смарт-контракту | Чи знайдені свідомі вразливості? | Час виконання аудиту (секунди) | ||||
Mythril | Securify | Slither | Mythril | Securify | Slither | |
unprotected0 | ні | так | ні | 3 | 2 | 2 |
overflow_single_tx | так | ні | ні | 9 | 9 | 2 |
lottery | ні | так | так | 3 | 30 | 3 |
dos_simple | так | ні | ні | 3 | 2 | 2 |
FindThisHash | так | так | так | 19 | 2 | 1 |
reentrancy_simple | так | так | так | 2 | 3 | 2 |
short_address_exampe | ні | ні | ні | 2 | 2 | 1 |
roulette | так | так | так | 25 | 2 | 2 |
lotto | так | так | так | 2 | 31 | 2 |
NaiveReceiver | ні | ні | ні | 10 | 9 | 2 |
Разом | 6 | 6 | 5 | 78 | 92 | 19 |
Серед уразливих смарт-контрактів інструменти Mythril та Securify правильно визначили проблеми в 6 з 10 смарт-контрактів DeFi, а Slither – в 5 з 10.
Securify позначив більшу частину помилок як Violation, що можна інтерпретувати як високу впевненість інструменту в коректному визначенні вразливостей безпеки. Крім того, Securify виявив проблеми відсутності валідації даних, що контролюються користувачем, та використання низькорівневих викликів call, що не відповідає найкращим практикам безпечної розробки мовою програмування Solidity.
У вразливих смарт-контрактах всі інструменти також виявили вразливості, які не були заявлені розробниками:
Назва вразливого смарт-контракту | Кількість знайдених незаявлених вразливостей | ||
Mythril | Securify | Slither | |
unprotected0 | 0 | 0 | 4 |
overflow_single_tx | 0 | 6 | 1 |
lottery | 1 | 1 | 1 |
dos_simple | 0 | 0 | 1 |
FindThisHash | 0 | 1 | 1 |
reentrancy_simple | 0 | 3 | 1 |
short_address_exampe | 1 | 0 | 1 |
roulette | 0 | 1 | 1 |
lotto | 0 | 5 | 2 |
NaiveReceiver | 1 | 4 | 3 |
Разом | 3 | 21 | 16 |
При оцінці інструментів ми не враховували ці вразливості, оскільки це потребувало б додаткової їхньої валідації (чи не є вони помилковими спрацьовуваннями), а це виходило за рамки нашого дослідження.
Висновки
Ми розглянули три найпопулярніші інструменти для автоматизованого пошуку вразливостей у смарт-контрактах, а саме Mythril, Securify та Slither.
Вивчення інструментів проводилося шляхом аналізу десяти свідомо безпечних смарт-контрактів, перевірених незалежними аудиторами, та десяти свідомо вразливих смарт-контрактів, розроблених для навчання, тестування тощо.
Для розуміння загального набору вразливостей наводимо діаграму загальної кількості знайдених уразливостей у безпечних та вразливих смарт-контрактах за результатами всіх трьох інструментів.
У результаті аналізу ми визначили точність, швидкість, повноту результатів та додаткові функції найпопулярніших інструментів аудиту смарт-контрактів.
Відносну вагу помилкових спрацьовувань (похибок першого роду) у загальній оцінці ми вважали меншою, ніж вагу пропусків подій (похибок другого роду), тому що перші легше верифікувати, ніж останні.
Результати представлено в таблиці нижче за п’ятибальною шкалою, де вищі оцінки означають кращі властивості інструментів.
Mythril | Securify | Slither | |
Помилкові спрацьовування | 4.5 | 4 | 3 |
Пропуски подій | 2 | 2 | 1.5 |
Швидкість аналізу | 4.5 | 4 | 5 |
Деталізація та функціонал | 4 | 4 | 4.5 |
Загальна оцінка | 3.75 | 3.5 | 3.5 |
Найважливіший висновок нашого дослідження полягає в тому, що сучасні популярні інструменти аудиту смарт-контрактів все ще досить погано знаходять уразливості в коді, пропускаючи до половини простих типових уразливостей, не кажучи про складніші.
Різні інструменти автоматичного аналізу смарт-контрактів дають хибні результати різного типу і знаходять неоднакові проблеми в певному фіксованому наборі смарт-контрактів. Основний та додатковий функціонал різних інструментів значно відрізняється.
Як очікувалося, жоден із інструментів не знайшов у безпечних смарт-контрактах уразливостей, що було усунуто за результатами професійних незалежних аудиторських звітів.
Таким чином, наразі не можна стверджувати, що для практичного аналізу безпеки смарт-контрактів якийсь один інструмент є суттєво кращим за інші. Для підвищення ефективності аналізу слід одночасно використовувати декілька універсальних та вузькоспеціалізованих інструментів.
У той самий час, висока кількість хибних результатів свідчить про те, що для виконання надійного аудиту безпеки смарт-контрактів недостатньо використовувати обмежену кількість інструментів із крос-верифікацією між їхніми звітами. Натомість необхідно вручну верифікувати результати роботи інструментів у ході професійного незалежного аудиту смарт-контрактів, особливо, якщо ваш смарт-контракт буде керувати великими коштами, або якщо від якісного аудиторського звіту з безпеки залежить довіра ваших інвесторів.
Скористайтеся нашим безкоштовним онлайн-аналізатором безпеки смарт-контрактів, щоб отримати швидке уявлення про результати роботи автоматичних інструментів.
У разі виникнення додаткових питань у сфері безпеки Web3 і блокчейн, будь ласка, зверніться до нас за отриманням безкоштовної консультації.
Підпишіться на наш канал Телеграм, щоб не пропустити нові статті нашого блогу.