Die jüngste Schwachstelle im Curve-Pool unterscheidet sich von den Kryptowährungs-Hacking-Vorfällen, die wir zuvor gesehen haben, da das Problem dieses Mal nicht direkt mit der Schwachstelle des Smart Contracts selbst zusammenhängt, sondern mit dem zugrunde liegenden Compiler der von Vyper verwendeten Programmiersprache.

Vyper ist eine intelligente, vertragsorientierte Programmiersprache, die einen Python-ähnlichen Stil annimmt und speziell für die Interaktion mit der Ethereum Virtual Machine (EVM) entwickelt wurde.

Die Auswirkungen dieser Sicherheitslücke sind sehr schwerwiegend und täglich werden in den Nachrichten große Verlustmengen gemeldet. Die Situation scheint unter Kontrolle zu sein, aber nicht bevor Hacker mehr als 70 Millionen Dollar gestohlen haben. Laut der Nachbewertung von LlamaRisk wurden auch einige DeFi-Projektpools von Hackern angegriffen, darunter der pETH/ETH-Pool von PEGD, der 11 Millionen US-Dollar verlor, der msETH/ETH-Pool von Metronome, der 3,4 Millionen US-Dollar verlor, und der alETH/ETH-Pool von Alchemix, der 11 Millionen US-Dollar verlor Mio. 22,6 Millionen US-Dollar, während der Curve DAO-Pool rund 24,7 Millionen US-Dollar verlor.

Diese Sicherheitslücke wird als Wiedereintrittsfehler bezeichnet und tritt hauptsächlich in einigen Versionen der Programmiersprache Vyper auf, insbesondere in Version 0.2.15, Version 0.2.16 und Version 0.3.0. Daher können Projekte, die diese spezifischen Versionen von Vyper verwenden, zum Ziel von Angriffen werden.

Was ist Wiedereintritt?​

Um zu verstehen, warum diese Sicherheitslücke aufgetreten ist, wollen wir zunächst verstehen, was Wiedereintritt ist und wie es funktioniert.

Der sogenannte Reentrancy bedeutet, dass eine Funktion während der Ausführung unterbrochen und sicher erneut aufgerufen werden kann, bevor der vorherige Aufruf abgeschlossen ist. Dieser Mechanismus wird häufig in Anwendungen wie der Verarbeitung von Hardware-Interrupts und der Rekursion verwendet.

Damit eine Funktion wiedereintrittsfähig ist, muss sie einige Bedingungen erfüllen:

Erstens können keine globalen und statischen Daten verwendet werden. Dies ist eine Konvention, was bedeutet, dass man sich bei der Ausführung der Funktion nicht auf globale Daten oder statische Variablen verlassen darf. Denn wenn eine Funktion während der Ausführung unterbrochen und dann erneut aufgerufen wird, können globale und statische Daten beschädigt werden oder Informationen verloren gehen.

Zweitens kann es seinen eigenen Code nicht ändern. Unabhängig davon, wann eine Funktion unterbrochen wird, sollte die Ausführung auf die gleiche Weise fortgesetzt werden können. Wenn eine Funktion während der Ausführung ihren eigenen Code ändert, kann es beim erneuten Aufruf zu einem Fehler kommen.

Schließlich können keine anderen Funktionen aufgerufen werden, die nicht wiedereintrittsfähig sind. Das heißt, Sie sollten innerhalb einer wiedereintrittsfähigen Funktion keine anderen Funktionen aufrufen, die möglicherweise nicht wiedereintrittsfähig sind. Denn wenn Sie dies tun, kann es zu unvorhersehbaren Ergebnissen kommen, die zum Absturz des Programms oder zu Fehlern führen können.

Es ist zu schwer zu verstehen, deshalb gehen wir nicht auf Details ein.

Wie wurde es ausgenutzt?

Lassen Sie uns erklären, wie Wiedereintrittsangriffe beim Curve-Angriff zum Diebstahl von Geldern und zum Verlust von 70 Millionen US-Dollar führten.

Zunächst einmal wissen wir, dass sich ein Wiedereintrittsangriff auf eine Methode bezieht, bei der ein böswilliger Vertrag wiederholt eine Funktion in einem Smart Contract aufruft. Beim Curve-Angriff wird diese Funktion verwendet, um dem Benutzer die Liquidität im Pool zu entziehen. Der Nachteil dieser Funktion besteht darin, dass sie vor der Aktualisierung des Betrags nicht genügend Prüfungen durchführt.

Schauen wir uns den spezifischen Prozess des Angriffs an:

  1. Nehmen wir an, ein anfälliger Smart Contract hat 10 Ether.

  2. Der Angreifer ruft die Einzahlungsfunktion auf und zahlt 1 Ethereum ein.

  3. Der Angreifer ruft dann die Auszahlungsfunktion auf und bereitet die Auszahlung von 1 Ethereum vor. In dieser Funktion wird geprüft, ob der Angreifer 1 Ethereum auf seinem Konto hat.

  4. Diese Funktion aktualisiert jedoch nicht den Saldo im Vertrag, bevor 1 Ether auf das Konto des Angreifers übertragen wird. Das bedeutet, dass der Vertrag immer noch davon ausgeht, dass sich 10 Ether darin befinden.

  5. Der Angreifer ruft die Auszahlungsfunktion (Re-Entry) erneut auf und bereitet sich darauf vor, erneut 1 Ethereum abzuheben.

  6. Da der Vertrag immer noch davon ausgeht, dass sich 10 Ether darin befinden, wird er erneut 1 Ether an den Angreifer übertragen.

  7. Dieser Vorgang wiederholt sich, bis im Vertrag keine Liquidität mehr vorhanden ist.

Auf diese Weise kann der Angreifer wiederholt die Auszahlungsfunktion aufrufen und nahezu die gesamte Liquidität im Vertrag auf sein eigenes Konto übertragen, wodurch die Gelder im Vertrag gestohlen werden.

Diese Sicherheitslücke ist für den Angreifer sehr vorteilhaft, da der Betrag im Vertrag nicht in Echtzeit aktualisiert wird, sodass der Angreifer den Angriff wiederholen kann, bis im Vertrag kein Geld mehr zum Abheben verfügbar ist. #Crv