Jak uciec od inteligentnych kontraktów ze szponów ataków wtórnych? Analiza danych PlatoBlockchain. Wyszukiwanie pionowe. AI.

Jak uciec od inteligentnych kontraktów ze szponów ataków wtórnych?

Czas czytania: 6 minuty

Jeśli przyjrzymy się bliżej największym hackom kryptograficznym i utraconym przez nie oszałamiającym liczbom, byłyby one głęboko zakorzenione w błędach w kodowaniu.

Jednym z takich częstych przypadków luk w zabezpieczeniach jest atak Reentrancy. Jednak destrukcyjny efekt spowodowany niewłaściwą reentrancją może nie brzmieć tak prosto, jak rozpoczęcie samego ataku.

Pomimo tego, że jest to znany i dobrze nagłośniony problem, pojawienie się błędu Reentrancy w inteligentnych kontraktach jest zawsze nieuniknione. 

Jak często luka Reentrancy była wykorzystywana przez hakerów w ostatnich latach? Jak to działa? Jak powstrzymać inteligentne kontrakty przed utratą środków z powodu błędów Reentrancy? Odpowiedzi na te pytania znajdziesz na tym blogu.

Tak więc, wkrótce odświeżmy największe ataki ponownego wejścia w pamięci. 

Niektóre z najbardziej niesławnych hacków związanych z ponownym wejściem w czasie rzeczywistym 

Ataki typu reentrancy, które miały najbardziej niszczycielski wpływ na projekty, zakończyły się wykonaniem jednego z tych dwóch lub nawet obu. 

  • Całkowicie opróżnić eter z inteligentnych kontraktów
  • Hakerzy wkradają się do kodu inteligentnego kontraktu

Możemy teraz zaobserwować kilka przypadków ataków Reentrancy i ich skutków. 

Czerwiec 2016: Atak DAO – Ether o wartości 3.54 mln lub 150 mln USD

Kwi 2020: Hack Uniswap/Lendf.Me – 25 mln USD

Maj 2021: Włamanie do BurgerSwap – 7.2 miliona dolarów

Aug 2021: Włamanie do CREAM FINANCE – 18.8 mln USD

Mar 2022: Ola Finanse – 3.6 mln USD

Jul 2022: Protokół OMNI – 1.43 mln USD

Jest krystalicznie jasne, że ataki Reentrancy nigdy nie wyszły z mody. Zdobądźmy głęboki wgląd w to w poniższych fragmentach. 

Przegląd ataku Reentrancy

Od nazwy „Reentrancy”, co oznacza „Ponowne wchodzenie raz za razem”. Atak z ponownym wejściem obejmuje dwa kontrakty: kontrakt z ofiarą i kontrakt z atakującym. 

Kontrakt atakującego wykorzystuje lukę w zabezpieczeniach dotyczącą ponownego wejścia w kontrakcie ofiary. Wykorzystuje funkcję wycofania, aby to osiągnąć. 

Kontrakt atakującego wywołuje funkcję wycofania w celu drenażu środków z kontraktu ofiary poprzez powtarzane wywołania, zanim saldo w kontrakcie ofiary zostanie zaktualizowane. Kontrakt ofiary sprawdzi saldo, wyśle ​​środki i zaktualizuje saldo. 

Ale w ramach czasowych wysyłania środków i aktualizowania salda w kontrakcie, kontrakt atakującego nieustannie wzywa do wypłaty środków. W rezultacie saldo nie jest aktualizowane w kontrakcie ofiary, dopóki kontrakt atakującego nie wyczerpie wszystkich środków.

Dotkliwość i koszt wykorzystania ponownego wejścia alarmują o pilnej potrzebie działania audyty inteligentnych kontraktów aby wykluczyć możliwość przeoczenia takich błędów. 

Ilustracyjny widok ataku ponownego wejścia

Zrozummy koncepcję ataku reentrancy na podstawie uproszczonej ilustracji poniżej. 

Oto dwa kontrakty: kontrakt wrażliwy i kontrakt hakerski

Kontrakt hakerski wzywa do wycofania się z kontraktu podatnego na ataki. Po odebraniu wezwania wrażliwy kontrakt sprawdza środki w kontrakcie hakerskim, a następnie przekazuje je hakerowi. 

Haker otrzymuje środki i wdraża funkcję awaryjną, która ponownie odwołuje się do wrażliwej umowy jeszcze przed aktualizacją salda w wrażliwej umowie. W ten sposób haker, powtarzając tę ​​samą operację, całkowicie wycofuje środki z wrażliwej umowy. 

Jak uciec od inteligentnych kontraktów ze szponów ataków wtórnych?

Funkcje funkcji awaryjnej używanej przez atakującego 

  • Można je wywoływać zewnętrznie. Oznacza to, że nie można ich wywołać z poziomu umowy, którą spisano
  • Nienazwana funkcja
  • Funkcja rezerwowa nie zawiera w sobie żadnej logiki
  • Rezerwa jest uruchamiana, gdy ETH jest wysyłane do otaczającej go inteligentnej umowy i nie jest zadeklarowana żadna funkcja odbierania ().

Analiza ataku ponownego wejścia z technicznego punktu widzenia 

Weźmy przykładową umowę i zrozummy, jak przebiega atak ponownego wejścia.

Złośliwy 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();
    }


}

Jest to kontrakt atakującego, w którym atakujący deponuje 2ETH. Atakujący wywołuje funkcję wycofania w podatnym kontrakcie. Po otrzymaniu środków z wrażliwej umowy uruchamiana jest funkcja rezerwowa. 

Rezerwa następnie wykonuje funkcję wycofania i drenuje fundusz z wrażliwego kontraktu. Cykl ten trwa do momentu całkowitego wyczerpania środków z wrażliwego kontraktu.

Wrażliwy 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;
    }


}

Wrażliwy kontrakt ma 30 ETH. W tym przypadku funkcja wycofania () wysyła żądaną kwotę do atakującego. Ponieważ saldo nie jest aktualizowane, tokeny są wielokrotnie przekazywane atakującemu. 

Rodzaje ataków ponownego wejścia

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

Funkcja msg.sender.call.value(amount)() przesyła środki, po czym funkcja rezerwowa kontraktu osoby atakującej ponownie wywołuje funkcję wycofania () przed zaktualizowaniem salda [msg.sender] = 0.

  • Reentrancja międzyfunkcyjna
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;
}

Reentrancja międzyfunkcyjna jest o wiele bardziej skomplikowana do zidentyfikowania. Różnica polega na tym, że funkcja rezerwowa wywołuje transfer, w przeciwieństwie do ponownego wejścia w jedną funkcję, gdzie wywołuje wycofanie.

Zapobieganie atakom ponownego wejścia

Wzorzec czeki-efekty-interakcje: Wzorzec kontrole-efekty-interakcje pomaga w ustrukturyzowaniu funkcji. 

Program powinien być zakodowany w sposób, który najpierw sprawdza warunki. Po przejściu kontroli należy rozstrzygnąć wpływ na stan kontraktów, po czym można wywołać funkcje zewnętrzne. 

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

Przepisany tutaj kod jest zgodny ze wzorcem kontrole-efekty-interakcje. Tutaj saldo jest zerowane przed wykonaniem połączenia zewnętrznego. 

Użycie modyfikatora

Modyfikator noReentrant zastosowany do funkcji zapewnia brak wywołań ponownego wejścia. 

contract ReEntrancyGuard {
    bool internal locked;

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

W końcu

Najskuteczniejszym krokiem jest podjęcie audytów inteligentnych kontraktów od wiodącej firmy zajmującej się bezpieczeństwem, takiej jak QuillAudits, w której audytorzy uważnie obserwują strukturę kodu i sprawdzają, jak działa funkcja rezerwowa. Na podstawie zbadanych wzorców podane są zalecenia dotyczące restrukturyzacji kodu, jeśli takie istnieją wrażliwe zachowania

Bezpieczeństwo środków jest zapewnione tuż przed popadnięciem w jakiekolwiek straty. 

Najczęściej zadawane pytania

Co to jest atak reentrancyjny?

Atak reentrancy ma miejsce, gdy funkcja w kontrakcie podatnym na ataki wywołuje niezaufany kontrakt. Niezaufany kontrakt będzie kontraktem atakującego, który będzie wykonywał rekurencyjne wywołania podatnego kontraktu, dopóki fundusze nie zostaną całkowicie wyczerpane. 

Co to jest reentrant?

Czynność ponownego wprowadzenia polega na przerwaniu wykonywania kodu i rozpoczęciu całego procesu od nowa, co jest również nazywane ponownym wprowadzeniem.

Co to jest strażnik ponownego wejścia?

Ochrona ponownego wejścia używa modyfikatora, który zapobiega wielokrotnemu wywoływaniu funkcji. Przeczytaj powyższy blog, aby znaleźć przykład strażnika ponownego wejścia.

Jakie są niektóre ataki na inteligentne kontrakty?

Inteligentne kontrakty są narażone na liczne luki, takie jak ponowne wejście, zależność od znaczników czasu, przepełnienia arytmetyczne, ataki DoS i tak dalej. Dlatego audyt jest koniecznością, aby upewnić się, że nie ma błędów, które zaburzają logikę umowy.

69 odwiedzajacy

Znak czasu:

Więcej z Quillhash