Hvordan unnslippe smarte kontrakter fra gjenopptakelsesangrepene? PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.

Hvordan unnslippe smarte kontrakter fra gjenopptakelsesangrepene?

Lesetid: 6 minutter

Hvis vi ser nærmere på de største kryptohakkene og de iøynefallende tallene som ble tapt for dem, ville de ha rotfestet seg dypt fra kodingsfeilene.

En slik vanlig forekomst av sikkerhetssårbarhet er Reentrancy-angrepet. Imidlertid kan den destruktive effekten forårsaket på grunn av feilbehandlet gjeninntreden høres kanskje ikke så enkelt ut som å starte selve angrepet.

Til tross for at det er et kjent og godt publisert tema, er opptredenen av Reentrancy-feilen i smarte kontrakter alltid uunngåelig. 

Hvor ofte hadde Reentrancy-sårbarheten blitt utnyttet av hackere de siste årene? Hvordan virker det? Hvordan hindre smarte kontrakter fra å tape midler til Reentrancy-feil? Finn svar på disse spørsmålene i denne bloggen.

Så, om ikke lenge, la oss friske opp de største re-entrance-angrepene i minnet. 

Noen av de mest beryktede sanntids-reentrancy-hakkene 

Reentrancy-angrep som forårsaket de mest ødeleggende effektene på prosjektene endte opp med å gjøre en av disse to eller til og med begge. 

  • Tøm eteren fullstendig fra de smarte kontraktene
  • Hackere sniker seg inn i den smarte kontraktskoden

Vi kan nå observere noen få tilfeller av reentrancy-angrep og deres innvirkning. 

Juni 2016: DAO angrep – 3.54 millioner eller $150 millioner eter

april 2020: Uniswap/Lendf.Me hack – $25 millioner

May 2021: BurgerSwap-hakket – 7.2 millioner dollar

2021. august: CREAM FINANCE hack – 18.8 millioner dollar

Mar 2022: Ola Finance – 3.6 millioner dollar

Jul 2022: OMNI-protokoll – 1.43 millioner dollar

Det er krystallklart at Reentrancy-angrep aldri har gått ut av stilen. La oss få dyp innsikt i det i de følgende passasjene. 

Oversikt over Reentrancy-angrep

Som fra navnet "Reentrancy", som innebærer "Reentering igjen og igjen." Reentrancy-angrep involverer to kontrakter: offerkontrakten og angriperkontrakten. 

Angriperkontrakten utnytter reentrancy-sårbarheten i offerkontrakten. Den bruker tilbaketrekningsfunksjonen for å oppnå det. 

Angriperkontrakten kaller tilbaketrekningsfunksjonen for å tappe midlene fra offerkontrakten ved å foreta gjentatte anrop før saldoen i offerkontrakten oppdateres. Offerkontrakten vil sjekke saldoen, sende midler og oppdatere saldoen. 

Men innenfor tidsrammen for å sende midlene og oppdatere saldoen i kontrakten, foretar angriperkontrakten den kontinuerlige oppfordringen om å ta ut penger. Som et resultat av dette oppdateres ikke saldoen i offerkontrakten før angriperkontrakten tapper alle midlene.

Alvorlighetsgraden og kostnadene ved reentrancy-utnyttelse alarmerer det store behovet for å prestere smarte kontraktsrevisjoner å utelukke muligheten for å overse slike feil. 

Illustrativt syn på Reentrancy Attack

La oss forstå konseptet med reentrancy-angrep fra den forenklede illustrasjonen nedenfor. 

Her er to kontrakter: Den sårbare kontrakten og Hacker-kontrakten

Hackerkontrakten oppfordrer til å trekke seg fra den sårbare kontrakten. Ved mottak av anropet sjekker den sårbare kontrakten for midlene i hackerkontrakten og overfører deretter midlene til hackeren. 

Hackeren mottar midlene og implementerer fallback-funksjonen, som kaller inn igjen den sårbare kontrakten selv før saldoen er oppdatert i den sårbare kontrakten. Ved å gjenta den samme operasjonen trekker hackeren pengene fullstendig fra den sårbare kontrakten. 

Hvordan unnslippe smarte kontrakter fra gjenopptakelsesangrepene?

Funksjoner av reservefunksjon brukt av angriper 

  • De er eksternt anropbare. Det vil si at de ikke kan ringes fra kontrakten de er skrevet
  • Funksjon uten navn
  • Reservefunksjonen inkluderer ikke vilkårlig logikk i den
  • Fallback utløses når ETH sendes til den vedlagte smarte kontrakten, og ingen receive() funksjon er deklarert.

Analyserer reentrancy-angrep fra et teknisk synspunkt 

La oss ta en prøvekontrakt og forstå hvordan reentrancy-angrepet oppstår.

Ondsinnet kontrakt

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();
    }


}

Dette er angriperkontrakten der angriperen setter inn 2ETH. Angriperen kaller tilbaketrekningsfunksjonen i den sårbare kontrakten. Når midlene er mottatt fra den sårbare kontrakten, utløses reservefunksjonen. 

Fallbacken utfører deretter uttaksfunksjonen og tapper fondet fra den sårbare kontrakten. Denne syklusen fortsetter til midlene er fullstendig oppbrukt fra den sårbare kontrakten.

Sårbar kontrakt

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;
    }


}

Den sårbare kontrakten har 30ETH. Heri sender tilbaketreknings()-funksjonen det forespurte beløpet til angriperen. Siden saldoen ikke er oppdatert, overføres tokens til angriperen gjentatte ganger. 

Typer reentrancy-angrep

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

msg.sender.call.value(amount)() overfører midlene hvoretter angriperkontraktens fallback-funksjon kaller withdraw() igjen før saldoene[msg.sender] = 0 oppdateres.

  • Reentrancy på tvers av funksjoner
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;
}

Gjeninntreden på tvers av funksjoner er mye mer komplisert å identifisere. Forskjellen her er at reservefunksjonen kaller overføring, i motsetning til ved enkeltfunksjons reentrancy, hvor den kaller tilbaketrekning.

Forebygging mot reentrancy-angrep

Sjekker-effekter-interaksjonsmønster: Sjekker-effekter-interaksjonsmønster hjelper til med å strukturere funksjonene. 

Programmet bør være kodet på en måte som kontrollerer forholdene først. Når kontrollene er bestått, bør virkningene på kontraktenes tilstand løses, hvoretter de eksterne funksjonene kan kalles opp. 

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

Den omskrevne koden her følger mønsteret sjekker-effekter-interaksjoner. Her gjøres saldoen null før et eksternt anrop. 

Bruk av modifikator

Modifikatoren noReentrant brukt på funksjonen sikrer at det ikke er noen reentrant-anrop. 

contract ReEntrancyGuard {
    bool internal locked;

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

Til slutt

Det mest effektive trinnet er å ta opp smarte kontraktrevisjoner fra et ledende sikkerhetsfirma som QuillAudits, der revisorene holder et nøye øye med strukturen til koden og sjekker hvordan reservefunksjonen fungerer. Basert på de studerte mønstrene, gis det anbefalinger til å restrukturere koden dersom det ser ut til å være noen sårbar atferd

Sikkerhet for midler er sikret rett før du blir offer for tap. 

Spørsmål og svar

Hva er et reentrancy-angrep?

Et reentrancy-angrep skjer når en funksjon i den sårbare kontrakten ringer til en ikke-klarert kontrakt. Den upålitelige kontrakten vil være angriperens kontrakt som gjør rekursive anrop til den sårbare kontrakten til midlene er fullstendig tappet. 

Hva er en reentrant?

Å gå inn på nytt betyr å avbryte kjøringen av koden og starte prosessen på nytt, som også er kjent som å gå inn på nytt.

Hva er en reentrancy-vakt?

Reentrancy guard bruker en modifikator som forhindrer at funksjonen kalles opp gjentatte ganger. Les bloggen ovenfor for å finne eksempelet for gjeninnreisevakt.

Hva er noen av angrepene på smarte kontrakter?

Smarte kontrakter er utsatt for en rekke sårbarheter, slik som reentrancy, tidsstempelavhengighet, aritmetiske overløp, DoS-angrep og så videre. Derfor er revisjon et must for å sikre at det ikke er noen feil som kollapser logikken i kontrakten.

69 Visninger

Tidstempel:

Mer fra Quillhash