Tu je návod, ako prebieha jeden z najbežnejších hackingov inteligentných zmlúv, ktoré stoja spoločnosti Web 3 milióny...

Niektoré z najväčších hackov v blockchainovom priemysle, kde boli ukradnuté tokeny kryptomien v hodnote miliónov dolárov, boli výsledkom reentrancy útokov. Aj keď sú tieto hacky v posledných rokoch menej bežné, stále predstavujú významnú hrozbu pre blockchainové aplikácie a používateľov.

Takže čo presne sú reentrancy útoky? Ako sú nasadené? A existujú nejaké opatrenia, ktoré môžu vývojári prijať, aby im zabránili?

Čo je reentrancy útok?

Reentrancy útok nastane, keď zraniteľná funkcia inteligentnej zmluvy uskutoční externé volanie na škodlivú zmluvu, čím sa dočasne vzdá kontroly nad tokom transakcie. Škodlivá zmluva potom opakovane volá pôvodnú funkciu inteligentnej zmluvy predtým, ako dokončí vykonávanie, pričom vyčerpá svoje prostriedky.

Transakcia výberu na blockchaine Ethereum má v podstate trojkrokový cyklus: potvrdenie zostatku, prevod a aktualizácia zostatku. Ak sa kyberzločinec dokáže zmocniť cyklu pred aktualizáciou zostatku, môže opakovane vyberať prostriedky, kým sa nevyčerpá peňaženka.

instagram viewer

Kredit za obrázok: Etherscan

Jeden z najznámejších blockchainových hackov, hack Ethereum DAO, ako sa Coindesk, bol reentrancy útok, ktorý viedol k strate eth v hodnote viac ako 60 miliónov dolárov a zásadne zmenil kurz druhej najväčšej kryptomeny.

Ako funguje reentrancy útok?

Predstavte si banku vo vašom rodnom meste, kde majú cnostní miestni obyvatelia svoje peniaze; jej celková likvidita je 1 milión USD. Banka má však chybný účtovný systém – zamestnanci čakajú na aktualizáciu bankových zostatkov do večera.

Váš priateľ investor navštívi mesto a objaví účtovnú chybu. Vytvorí si účet a vloží 100 000 dolárov. O deň neskôr vyberie 100 000 dolárov. Po hodine sa znova pokúsi vybrať 100 000 dolárov. Keďže banka neaktualizovala jeho zostatok, stále má hodnotu 100 000 USD. Takže dostane peniaze. Robí to opakovane, až kým nezostanú žiadne peniaze. Zamestnanci si uvedomia, že nie sú peniaze, až keď večer bilancujú knihy.

V kontexte inteligentnej zmluvy prebieha tento proces takto:

  1. Kyberzločinec identifikuje inteligentnú zmluvu „X“ so zraniteľnosťou.
  2. Útočník iniciuje legitímnu transakciu s cieľovou zmluvou X, aby poslal prostriedky na škodlivú zmluvu „Y“. Počas vykonávania Y volá zraniteľnú funkciu v X.
  3. Vykonávanie zmluvy X je pozastavené alebo oneskorené, pretože zmluva čaká na interakciu s externou udalosťou
  4. Kým je vykonávanie pozastavené, útočník opakovane volá rovnakú zraniteľnú funkciu v X, čím opäť spúšťa jej spustenie toľkokrát, koľkokrát je to možné
  5. Pri každom opätovnom vstupe sa manipuluje so stavom zmluvy, čo umožňuje útočníkovi odčerpať prostriedky z X na Y
  6. Po vyčerpaní finančných prostriedkov sa opätovný vstup zastaví, oneskorená realizácia X sa konečne dokončí a stav zmluvy sa aktualizuje na základe posledného opätovného vstupu.

Vo všeobecnosti útočník úspešne využíva zraniteľnosť pri opakovanom vstupe vo svoj prospech a ukradne finančné prostriedky zo zmluvy.

Príklad reentrancy útoku

Ako teda presne môže technicky dôjsť k reentrancy útoku pri nasadení? Tu je hypotetická inteligentná zmluva s opätovným vstupom. Na uľahčenie sledovania použijeme axiomatické pomenovanie.

// Vulnerable contract with a reentrancy vulnerability

pragmasolidity ^0.8.0;

contract VulnerableContract {
mapping(address => uint256) private balances;

functiondeposit() publicpayable{
balances[msg.sender] += msg.value;
}

functionwithdraw(uint256 amount) public{
require(amount <= balances[msg.sender], "Insufficient balance");
(bool success, ) = msg.sender.call{value: amount}("");
require(success, "Transfer failed");
balances[msg.sender] -= amount;
}
}

The VulnerableContract umožňuje používateľom vložiť eth do zmluvy pomocou Záloha funkciu. Používatelia si potom môžu vybrať svoje vložené eth pomocou odstúpiť funkciu. Existuje však opätovná zraniteľnosť odstúpiť funkciu. Keď používateľ odstúpi, zmluva prevedie požadovanú sumu na adresu používateľa pred aktualizáciou zostatku, čím sa útočníkovi vytvorí príležitosť na zneužitie.

Teraz si pozrite, ako by vyzerala inteligentná zmluva útočníka.

// Attacker's contract to exploit the reentrancy vulnerability

pragmasolidity ^0.8.0;

interfaceVulnerableContractInterface{
functionwithdraw(uint256 amount)external;
}

contract AttackerContract {
VulnerableContractInterface private vulnerableContract;
address private targetAddress;

constructor(address _vulnerableContractAddress) {
vulnerableContract = VulnerableContractInterface(_vulnerableContractAddress);
targetAddress = msg.sender;
}

// Function to trigger the attack
functionattack() publicpayable{
// Deposit some ether to the vulnerable contract
vulnerableContract.deposit{value: msg.value}();

// Call the vulnerable contract's withdraw function
vulnerableContract.withdraw(msg.value);
}

// Receive function to receive funds from the vulnerable contract
receive() external payable {
if (address(vulnerableContract).balance >= 1 ether) {
// Reenter the vulnerable contract's withdraw function
vulnerableContract.withdraw(1 ether);
}
}

// Function to steal the funds from the vulnerable contract
functionwithdrawStolenFunds() public{
require(msg.sender == targetAddress, "Unauthorized");
(bool success, ) = targetAddress.call{value: address(this).balance}("");
require(success, "Transfer failed");
}
}

Keď sa útok spustí:

  1. The Útočnícka zmluva berie adresu VulnerableContract vo svojom konštruktore a ukladá ho do zraniteľnáZmluva premenlivý.
  2. The útok Funkciu zavolá útočník a vloží do eth nejaké eth VulnerableContract pomocou Záloha a potom okamžite zavolajte odstúpiť funkciu VulnerableContract.
  3. The odstúpiť funkciu v VulnerableContract prevedie požadované množstvo eth útočníkovi Útočnícka zmluva pred aktualizáciou zostatku, ale keďže zmluva útočníka je počas externého hovoru pozastavená, funkcia ešte nie je dokončená.
  4. The prijímať funkciu v Útočnícka zmluva sa spúšťa, pretože VulnerableContract poslal eth k tejto zmluve počas externého hovoru.
  5. Funkcia príjmu kontroluje, či je Útočnícka zmluva zostatok je aspoň 1 éter (suma na výber), potom znova vstúpi do VulnerableContract volaním jeho odstúpiť znova fungovať.
  6. Kroky tri až päť opakujte, kým sa VulnerableContract dôjdu finančné prostriedky a v zmluve útočníka sa nahromadí podstatné množstvo eth.
  7. Nakoniec môže útočník zavolať vytiahnuťStolenFunds funkciu v Útočnícka zmluva ukradnúť všetky prostriedky nahromadené v ich zmluve.

Útok môže prebehnúť veľmi rýchlo v závislosti od výkonu siete. Pri zapájaní zložitých smart kontraktov ako DAO Hack, čo viedlo k hard forku Etherea do Ethereum a Ethereum Classicútok trvá niekoľko hodín.

Ako zabrániť reentrancy útoku

Aby sme predišli útoku opätovného vstupu, musíme upraviť zraniteľnú inteligentnú zmluvu tak, aby sa riadili osvedčenými postupmi pre bezpečný vývoj inteligentnej zmluvy. V tomto prípade by sme mali implementovať vzor „checks-effects-interactions“ ako v kóde nižšie.

// Secure contract with the "checks-effects-interactions" pattern

pragmasolidity ^0.8.0;

contract SecureContract {
mapping(address => uint256) private balances;
mapping(address => bool) private isLocked;

functiondeposit() publicpayable{
balances[msg.sender] += msg.value;
}

functionwithdraw(uint256 amount) public{
require(amount <= balances[msg.sender], "Insufficient balance");
require(!isLocked[msg.sender], "Withdrawal in progress");

// Lock the sender's account to prevent reentrancy
isLocked[msg.sender] = true;

// Perform the state change
balances[msg.sender] -= amount;

// Interact with the external contract after the state change
(bool success, ) = msg.sender.call{value: amount}("");
require(success, "Transfer failed");

// Unlock the sender's account
isLocked[msg.sender] = false;
}
}

V tejto pevnej verzii sme zaviedli isLocked mapovanie na sledovanie, či konkrétny účet práve prebieha výber. Keď používateľ iniciuje výber, zmluva skontroluje, či je jeho účet zablokovaný (!isLocked[msg.sender]), čo naznačuje, že momentálne neprebieha žiadny iný výber z toho istého účtu.

Ak účet nie je zablokovaný, zmluva pokračuje zmenou stavu a externou interakciou. Po zmene stavu a externej interakcii sa účet opäť odblokuje, čo umožňuje budúce výbery.

Typy reentrancy útokov

Image Credit: Ivan Radic/Flickr

Vo všeobecnosti existujú tri hlavné typy reentrancy útokov na základe ich povahy využívania.

  1. Jediný reentrancy útok: V tomto prípade je zraniteľná funkcia, ktorú útočník opakovane volá, tá istá, ktorá je citlivá na bránu opätovného vstupu. Vyššie uvedený útok je príkladom jediného reentrancy útoku, ktorému sa dá ľahko zabrániť implementáciou správnych kontrol a zámkov v kóde.
  2. Krížový útok: V tomto scenári útočník využíva zraniteľnú funkciu na volanie inej funkcie v rámci tej istej zmluvy, ktorá zdieľa stav so zraniteľnou. Druhá funkcia, ktorú volá útočník, má nejaký želateľný účinok, vďaka čomu je pre zneužitie atraktívnejšia. Tento útok je zložitejší a je ťažšie ho odhaliť, takže na jeho zmiernenie sú potrebné prísne kontroly a zámky naprieč prepojenými funkciami.
  3. Krížový kontraktový útok: K tomuto útoku dochádza, keď externý kontrakt interaguje so zraniteľným kontraktom. Počas tejto interakcie sa stav zraniteľnej zmluvy zavolá do externej zmluvy pred jej úplnou aktualizáciou. Zvyčajne sa to stáva, keď viaceré zmluvy zdieľajú rovnakú premennú a niektoré aktualizujú zdieľanú premennú neisto. Bezpečné komunikačné protokoly medzi zmluvami a periodickou audity inteligentných zmlúv musia byť implementované na zmiernenie tohto útoku.

Útoky opätovného vstupu sa môžu prejaviť v rôznych formách, a preto si vyžadujú osobitné opatrenia na zabránenie každému z nich.

Zostaňte v bezpečí pred reentrancy útokmi

Reentrancy útoky spôsobili značné finančné straty a podkopali dôveru v blockchain aplikácie. Na ochranu zmlúv musia vývojári dôsledne prijať osvedčené postupy, aby sa vyhli zraniteľnostiam pri opätovnom vstupe.

Mali by tiež implementovať bezpečné vzory výberu, používať dôveryhodné knižnice a vykonávať dôkladné audity na ďalšie posilnenie obrany inteligentnej zmluvy. Samozrejme, informovanosť o vznikajúcich hrozbách a proaktívna aktivita v oblasti bezpečnosti môže zabezpečiť, že budú podporovať aj integritu blockchainových ekosystémov.