Come sfuggire agli Smart Contracts dalla morsa degli attacchi di rientro? Intelligenza dei dati PlatoBlockchain. Ricerca verticale. Ai.

Come sfuggire agli Smart Contract dalla frizione degli attacchi di rientro?

Tempo per leggere: 6 verbale

Se diamo un'occhiata più da vicino ai più grandi hack crittografici e alle cifre sbalorditive perse per loro, si sarebbero radicati profondamente dai difetti di codifica.

Uno di questi casi comuni di vulnerabilità della sicurezza è l'attacco Reentrancy. Tuttavia, l'effetto distruttivo causato da un rientro mal gestito potrebbe non sembrare semplice come lanciare l'attacco stesso.

Nonostante sia un problema noto e ben pubblicizzato, la comparsa del bug Reentrancy negli smart contract è sempre inevitabile. 

Quante volte la vulnerabilità di Reentrancy è stata sfruttata dagli hacker negli ultimi anni? Come funziona? Come impedire agli smart contract di perdere fondi a causa di bug di rientro? Trova le risposte a queste domande in questo blog.

Quindi, tra non molto, rispolveriamo i più grandi attacchi di rientro in memoria. 

Alcuni dei più famigerati hack di rientro in tempo reale 

Gli attacchi di rientro che hanno causato gli effetti più devastanti sui progetti hanno finito per fare uno di questi due o addirittura entrambi. 

  • Svuota completamente l'etere dai contratti intelligenti
  • Gli hacker si intrufolano nel codice degli smart contract

Possiamo ora osservare alcuni casi di attacchi Reentrancy e il loro impatto. 

Giu 2016: Attacco DAO – 3.54 milioni o $ 150 milioni di Ether

Aprile 2020: hack Uniswap/Lendf.Me – $ 25 milioni

Maggio 2021: L'hack di BurgerSwap – $ 7.2 milioni

Ago 2021: hack di CREMA FINANZA – $ 18.8 milioni

Mar 2022: Ola Finance – $ 3.6 milioni

Jul 2022: Protocollo OMNI – $ 1.43 milioni

È chiaro che gli attacchi Reentrancy non sono mai passati di moda. Approfondiamolo nei passaggi seguenti. 

Panoramica dell'attacco di rientro

Come dal nome "Rientro", che implica "Rientrare ancora e ancora". L'attacco di rientro prevede due contratti: il contratto della vittima e il contratto dell'attaccante. 

Il contratto dell'attaccante sfrutta la vulnerabilità di rientro nel contratto della vittima. Utilizza la funzione di ritiro per raggiungerlo. 

Il contratto dell'attaccante chiama la funzione di prelievo per drenare i fondi dal contratto della vittima effettuando chiamate ripetute prima che il saldo nel contratto della vittima venga aggiornato. Il contratto della vittima controllerà il saldo, invierà fondi e aggiornerà il saldo. 

Ma entro il termine dell'invio dei fondi e dell'aggiornamento del saldo del contratto, l'attaccante del contratto effettua la chiamata continua per prelevare i fondi. Di conseguenza, il saldo non viene aggiornato nel contratto della vittima fino a quando il contratto dell'attaccante non drena tutti i fondi.

La gravità e il costo dello sfruttamento del rientro allarmano la disperata necessità di esibirsi audit del contratto intelligente per escludere la possibilità di trascurare tali errori. 

Vista illustrativa di Reentrancy Attack

Analizziamo il concetto di attacco di rientro dall'illustrazione semplificata di seguito. 

Ecco due contratti: il contratto vulnerabile e il contratto Hacker

Il contratto hacker effettua una chiamata per recedere dal contratto vulnerabile. Alla ricezione della chiamata, il contratto vulnerabile controlla i fondi nel contratto hacker e quindi trasferisce i fondi all'hacker. 

L'hacker riceve i fondi e implementa la funzione di fallback, che richiama nuovamente il contratto vulnerabile anche prima che il saldo venga aggiornato nel contratto vulnerabile. Ripetendo così la stessa operazione, l'hacker preleva completamente i fondi dal contratto vulnerabile. 

Come sfuggire agli Smart Contract dalla frizione degli attacchi di rientro?

Caratteristiche della funzione di fallback utilizzata dall'attaccante 

  • Sono richiamabili esternamente. Cioè non possono essere chiamati dall'interno del contratto che sono scritti
  • Funzione senza nome
  • La funzione di fallback non include una logica arbitraria al suo interno
  • Il fallback viene attivato quando ETH viene inviato al suo contratto intelligente che lo racchiude e non viene dichiarata alcuna funzione di ricezione().

Analisi dell'attacco di rientro da un punto di vista tecnico 

Prendiamo un contratto campione e capiamo come si verifica l'attacco di rientro.

Contratto dannoso

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


}

Questo è il contratto dell'attaccante in cui l'attaccante deposita 2ETH. L'attaccante chiama la funzione di ritiro nel contratto vulnerabile. Una volta ricevuti i fondi dal contratto vulnerabile, viene attivata la funzione di fallback. 

Il fallback esegue quindi la funzione di prelievo e drena il fondo dal contratto vulnerabile. Questo ciclo continua fino a quando i fondi non sono completamente esauriti dal contratto vulnerabile.

Contratto vulnerabile

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


}

Il contratto vulnerabile ha 30 ETH. Qui la funzione ritira() invia l'importo richiesto all'attaccante. Poiché il saldo non viene aggiornato, i token vengono trasferiti ripetutamente all'attaccante. 

Tipi di attacchi di rientro

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

Il msg.sender.call.value(amount)() trasferisce i fondi dopo di che la funzione di fallback del contratto dell'attaccante chiama nuovamente draw() prima che balances[msg.sender] = 0 venga aggiornato.

  • Rientro interfunzionale
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;
}

Il rientro tra funzioni è molto più complesso da identificare. La differenza qui è che la funzione di fallback chiama il trasferimento, a differenza del rientro a funzione singola, dove chiama il ritiro.

Prevenzione contro gli attacchi di rientro

Pattern Controlli-Effetti-Interazioni: Il pattern Checks-effects-interactions aiuta a strutturare le funzioni. 

Il programma dovrebbe essere codificato in modo da verificare prima le condizioni. Una volta superate le verifiche, dovrebbero essere risolti gli effetti sullo stato dei contratti, dopodiché possono essere richiamate le funzioni esterne. 

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

Il codice riscritto qui segue il modello checks-effects-interactions. Qui il saldo viene azzerato prima di effettuare una chiamata esterna. 

Uso del modificatore

Il modificatore noReentrant applicato alla funzione assicura che non vi siano chiamate rientranti. 

contract ReEntrancyGuard {
    bool internal locked;

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

Alla fine

Il passaggio più efficace consiste nell'effettuare audit di contratti intelligenti da un'importante società di sicurezza come QuillAudits, in cui i revisori tengono d'occhio la struttura del codice e controllano come funziona la funzione di fallback. Sulla base dei modelli studiati, vengono fornite raccomandazioni per ristrutturare il codice, se sembra che ce ne siano comportamenti vulnerabili

La sicurezza dei fondi è assicurata subito prima di cadere vittima di eventuali perdite. 

FAQ

Che cos'è un attacco di rientro?

Un attacco di rientro si verifica quando una funzione nel contratto vulnerabile effettua una chiamata a un contratto non attendibile. Il contratto non attendibile sarà il contratto dell'attaccante che effettua chiamate ricorsive al contratto vulnerabile fino a quando i fondi non saranno completamente prosciugati. 

Che cos'è un rientrante?

L'atto di rientrare significa interrompere l'esecuzione del codice e riavviare il processo, noto anche come rientrare.

Che cos'è una guardia di rientro?

Reentrancy guard utilizza un modificatore che impedisce che la funzione venga chiamata ripetutamente. Leggi il blog sopra per trovare l'esempio per la guardia di rientro.

Quali sono alcuni degli attacchi agli smart contract?

Gli smart contract sono esposti a numerose vulnerabilità, come rientro, dipendenza da timestamp, overflow aritmetici, attacchi DoS e così via. Pertanto, l'auditing è d'obbligo per assicurarsi che non ci siano bug che facciano crollare la logica del contratto.

69 Visualizzazioni

Timestamp:

Di più da quillhash