Ungeprüfte Externe Aufrufe: Ignorierte Rückgabewerte in Solidity
Ein ungeprüfter externer Aufruf in Solidity tritt auf, wenn ein Smart Contract mit einem anderen Vertrag oder einer externen Adresse interagiert, aber das Ergebnis dieser Interaktion nicht überprüft. Diese Nachlässigkeit kann dazu führen,
Struktur, Lesbarkeit, interne Verlinkung und SEO-Metadaten wurden automatisiert geprüft. Der Artikel wird fortlaufend aktualisiert und dient der Bildung, nicht als Finanzberatung.
Definition
Stellen Sie sich vor, Sie verschicken ein Paket und überprüfen nicht, ob es tatsächlich am Zielort angekommen ist. In der Welt der Smart Contracts stellt ein ungeprüfter externer Aufruf eine ähnliche Nachlässigkeit dar. Er tritt auf, wenn ein Solidity-Smart-Contract eine Interaktion mit einem anderen Vertrag oder einer externen Adresse initiiert, aber das Ergebnis dieser Interaktion kritisch vernachlässigt. Dies bedeutet, dass der Vertrag seine Operationen fortsetzt und Erfolg annimmt, selbst wenn der externe Aufruf stillschweigend fehlgeschlagen ist.
Diese Schwachstelle entsteht hauptsächlich, weil Low-Level-Funktionen in Solidity, wie .call(), .send() und delegatecall, die Transaktion bei einem Fehler der externen Operation nicht automatisch rückgängig machen (revertieren). Stattdessen geben sie einen booleschen Wert zurück, der den Erfolg oder Misserfolg anzeigt. Wenn ein Entwickler die Überprüfung dieses Rückgabewerts übersieht, kann der Vertrag mit einem inkonsistenten Zustand weiter ausgeführt werden, was die Tür für verschiedene Exploits öffnet.
Kernaussage
Die Hauptgefahr ungeprüfter externer Aufrufe liegt im Potenzial eines Smart Contracts, unter falschen Voraussetzungen zu operieren, was zu einem inkonsistenten internen Zustand oder dem Verlust von Vermögenswerten führen kann. Durch das Ignorieren des Erfolgs oder Misserfolgs einer externen Interaktion vertraut der Vertrag implizit der externen Entität – ein Vertrauen, das bei Verletzung katastrophale Folgen für das Protokoll und seine Nutzer haben kann.
Mechanik
In Solidity müssen Smart Contracts häufig mit anderen Verträgen interagieren oder Ether an externe Adressen senden. Diese Interaktionen werden typischerweise mithilfe von Low-Level-Funktionen oder übergeordneten Abstraktionen durchgeführt. Die gängigsten Low-Level-Funktionen sind call(), delegatecall(), staticcall() und send().
Insbesondere die Funktion .call() ist die vielseitigste und gibt ein Tupel (bool success, bytes memory data) zurück. Der boolesche Wert success zeigt an, ob der Aufruf erfolgreich war. Wenn dieser success-Wert nicht überprüft wird, wird der Vertrag unabhängig vom Ergebnis des externen Aufrufs weiter ausgeführt. Wenn beispielsweise eine Token-Übertragung innerhalb eines DeFi-Protokolls fehlschlägt, aber der interne Kontostand des Protokolls so aktualisiert wird, als wäre die Übertragung erfolgreich gewesen, entsteht eine Diskrepanz, die ausgenutzt werden kann. Ähnlich gibt .send() einen bool-Wert zurück, der Erfolg oder Misserfolg anzeigt, leitet aber eine feste Menge Gas (2300 Gas) weiter, was es für Aufrufe, die mehr Gas erfordern, oder für die Interaktion mit Verträgen, die mehr Gas verbrauchen könnten, ungeeignet macht. Wenn send() false zurückgibt und dies ignoriert wird, schlägt die Ether-Übertragung effektiv fehl, aber der Kontostand des Senders könnte intern trotzdem reduziert werden.
Höhere Funktionen wie transfer() (für Ether) verhalten sich anders; vor Solidity 0.8.0 würde transfer() bei einem Fehler revertieren, leitete aber auch eine begrenzte Menge Gas weiter. Nach 0.8.0 revertiert transfer() einfach bei einem Fehler, was es in Bezug auf die Überprüfung des Rückgabewerts sicherer macht, aber immer noch durch die Gasweiterleitung begrenzt ist. Die Hauptbedenken bei ungeprüften externen Aufrufen drehen sich jedoch um call() und send(), bei denen der explizite boolesche Rückgabewert unbedingt behandelt werden muss. Darüber hinaus halten sich einige ältere oder nicht-standardisierte ERC-20-Token möglicherweise nicht strikt an die Rückgabewertspezifikation des ERC-20-Standards für transfer() oder transferFrom(), was zu Problemen führen kann, wenn ein Vertrag einen booleschen Rückgabewert erwartet, der nicht bereitgestellt oder falsch interpretiert wird.
Trading-Relevanz
Ungeprüfte externe Aufrufe haben erhebliche Auswirkungen auf dezentrale Finanzsysteme (DeFi) und das breitere Krypto-Trading-Ökosystem. Protokolle, die große Mengen an Vermögenswerten verwalten, wie dezentrale Börsen (DEXs), Kreditplattformen und Yield-Aggregatoren, sind besonders anfällig. Wenn beispielsweise eine DEX einen Token-Swap durch Aufruf der transferFrom-Funktion eines anderen Vertrags initiiert, aber dessen Erfolg nicht überprüft, könnte sie einem Nutzer fälschlicherweise Token gutschreiben, die dieser nie erhalten hat, oder Gelder freigeben, ohne die entsprechenden eingehenden Vermögenswerte zu erhalten. Dies kann zu einem Ungleichgewicht in den Reserven des Protokolls führen, was Liquiditätsanbieter und Trader gleichermaßen betrifft.
Für Trader bedeutet diese Schwachstelle potenzielle finanzielle Verluste. Stellen Sie sich vor, Sie nehmen an einem Liquiditätspool teil, dessen zugrunde liegender Smart Contract anfällig für ungeprüfte externe Aufrufe ist. Ein böswilliger Akteur könnte dies ausnutzen, um Gelder abzuziehen oder Salden zu manipulieren, was zu einem impermanenten Verlust oder sogar zum Totalverlust der eingesetzten Vermögenswerte für legitime Teilnehmer führen kann. Die Integrität von Token-Transfers, Einzahlungen und Abhebungen ist im Handel von größter Bedeutung, und jedes Versäumnis, diese Operationen zu bestätigen, kann das Vertrauen untergraben und die Marktpreise für betroffene Vermögenswerte destabilisieren. Daher ist das Verständnis dieser Schwachstelle unerlässlich, um die Sicherheitslage eines DeFi-Protokolls zu bewerten, bevor man sich damit befasst.
Risiken
Die Risiken, die mit ungeprüften externen Aufrufen verbunden sind, sind vielfältig und können schwerwiegende Folgen für Smart Contracts und ihre Nutzer haben. Das unmittelbarste Risiko ist die Zustandsinkonsistenz. Wenn ein externer Aufruf, wie eine Token-Übertragung, fehlschlägt, der aufrufende Vertrag aber seinen internen Zustand so aktualisiert, als wäre die Übertragung erfolgreich gewesen, stimmt die interne Buchführung des Vertrags nicht mehr mit dem tatsächlichen Zustand der Vermögenswerte auf der Blockchain überein. Diese Diskrepanz kann ausgenutzt werden, um Gelder abzuziehen, unautorisierte Token zu prägen oder Zugangskontrollen zu umgehen.
Ein weiteres erhebliches Risiko ist das Potenzial für Reentrancy-Angriffe. Obwohl keine Reentrancy-Schwachstelle an sich, kann ein ungeprüfter externer Aufruf die Bedingungen dafür schaffen. Wenn ein Vertrag seinen Zustand nach einem externen Aufruf aktualisiert (z. B. einen Kontostand nach dem Senden von Ether reduziert) und der externe Aufruf an einen bösartigen Vertrag erfolgt, der den ursprünglichen Vertrag erneut aufruft (re-enters), könnte der bösartige Vertrag wiederholt Gelder abheben, bevor der Kontostand aktualisiert wird. Das Versäumnis, den Erfolg des externen Aufrufs zu überprüfen, bedeutet, dass der Vertrag möglicherweise nicht einmal bemerkt, dass die ursprüngliche Übertragung fehlgeschlagen ist, was die Reentrancy noch potenter macht. Darüber hinaus können ungeprüfte externe Aufrufe direkt zu Geldverlusten führen, wie in Szenarien, in denen Ether oder Token gesendet, aber nie empfangen werden, der Kontostand des Senders jedoch trotzdem reduziert wird. Dies kann auch die allgemeine Solvenz eines Protokolls beeinträchtigen und bei großflächiger Ausnutzung zu einem vollständigen Zusammenbruch führen.
Geschichte und Beispiele
Eines der anschaulichsten historischen Beispiele, das oft im Kontext von Reentrancy, aber grundlegend ungeprüfte externe Aufrufe betreffend diskutiert wird, ist der King of the Ether Throne-Exploit. Obwohl die primäre Schwachstelle Reentrancy war, beruhte der Erfolg des Exploits darauf, dass der Opfervertrag den Rückgabewert von send() nicht überprüfte, bevor er seinen internen Zustand aktualisierte. Angreifer konnten die claim-Funktion, die send() zum Übertragen von Ether verwendete, wiederholt aufrufen, ohne dass der Vertrag überprüfte, ob der send()-Vorgang erfolgreich war, bevor er weitere Ansprüche zuließ. Dies ermöglichte es dem Angreifer, das Ether des Vertrags durch mehrfaches erneutes Aufrufen der claim-Funktion innerhalb einer einzigen Transaktion abzuziehen, bevor der interne Kontostand aktualisiert wurde.
Ein direkteres und häufigeres Beispiel betrifft nicht-standardisierte ERC-20-Token. Der ERC-20-Standard schreibt vor, dass die Funktionen transfer() und transferFrom() einen booleschen Wert zurückgeben sollten, der den Erfolg anzeigt. Einige ältere oder nicht-konforme Token, wie bestimmte Versionen von USDT (Tether), gaben jedoch nicht immer einen booleschen Wert zurück oder revertierten stattdessen, anstatt bei einem Fehler false zurückzugeben. Wenn ein Smart Contract, der mit einem solchen Token interagierte, einen booleschen Rückgabewert erwartete und keinen erhielt (oder den Revert nicht korrekt behandelte), konnte dies zu unerwartetem Verhalten führen. Zum Beispiel könnte ein Vertrag annehmen, dass eine Übertragung erfolgreich war, weil er nicht explizit false erhielt, selbst wenn die zugrunde liegende Token-Operation fehlschlug. Dies unterstreicht die Bedeutung, externe Token-Aufrufe mit call() zu umschließen und dessen success-Rückgabewert explizit zu überprüfen, insbesondere wenn man mit Token arbeitet, die sich möglicherweise nicht strikt an den Standard halten.
Häufige Missverständnisse
Ein häufiges Missverständnis unter Entwicklern ist die Annahme, dass alle externen Aufrufe, insbesondere solche, die Ether-Transfers wie transfer() oder send() betreffen, die Transaktion bei einem Fehler automatisch rückgängig machen (revertieren). Während transfer() (insbesondere in Solidity 0.8.0+) bei einem Fehler revertiert, tun dies send() und call() nicht. Sie geben einen booleschen Wert zurück, der den Erfolg oder Misserfolg anzeigt, und es liegt in der Verantwortung des Entwicklers, diesen Wert explizit zu überprüfen. Das Ignorieren dieses booleschen Werts ist die Wurzel der Schwachstelle ungeprüfter externer Aufrufe.
Ein weiteres häufiges Missverständnis ist, dass übergeordnete Abstraktionen oder Bibliotheken irgendwie von Natur aus davor schützen. Obwohl einige Bibliotheken Überprüfungen enthalten mögen, ist es gefährlich, sich auf implizite Sicherheit zu verlassen. Entwickler müssen immer explizit den Erfolg jeder externen Interaktion überprüfen, unabhängig von der verwendeten Methode. Darüber hinaus verwechseln einige diese Schwachstelle ausschließlich mit Reentrancy. Obwohl ungeprüfte externe Aufrufe Reentrancy erleichtern können, sind sie unterschiedlich. Ein ungeprüfter externer Aufruf bezieht sich auf das Ignorieren des Ergebnisses eines externen Funktionsaufrufs, was auch ohne einen Reentrancy-Versuch zu Zustandsinkonsistenzen führen kann. Reentrancy ist, wenn ein externer Vertrag den ursprünglichen Vertrag erneut aufruft, bevor dessen Zustand vollständig aktualisiert wurde. Die beiden können sich kombinieren, um schwerwiegendere Exploits zu erzeugen, sind aber separate Schwachstellen.
Zusammenfassung
Ungeprüfte externe Aufrufe stellen einen grundlegenden Sicherheitsfehler in Solidity-Smart-Contracts dar, der aus dem Versäumnis resultiert, die Rückgabewerte externer Interaktionen zu überprüfen. Diese Nachlässigkeit kann dazu führen, dass ein Vertrag mit einem inkonsistenten internen Zustand operiert, wodurch er anfällig für verschiedene Exploits wird, einschließlich finanzieller Verluste und Reentrancy-Angriffe. Entwickler müssen einen defensiven Programmieransatz verfolgen und die booleschen Rückgabewerte von Low-Level-Aufrufen wie .call() und .send() explizit überprüfen. Durch die sorgfältige Validierung des Erfolgs jeder externen Interaktion können Smart-Contract-Entwickler die Sicherheit und Zuverlässigkeit ihrer dezentralen Anwendungen erheblich verbessern, Benutzergelder schützen und die Integrität des Blockchain-Ökosystems wahren. Diese Wachsamkeit ist von größter Bedeutung für den Aufbau robuster und vertrauenswürdiger Protokolle in der sich ständig weiterentwickelnden Landschaft von Web3.
OKX EU · Offizieller Biturai-Partner
OKX EU
Entdecke das aktuelle Angebot von OKX EU über den offiziellen Biturai-Partnerlink. Produkte und Verfügbarkeit können je Land abweichen.
OKX EU ansehenPartnerlink · Biturai kann bei Nutzung eine Vergütung erhalten · keine Anlageberatung
