Die Enzyklopädie der Smart Contract Attacks & Vulnerabilities


In diesem Abschnitt werden bekannte Angriffe beschrieben, mit denen Sicherheitslücken bei intelligenten Verträgen ausgenutzt werden können.

Front-Running-Abhängigkeit von AKA-Transaktionen

Die University of Concordia betrachtet Front-Running als „eine Vorgehensweise, bei der ein Unternehmen vom vorherigen Zugriff auf privilegierte Marktinformationen über bevorstehende Transaktionen und Trades profitiert.“ Diese Kenntnis zukünftiger Ereignisse in einem Markt kann zur Ausbeutung führen.

Wenn ein schlechter Akteur beispielsweise weiß, dass ein sehr großer Kauf eines bestimmten Tokens stattfinden wird, kann er diesen Token im Voraus kaufen und ihn mit Gewinn verkaufen, wenn der übergroße Kaufauftrag den Preis erhöht.

Front-Running-Angriffe sind seit langem ein Problem auf den Finanzmärkten. Aufgrund der Transparenz der Blockchain tritt das Problem auf den Märkten für Kryptowährungen erneut auf.

Da die Lösung für dieses Problem je nach Vertrag unterschiedlich ist, kann es schwierig sein, sich davor zu schützen. Mögliche Lösungen umfassen das Batching von Transaktionen und die Verwendung eines Pre-Commit-Schemas, d. H. Die Möglichkeit für Benutzer, Details zu einem späteren Zeitpunkt einzureichen.

DoS mit Blockgaslimit

In der Ethereum-Blockkette haben alle Blöcke ein Gaslimit. Einer der Vorteile eines Blockgaslimits besteht darin, dass Angreifer daran gehindert werden, eine unendliche Transaktionsschleife zu erstellen. Wenn der Gasverbrauch einer Transaktion dieses Limit überschreitet, schlägt die Transaktion jedoch fehl. Dies kann auf verschiedene Arten zu einem DoS-Angriff führen.

Ungebundener Betrieb

Eine Situation, in der das Blockgaslimit ein Problem sein kann, besteht darin, Gelder an eine Reihe von Adressen zu senden. Auch ohne böswillige Absicht kann dies leicht schief gehen. Nur durch eine zu große Anzahl von Benutzern, die zu zahlen sind, kann das Gaslimit maximiert und verhindert werden, dass die Transaktion jemals erfolgreich ist.

Diese Situation kann auch zu einem Angriff führen. Angenommen, ein schlechter Schauspieler beschließt, eine erhebliche Anzahl von Adressen zu erstellen, wobei jeder Adresse eine kleine Summe aus dem Smart-Vertrag gezahlt wird. Wenn dies effektiv durchgeführt wird, kann die Transaktion auf unbestimmte Zeit blockiert werden, möglicherweise wird sogar verhindert, dass weitere Transaktionen durchgeführt werden.

Eine effektive Lösung für dieses Problem wäre die Verwendung eines Pull-Payment-Systems über das derzeitige Push-Payment-System. Trennen Sie dazu jede Zahlung in ihre eigene Transaktion und lassen Sie den Empfänger die Funktion aufrufen.

Wenn Sie aus irgendeinem Grund wirklich eine Schleife durch ein Array mit nicht angegebener Länge durchführen müssen, müssen Sie mindestens damit rechnen, dass es möglicherweise mehrere Blöcke enthält und in mehreren Transaktionen ausgeführt werden kann – wie im folgenden Beispiel dargestellt:

Beispiel von Consensys

Blockfüllung

In einigen Situationen kann Ihr Vertrag mit einem Blockgaslimit angegriffen werden, auch wenn Sie keine Schleife über ein Array von nicht angegebener Länge ausführen. Ein Angreifer kann mehrere Blöcke füllen, bevor eine Transaktion mit einem ausreichend hohen Gaspreis abgewickelt werden kann.

Dieser Angriff erfolgt durch Ausgabe mehrerer Transaktionen zu einem sehr hohen Gaspreis. Wenn der Gaspreis hoch genug ist und die Transaktionen genügend Gas verbrauchen, können sie ganze Blöcke füllen und verhindern, dass andere Transaktionen verarbeitet werden.

Bei Transaktionen mit Ethereum muss der Absender Gas bezahlen, um Spam-Angriffe zu verhindern. In einigen Situationen kann jedoch ein ausreichender Anreiz für einen solchen Angriff bestehen. Beispielsweise wurde ein Block-Stuffing-Angriff auf eine Glücksspiel-App, Fomo3D, ausgeführt. Die App hatte einen Countdown-Timer, und Benutzer konnten einen Jackpot gewinnen, indem sie als letzte einen Schlüssel kauften. Allerdings wurde der Timer jedes Mal verlängert, wenn ein Benutzer einen Schlüssel kaufte. Ein Angreifer kaufte einen Schlüssel und stopfte dann die nächsten 13 Blöcke und eine Reihe, um den Jackpot zu gewinnen.

Um solche Angriffe zu verhindern, ist es wichtig zu prüfen, ob es sicher ist, zeitbasierte Aktionen in Ihre Anwendung aufzunehmen.

DoS with (Unexpected) Revert

DoS-Angriffe (Denial of Service) können in Funktionen auftreten, wenn Sie versuchen, Gelder an einen Benutzer zu senden, und die Funktionalität davon abhängt, dass diese Überweisung erfolgreich ist.

Dies kann problematisch sein, wenn die Gelder an einen intelligenten Vertrag gesendet werden, der von einem schlechten Akteur erstellt wurde, da diese einfach eine Fallback-Funktion erstellen können, die alle Zahlungen zurücksetzt.

Beispielsweise:

Beispiel von Consensys

Wie Sie in diesem Beispiel sehen können, kann ein Angreifer, der aus einem intelligenten Vertrag mit einer Fallback-Funktion bietet, bei dem alle Zahlungen zurückgesetzt werden, niemals eine Rückerstattung erhalten, sodass niemand jemals ein höheres Gebot abgeben kann.

Dies kann auch problematisch sein, wenn kein Angreifer anwesend ist. Beispielsweise möchten Sie möglicherweise ein Array von Benutzern bezahlen, indem Sie das Array durchlaufen, und Sie möchten natürlich sicherstellen, dass jeder Benutzer ordnungsgemäß bezahlt wird. Das Problem hierbei ist, dass wenn eine Zahlung fehlschlägt, die Funktion zurückgesetzt wird und niemand bezahlt wird.

Beispiel von Consensys

Eine effektive Lösung für dieses Problem wäre die Verwendung eines Pull-Payment-Systems über das derzeitige Push-Payment-System. Trennen Sie dazu jede Zahlung in ihre eigene Transaktion und lassen Sie den Empfänger die Funktion aufrufen.

Beispiel von Consensys

Ether zwangsweise an einen Vertrag senden

Gelegentlich ist es nicht erwünscht, dass Benutzer Ether an einen intelligenten Vertrag senden können. Leider ist es unter diesen Umständen möglich, eine Vertrags-Fallback-Funktion zu umgehen und Ether zwangsweise zu senden.

Beispiel von Consensys

Obwohl es so aussieht, als müsste jede Transaktion in Bezug auf den verwundbaren Vertrag rückgängig gemacht werden, gibt es tatsächlich ein paar Möglichkeiten, Ether mit Gewalt zu senden.

Die erste Methode ist das Aufrufen der Selbstzerstörung Methode für einen Vertrag mit der als Begünstigter festgelegten Adresse des gefährdeten Vertrags. Das funktioniert weil Selbstzerstörung löst die Fallback-Funktion nicht aus.

Eine andere Methode besteht darin, die Adresse eines Vertrags vorab zu berechnen und Ether an die Adresse zu senden, bevor der Vertrag überhaupt bereitgestellt wird. Überraschenderweise ist dies möglich.

Unzureichende Gasversorgung

Trauer ist eine Art von Angriff, die häufig in Videospielen ausgeführt wird, in denen ein böswilliger Benutzer ein Spiel auf unbeabsichtigte Weise spielt, um andere Spieler zu stören. Dies wird auch als Trolling bezeichnet. Diese Art von Angriff wird auch verwendet, um zu verhindern, dass Transaktionen wie beabsichtigt ausgeführt werden.

Dieser Angriff kann auf Verträge erfolgen, die Daten akzeptieren und in einem Unteraufruf für einen anderen Vertrag verwenden. Diese Methode wird häufig in Multisignatur-Wallets sowie in Transaktions-Relayern verwendet. Wenn der Unteraufruf fehlschlägt, wird entweder die gesamte Transaktion zurückgesetzt oder die Ausführung fortgesetzt.

Betrachten wir als Beispiel einen einfachen Relayer-Vertrag. Wie unten gezeigt, ermöglicht der Relayer-Vertrag es jemandem, eine Transaktion zu tätigen und zu unterzeichnen, ohne die Transaktion ausführen zu müssen. Dies wird häufig verwendet, wenn ein Benutzer das mit der Transaktion verbundene Gas nicht bezahlen kann.

Beispiel von Consensys

Der Benutzer, der die Transaktion ausführt, der "Weiterleitende", kann Transaktionen effektiv zensieren, indem er nur so viel Gas verwendet, dass die Transaktion ausgeführt wird, jedoch nicht so viel Gas, dass der Unteraufruf erfolgreich ist.

Dies kann auf zwei Arten verhindert werden. Die erste Lösung wäre, nur vertrauenswürdigen Benutzern die Weiterleitung von Transaktionen zu ermöglichen. Die andere Lösung besteht darin, zu verlangen, dass der Spediteur genügend Gas liefert, wie unten dargestellt.

Beispiel von Consensys

Wiedereintritt

Wiedereintritt ist ein Angriff, der auftreten kann, wenn ein Fehler in einer Vertragsfunktion dazu führen kann, dass eine Funktionsinteraktion mehrmals ausgeführt wird, wenn dies ansonsten verboten werden sollte. Dies kann verwendet werden, um Gelder aus einem intelligenten Vertrag abzuziehen, wenn diese böswillig verwendet werden. Tatsächlich war Wiedereintritt der Angriffsvektor, der beim DAO-Hack verwendet wurde.

Wiedereintritt in die Einzelfunktion

Ein Einzelfunktions-Wiedereintrittsangriff tritt auf, wenn eine anfällige Funktion dieselbe Funktion ist, die ein Angreifer versucht, rekursiv aufzurufen.

Beispiel von Consensys

Hier sehen wir, dass der Kontostand erst nach Überweisung der Mittel geändert wird. Dies kann einem Hacker ermöglichen, die Funktion viele Male aufzurufen, bevor der Kontostand auf 0 gesetzt wird, wodurch der Smart-Vertrag effektiv geleert wird.

Funktionsübergreifender Wiedereintritt

Ein funktionsübergreifender Wiedereintrittsangriff ist eine komplexere Version desselben Prozesses. Funktionsübergreifende Wiedereintritte treten auf, wenn eine anfällige Funktion den Status mit einer Funktion teilt, die ein Angreifer ausnutzen kann.

Beispiel von Consensys

In diesem Beispiel kann ein Hacker diesen Vertrag über einen Fallback-Funktionsaufruf ausnutzen Transfer() um ausgegebene Mittel zu überweisen, bevor der Kontostand in der Liste auf 0 gesetzt wird abheben() Funktion.

Prävention von Wiedereintritten

Verwenden Sie beim Überweisen von Geldern in einem intelligenten Vertrag senden oder Transfer anstatt Anruf. Das Problem mit der Verwendung Anruf ist, dass es im Gegensatz zu den anderen Funktionen kein Gaslimit von 2300 gibt. Dies bedeutet, dass Anruf kann in externen Funktionsaufrufen verwendet werden, die zur Durchführung von Wiedereintrittsangriffen verwendet werden können.

Eine andere feste Verhütungsmethode ist zu Nicht vertrauenswürdige Funktionen markieren.

Beispiel von Consensys

Für optimale Sicherheit sorgen außerdem die Prüft das Wechselwirkungsmuster. Dies ist eine einfache Faustregel für die Bestellung von Smart Contract-Funktionen.

Die Funktion sollte mit beginnen prüft, z.B. benötigen und behaupten Aussagen.

Als nächstes die Auswirkungen des Vertrags sollte durchgeführt werden, d. h. staatliche Änderungen.

Endlich können wir durchführen Wechselwirkungen mit anderen intelligenten Verträgen, z.B. externe Funktionsaufrufe.

Diese Struktur ist wirksam gegen Wiedereintritt, da der geänderte Vertragsstatus schlechte Akteure daran hindert, böswillige Interaktionen durchzuführen.

Beispiel von Consensys

Da der Kontostand vor der Ausführung von Interaktionen auf 0 gesetzt wird, ist nach dem rekursiven Aufrufen des Vertrags nach der ersten Transaktion nichts mehr zu senden.

In diesem Abschnitt werden bekannte Sicherheitslücken bei intelligenten Verträgen und deren Vermeidung beschrieben. Nahezu alle hier aufgeführten Schwachstellen finden Sie in der Smart Contract Weakness Classification.

Ganzzahliger Überlauf und Unterlauf

In Solidity haben Integer-Typen Maximalwerte. Beispielsweise:

uint8 => 255

uint16 => 65535

uint24 => 16777215

uint256 => (2 ^ 256) – 1

Überlauf- und Unterlauffehler können auftreten, wenn Sie den Maximalwert (Überlauf) überschreiten oder den Minimalwert (Unterlauf) unterschreiten. Wenn Sie den Maximalwert überschreiten, gehen Sie zurück auf Null, und wenn Sie den Minimalwert unterschreiten, gelangen Sie zurück auf den Maximalwert.

Da kleinere Integer-Typen wie: uint8, uint16haben kleinere Maximalwerte, kann es einfacher sein, einen Überlauf zu verursachen, daher sollten sie mit größerer Vorsicht verwendet werden.

Die wahrscheinlich beste verfügbare Lösung für Überlauf- und Unterlauffehler ist die Verwendung der OpenZeppelin SafeMath-Bibliothek zur Durchführung mathematischer Operationen.

Zeitstempelabhängigkeit

Der Zeitstempel eines Blocks, auf den von zugegriffen wird jetzt oder block.timestamp kann von einem Bergmann manipuliert werden. Es gibt drei Überlegungen, die Sie berücksichtigen sollten, wenn Sie einen Zeitstempel zum Ausführen einer Vertragsfunktion verwenden.

Timestamp-Manipulation

Wenn ein Zeitstempel verwendet wird, um Zufälligkeit zu generieren, kann ein Miner innerhalb von 15 Sekunden nach der Blockvalidierung einen Zeitstempel veröffentlichen. Auf diese Weise kann der Zeitstempel als Wert festgelegt werden, der die Wahrscheinlichkeit erhöht, von der Funktion zu profitieren.

Beispielsweise kann eine Lotterieanwendung den Block-Zeitstempel verwenden, um einen zufälligen Bieter in einer Gruppe auszuwählen. Ein Bergmann kann an der Lotterie teilnehmen und dann den Zeitstempel auf einen Wert ändern, der ihm bessere Gewinnchancen bietet.

Zeitstempel sollten daher nicht zur Erzeugung von Zufälligkeiten verwendet werden.

Die 15-Sekunden-Regel

In der Referenzspezifikation von Ethereum, dem Yellow Paper, ist keine Grenze für die zeitliche Änderung von Blöcken festgelegt. Sie muss lediglich größer sein als der Zeitstempel des übergeordneten Elements. Angesichts dessen lehnen gängige Protokollimplementierungen Blöcke mit Zeitstempeln von mehr als 15 Sekunden in der Zukunft ab. Solange Ihr zeitabhängiges Ereignis sicher um 15 Sekunden variieren kann, ist es sicher, einen Blockzeitstempel zu verwenden.

Nicht benutzen Blocknummer als Zeitstempel

Sie können den Zeitunterschied zwischen Ereignissen mit schätzen Blocknummer und die durchschnittliche Blockierungszeit, aber die Blockierungszeiten können sich ändern und die Funktionalität beeinträchtigen. Vermeiden Sie diese Verwendung daher am besten.

Autorisierung Durch tx.origin

tx.origin ist eine globale Variable in Solidity, die die Adresse zurückgibt, die eine Transaktion gesendet hat. Es ist wichtig, dass Sie niemals verwenden tx.origin zur Autorisierung, da ein anderer Vertrag eine Ausweichfunktion verwenden kann, um Ihren Vertrag aufzurufen und die Autorisierung zu erhalten, da die autorisierte Adresse in gespeichert ist tx.origin. Betrachten Sie dieses Beispiel:

Beispiel aus Solidity-Dokumenten

Hier können wir sehen, dass die TxUserWallet Vertrag autorisiert die transferTo () funktionieren mit tx.origin.

Beispiel aus Solidity-Dokumenten

Nun, wenn dich jemand dazu verleiten würde, Äther an die zu senden TxAttackWallet Vertragsadresse, sie können Ihr Geld durch Überprüfung stehlen tx.origin um die Adresse zu finden, die die Transaktion gesendet hat.

Um diese Art von Angriff zu verhindern, verwenden Sie msg.sender zur Genehmigung.

Schwimmendes Pragma

Es wird als bewährte Methode angesehen, eine Compilerversion auszuwählen und dabei zu bleiben. Mit einem Floating-Pragma können Verträge versehentlich mit einer veralteten oder problematischen Compilerversion bereitgestellt werden, was zu Fehlern führen und die Sicherheit Ihres Smart-Vertrags gefährden kann. Bei Open-Source-Projekten teilt das Pragma den Entwicklern auch mit, welche Version sie verwenden sollen, falls sie Ihren Vertrag bereitstellen. Die ausgewählte Compiler-Version sollte gründlich getestet und auf bekannte Fehler überprüft werden.

Die Ausnahme, in der es akzeptabel ist, ein Floating-Pragma zu verwenden, sind Bibliotheken und Pakete. Andernfalls müssten Entwickler das Pragma manuell aktualisieren, um es lokal zu kompilieren.

Funktion Standardsichtbarkeit

Die Funktionssichtbarkeit kann entweder als öffentlich, privat, intern oder extern angegeben werden. Es ist wichtig zu prüfen, welche Sichtbarkeit für Ihre Smart-Contract-Funktion am besten ist.

Viele intelligente Vertragsangriffe werden dadurch verursacht, dass ein Entwickler die Verwendung eines Sichtbarkeitsmodifikators vergisst oder darauf verzichtet. Die Funktion ist dann standardmäßig als öffentlich festgelegt, was zu unbeabsichtigten Statusänderungen führen kann.

Veraltete Compiler-Version

Entwickler finden häufig Fehler und Schwachstellen in vorhandener Software und erstellen Patches. Aus diesem Grund ist es wichtig, die aktuellste Compiler-Version zu verwenden. Hier finden Sie Fehler aus früheren Compilerversionen.

Deaktivierter Rückgabewert für Anruf

Wenn der Rückgabewert eines Low-Level-Aufrufs nicht überprüft wird, wird die Ausführung möglicherweise fortgesetzt, auch wenn der Funktionsaufruf einen Fehler auslöst. Dies kann zu unerwartetem Verhalten führen und die Programmlogik beschädigen. Ein fehlgeschlagener Anruf kann sogar von einem Angreifer verursacht werden, der die Anwendung möglicherweise weiter ausnutzen kann.

Aus Gründen der Solidität können Sie entweder Anrufe auf niedriger Ebene verwenden, z. address.call (), address.callcode (), address.delegatecall (), und address.send (); oder Sie können Vertragsaufrufe verwenden wie: ExternalContract.doSomething (). Low-Level-Aufrufe lösen niemals eine Ausnahme aus, sondern kehren zurück falsch Wenn sie auf eine Ausnahme stoßen, werden Vertragsaufrufe automatisch ausgelöst.

Stellen Sie sicher, dass Sie den Rückgabewert für den Fall, dass Sie Low-Level-Aufrufe verwenden, überprüfen, um mögliche fehlgeschlagene Aufrufe zu behandeln.

Entnahme ungeschützter Ether

Ohne angemessene Zugangskontrollen können schlechte Schauspieler möglicherweise einen Teil oder den gesamten Ether von einem Vertrag zurückziehen. Dies kann dadurch verursacht werden, dass eine Funktion, die als Konstrukteur gedacht ist, falsch benannt wird und jeder Zugriff auf die Neuinitialisierung des Vertrags erhält. Um diese Sicherheitsanfälligkeit zu vermeiden, sollten Sie nur zulassen, dass Auszahlungen von autorisierten oder bestimmungsgemäßen Personen ausgelöst werden, und Ihren Konstruktor entsprechend benennen.

Ungeschützte Selbstzerstörungsanweisung

In Verträgen, die a Selbstzerstörung Wenn fehlende oder unzureichende Zugriffskontrollen vorhanden sind, können böswillige Akteure den Vertrag selbst zerstören. Es ist wichtig zu überlegen, ob eine Selbstzerstörungsfunktion unbedingt erforderlich ist. Ziehen Sie ggf. die Verwendung einer Multisig-Autorisierung in Betracht, um einen Angriff zu verhindern.

Dieser Angriff wurde im Parity Attack verwendet. Ein anonymer Benutzer hat eine Sicherheitsanfälligkeit im intelligenten Vertrag "Bibliothek" gefunden und ausgenutzt und sich selbst zum Vertragsinhaber gemacht. Der Angreifer machte sich daran, den Vertrag selbst zu zerstören. Dies führte dazu, dass Gelder in 587 einzigartigen Geldbörsen mit insgesamt 513.774,16 Ether gesperrt wurden.

Statusvariable Standardsichtbarkeit

Entwickler deklarieren häufig explizit die Sichtbarkeit von Funktionen, nicht jedoch die Sichtbarkeit von Variablen. Zustandsvariablen können einen von drei Sichtbarkeitsbezeichnern haben: Öffentlichkeit, intern, oder Privatgelände. Glücklicherweise ist die Standardsichtbarkeit für Variablen intern und nicht öffentlich. Auch wenn Sie beabsichtigen, eine Variable als intern zu deklarieren, ist es wichtig, sie explizit anzugeben, damit keine falschen Annahmen darüber bestehen, wer auf die Variable zugreifen kann.

Nicht initialisierter Speicherzeiger

Daten werden im EVM entweder als gespeichert Lager, Erinnerung, oder calldata. Es ist wichtig, dass die beiden gut verstanden und richtig initialisiert sind. Das inkorrekte Initialisieren oder Nichtinitialisieren von Datenspeicherzeigern kann zu Vertragsanfälligkeiten führen.

Aus Solidität 0.5.0sind nicht initialisierte Speicherzeiger kein Problem mehr, da Verträge mit nicht initialisierten Speicherzeigern nicht mehr kompiliert werden. Dennoch ist es wichtig zu verstehen, welche Speicherzeiger Sie in bestimmten Situationen verwenden sollten.

Zuwiderhandlung geltend machen

In Solidität 0.4.10wurden folgende Funktionen erstellt: behaupten(), benötigen(), und zurückkehren(). Hier werden wir die Assert-Funktion und ihre Verwendung diskutieren.

Formell gesagt, die behaupten() Funktion soll Invarianten behaupten; informell gesagt, behaupten() ist ein übermäßig durchsetzungsfähiger Leibwächter, der Ihren Vertrag schützt, dabei aber Ihr Benzin stiehlt. Ordnungsgemäß funktionierende Verträge sollten niemals eine fehlerhafte Aussage treffen. Wenn Sie zu einer fehlgeschlagenen Assert-Anweisung gelangt sind, wurde diese entweder nicht ordnungsgemäß verwendet behaupten(), oder es gibt einen Fehler in Ihrem Vertrag, der ihn in einen ungültigen Zustand versetzt.

Wenn die Bedingung in der eingecheckten behaupten() ist eigentlich keine Invariante. Es wird empfohlen, sie durch eine zu ersetzen benötigen() Aussage.

Verwendung veralteter Funktionen

Im Laufe der Zeit werden Funktionen in Solidity nicht mehr unterstützt und häufig durch bessere Funktionen ersetzt. Es ist wichtig, keine veralteten Funktionen zu verwenden, da dies zu unerwarteten Effekten und Kompilierungsfehlern führen kann.

Hier finden Sie eine Liste veralteter Funktionen und Alternativen. Bei vielen Alternativen handelt es sich lediglich um Aliase, die das derzeitige Verhalten nicht beeinträchtigen, wenn sie als Ersatz für das veraltete Gegenstück verwendet werden.

Veraltete Funktionen und Alternativen

Delegatecall an Untrusted Callee

Delegatecall ist eine spezielle Variante eines Nachrichtenaufrufs. Es ist fast identisch mit einem regulären Nachrichtenanruf, außer dass die Zieladresse im Rahmen des aufrufenden Vertrags ausgeführt wird und msg.sender und msg.value gleich bleiben. Im Wesentlichen, delegatecall delegiert andere Verträge, um den Speicher des aufrufenden Vertrags zu ändern.

Schon seit delegatecall bietet so viel Kontrolle über einen Vertrag, dass es sehr wichtig ist, diesen nur mit vertrauenswürdigen Verträgen wie Ihren eigenen zu verwenden. Wenn die Zieladresse von einer Benutzereingabe stammt, stellen Sie sicher, dass es sich um einen vertrauenswürdigen Vertrag handelt.

Signatur Formbarkeit

Häufig wird davon ausgegangen, dass die Verwendung eines kryptografischen Signatursystems in intelligenten Verträgen die Eindeutigkeit von Signaturen bestätigt. Dies ist jedoch nicht der Fall. Signaturen in Ethereum können ohne den privaten Schlüssel geändert werden und behalten ihre Gültigkeit. Beispielsweise besteht die Kryptografie mit elliptischen Schlüsseln aus drei Variablen: v, r, und s und wenn diese Werte auf die richtige Weise geändert werden, können Sie eine gültige Signatur mit einem ungültigen privaten Schlüssel erhalten.

Um das Problem der Formbarkeit von Signaturen zu vermeiden, verwenden Sie niemals eine Signatur in einem signierten Nachrichten-Hash, um zu überprüfen, ob zuvor signierte Nachrichten vom Vertrag verarbeitet wurden, da böswillige Benutzer Ihre Signatur finden und neu erstellen können.

Falscher Konstruktorname

Vor der Solidität 0,4,22Die einzige Möglichkeit, einen Konstruktor zu definieren, bestand darin, eine Funktion mit dem Vertragsnamen zu erstellen. In einigen Fällen war dies problematisch. Wenn beispielsweise ein Smart-Vertrag mit einem anderen Namen wiederverwendet wird, die Konstruktorfunktion jedoch nicht geändert wird, wird er einfach zu einer regulären, aufrufbaren Funktion.

Mit modernen Versionen von Solidity können Sie jetzt den Konstruktor mit dem Befehl definieren Konstrukteur Schlüsselwort, das diese Sicherheitsanfälligkeit effektiv ausschließt. Daher besteht die Lösung für dieses Problem einfach darin, moderne Solidity-Compiler-Versionen zu verwenden.

Variablen für den Schattenstatus

In Solidity kann dieselbe Variable zweimal verwendet werden, dies kann jedoch zu unbeabsichtigten Nebenwirkungen führen. Dies ist besonders schwierig, wenn Sie mit mehreren Verträgen arbeiten. Nehmen Sie das folgende Beispiel:

Beispiel für Schattenzustandsvariablen

Hier können wir das sehen Untervertrag erbt SuperContract und die Variable ein wird zweimal mit unterschiedlichen Werten definiert. Sagen wir jetzt wir benutzen ein eine Funktion ausführen Untervertrag, Funktionalität, die von geerbt wurde SuperContract wird nicht mehr funktionieren, da der Wert von ein wurde verändert.

Um diese Sicherheitsanfälligkeit zu vermeiden, ist es wichtig, dass das gesamte Smart Contract-System auf Unklarheiten überprüft wird. Es ist auch wichtig, nach Compiler-Warnungen zu suchen, da sie diese Mehrdeutigkeiten kennzeichnen können, solange sie im Smart-Vertrag enthalten sind.

Schwache Zufallsquellen durch Kettenattribute

In Ethereum gibt es bestimmte Anwendungen, die aus Gründen der Fairness auf der Generierung von Zufallszahlen beruhen. Die Erzeugung von Zufallszahlen ist in Ethereum jedoch sehr schwierig, und es gibt mehrere erwägenswerte Fallstricke.

Verwenden von Kettenattributen wie: block.timestamp, Blockhasch, und block.difficulty kann wie eine gute Idee erscheinen, da sie oft Pseudozufallswerte produzieren. Das Problem liegt jedoch in der Fähigkeit eines Bergmanns, diese Werte zu ändern. Beispiel: In einer Glücksspiel-App mit einem Jackpot von mehreren Millionen Dollar besteht für einen Bergarbeiter ein ausreichender Anreiz, viele alternative Blöcke zu generieren, wobei nur der Block ausgewählt wird, der zu einem Jackpot für den Bergarbeiter führt. Natürlich ist es mit erheblichen Kosten verbunden, die Blockchain so zu steuern, aber wenn der Einsatz hoch genug ist, kann dies mit Sicherheit getan werden.

Um die Manipulation von Minern bei der Zufallszahlengenerierung zu vermeiden, gibt es einige Lösungen:

  • Ein Verpflichtungsschema wie RANDAO, ein DAO, bei dem die Zufallszahl von allen Teilnehmern des DAO generiert wird.
  • Externe Quellen über Orakel, z. Oraclize.
  • Verwendung von Bitcoin-Block-Hashes, da das Netzwerk dezentraler ist und Blöcke teurer sind.

Fehlender Schutz vor Signaturwiederholungsangriffen

In intelligenten Verträgen ist es manchmal erforderlich, eine Signaturprüfung durchzuführen, um die Benutzerfreundlichkeit und die Gaskosten zu verbessern. Bei der Implementierung der Signaturüberprüfung muss jedoch berücksichtigt werden. Zum Schutz vor Signaturwiederholungsangriffen sollte der Vertrag nur die Verarbeitung neuer Hashes zulassen. Dadurch wird verhindert, dass böswillige Benutzer die Signatur eines anderen Benutzers mehrmals abspielen.

Befolgen Sie die folgenden Empfehlungen, um bei der Signaturüberprüfung besonders sicher zu sein:

  • Speichern Sie jeden vom Vertrag verarbeiteten Nachrichten-Hash, und vergleichen Sie die Nachrichten-Hashes mit den vorhandenen, bevor Sie die Funktion ausführen.
  • Fügen Sie die Adresse des Vertrags in den Hash ein, um sicherzustellen, dass die Nachricht nur in einem einzelnen Vertrag verwendet wird.
  • Generieren Sie niemals den Nachrichten-Hash einschließlich der Signatur. Siehe Signaturformbarkeit

Anforderungsverletzung

Das benötigen() Diese Methode dient zum Validieren von Bedingungen wie Eingaben oder Vertragsstatusvariablen oder zum Validieren von Rückgabewerten aus externen Vertragsaufrufen. Für die Validierung externer Anrufe können Eingaben von Anrufern bereitgestellt oder von Angerufenen zurückgesendet werden. In dem Fall, dass eine Eingabeverletzung durch den Rückgabewert eines Angerufenen aufgetreten ist, ist wahrscheinlich eines von zwei Dingen schiefgegangen:

  • Es gibt einen Fehler im Vertrag, der die Eingabe geliefert hat.
  • Die Anforderungsbedingung ist zu stark.

Um dieses Problem zu lösen, prüfen Sie zunächst, ob die Anforderungsbedingung zu stark ist. Schwächen Sie sie gegebenenfalls ab, um gültige externe Eingaben zuzulassen. Wenn das Problem nicht die Anforderungsbedingung ist, muss der Vertrag einen Fehler enthalten, der externe Eingaben bereitstellt. Stellen Sie sicher, dass dieser Vertrag keine ungültigen Eingaben enthält.

Schreiben Sie an einen beliebigen Speicherort

Nur autorisierte Adressen sollten Schreibzugriff auf vertrauliche Speicherorte haben. Wenn im gesamten Vertrag keine ordnungsgemäßen Berechtigungsprüfungen durchgeführt werden, kann ein böswilliger Benutzer möglicherweise vertrauliche Daten überschreiben. Selbst wenn Berechtigungsprüfungen zum Schreiben auf vertrauliche Daten durchgeführt werden, kann ein Angreifer die vertraulichen Daten möglicherweise über nicht vertrauliche Daten überschreiben. Dies kann einem Angreifer den Zugriff auf das Überschreiben wichtiger Variablen ermöglichen, z. B. des Vertragsinhabers.

Um dies zu verhindern, möchten wir nicht nur vertrauliche Datenspeicher mit Berechtigungsanforderungen schützen, sondern auch sicherstellen, dass beim Schreiben in eine Datenstruktur nicht versehentlich Einträge einer anderen Datenstruktur überschrieben werden.

Inkorrekte Vererbungsreihenfolge

In Solidity ist es möglich, von mehreren Quellen zu erben, was, wenn es nicht richtig verstanden wird, zu Mehrdeutigkeiten führen kann. Diese Mehrdeutigkeit wird als Diamantproblem bezeichnet. Wenn zwei Basisverträge dieselbe Funktion haben, welche sollte priorisiert werden? Glücklicherweise geht Solidity mit diesem Problem zierlich um, solange der Entwickler die Lösung versteht.

Die Lösung, die Solidität für das Diamantproblem bietet, ist die Verwendung der umgekehrten C3-Linearisierung. Dies bedeutet, dass die Vererbung von rechts nach links linearisiert wird, sodass die Reihenfolge der Vererbung von Bedeutung ist. Es wird empfohlen, mit allgemeineren Verträgen zu beginnen und mit spezifischeren Verträgen zu enden, um Probleme zu vermeiden.

Willkürlicher Sprung mit variablem Funktionstyp

Funktionstypen werden in Solidity unterstützt. Dies bedeutet, dass einer Funktion mit passender Signatur eine Variable vom Typ function zugewiesen werden kann. Die Funktion kann dann wie jede andere Funktion aus der Variablen aufgerufen werden. Benutzer sollten nicht in der Lage sein, die Funktionsvariable zu ändern. In einigen Fällen ist dies jedoch möglich.

Wenn der Smart-Vertrag bestimmte Montageanweisungen verwendet, mstore Beispielsweise kann ein Angreifer die Funktionsvariable auf eine beliebige andere Funktion verweisen. Dies kann dem Angreifer die Möglichkeit geben, die Funktionalität des Vertrags zu beeinträchtigen und möglicherweise sogar die Vertragsmittel zu erschöpfen.

Da die Inline-Montage eine Möglichkeit ist, auf einer niedrigen Ebene auf das EVM zuzugreifen, werden viele wichtige Sicherheitsfunktionen umgangen. Daher ist es wichtig, die Montage nur zu verwenden, wenn dies erforderlich und richtig verstanden ist.

Vorhandensein nicht verwendeter Variablen

Es wird empfohlen, nicht verwendete Variablen zu vermeiden, obwohl dies zulässig ist. Nicht verwendete Variablen können zu verschiedenen Problemen führen:

  • Erhöhung der Berechnungen (unnötiger Gasverbrauch)
  • Anzeige von Fehlern oder fehlerhaften Datenstrukturen
  • Verminderte Lesbarkeit des Codes

Es wird dringend empfohlen, alle nicht verwendeten Variablen aus einer Codebasis zu entfernen.

Unerwartetes Ethergleichgewicht

Da es immer möglich ist, Ether an einen Vertrag zu senden, siehe Ether zwangsweise an einen intelligenten Vertrag senden. Wenn ein Vertrag ein bestimmtes Gleichgewicht annimmt, ist er anfällig für Angriffe.

Angenommen, wir haben einen Vertrag, der die Ausführung aller Funktionen verhindert, wenn im Vertrag Ether gespeichert ist. Wenn ein böswilliger Benutzer dies ausnutzt, indem er Ether zwangsweise sendet, verursacht er einen DoS, wodurch der Vertrag unbrauchbar wird. Aus diesem Grund ist es wichtig, in einem Vertrag niemals strenge Gleichheitsprüfungen für das Ether-Gleichgewicht durchzuführen.

Unverschlüsselte Geheimnisse

Der Smart Contract Code von Ethereum kann immer gelesen werden. Behandle es als solches. Selbst wenn Ihr Code in Etherscan nicht verifiziert ist, können Angreifer ihn dekompilieren oder auch nur Transaktionen von und zu ihm überprüfen, um ihn zu analysieren.

Ein Beispiel für ein Problem wäre hier ein "Ratespiel", bei dem der Benutzer eine gespeicherte private Variable erraten muss, um den Äther im Vertrag zu gewinnen. Dies ist natürlich äußerst trivial auszunutzen (bis zu dem Punkt, dass Sie es nicht ausprobieren sollten, da es sich mit ziemlicher Sicherheit um einen Honeypot-Vertrag handelt, der viel schwieriger ist).

Ein weiteres häufiges Problem ist die Verwendung unverschlüsselter Geheimnisse außerhalb der Kette, z. B. von API-Schlüsseln, bei Oracle-Aufrufen. Wenn Ihr API-Schlüssel ermittelt werden kann, können böswillige Akteure ihn entweder einfach für sich selbst verwenden oder andere Methoden nutzen, z. B. Ihre zulässigen API-Aufrufe erschöpfen und Oracle dazu zwingen, eine Fehlerseite zurückzugeben, die abhängig von möglicherweise zu Problemen führt oder nicht die Struktur des Vertrages.

Fehlerhafte Vertragserkennung

Einige Verträge möchten nicht, dass andere Verträge mit ihnen interagieren. Eine übliche Möglichkeit, dies zu verhindern, besteht darin, zu überprüfen, ob in dem anrufenden Konto ein Code gespeichert ist. Vertragskonten, die während ihrer Erstellung Anrufe einleiten, zeigen jedoch noch nicht an, dass sie Code speichern, wodurch die Vertragserkennung effektiv umgangen wird.

Nicht verstopfte Blockchain Reliance

Viele Verträge basieren auf Anrufen, die innerhalb eines bestimmten Zeitraums getätigt werden, aber Ethereum kann für einen angemessenen Zeitraum relativ billig mit sehr hohen Gwei-Transaktionen überflutet werden.

Zum Beispiel wurde FOMO3D (ein Countdown-Spiel, bei dem der letzte Investor den Jackpot gewinnt, jede Investition jedoch Zeit zum Countdown hinzufügt) von einem Benutzer gewonnen, der die Blockchain für einen kurzen Zeitraum vollständig verstopfte und anderen untersagte, zu investieren, bis der Timer lief raus und er hat gewonnen (siehe DoS mit Block Gas Limit).

Es gibt heutzutage viele Croupier-Glücksspielverträge, die sich auf vergangene Blockhashes stützen, um RNG bereitzustellen. Dies ist zum größten Teil keine schreckliche Quelle für RNG, und sie erklären sogar das Löschen von Hashes, das nach 256 Blöcken erfolgt, aber zu diesem Zeitpunkt machen viele von ihnen einfach den Einsatz null. Dies würde es jemandem ermöglichen, Wetten auf viele dieser ähnlich funktionierenden Verträge mit einem bestimmten Ergebnis als Sieger für alle abzuschließen, die Einreichung des Croupiers zu überprüfen, während sie noch aussteht, und, wenn es ungünstig ist, einfach die Blockchain zu verstopfen, bis das Beschneiden eintritt und Sie können Ihre Wetten zurückerhalten.

Nichteinhaltung von Standards

In Bezug auf die Entwicklung intelligenter Verträge ist es wichtig, Standards zu befolgen. Standards are set to prevent vulnerabilities, and ignoring them can lead to unexpected effects.

Take for example binance’s original BNB token. It was marketed as an ERC20 token, but it was later pointed out that it wasn’t actually ERC20 compliant for a few reasons:

  • It prevented sending to 0x0
  • It blocked transfers of 0 value
  • It didn’t return true or false for success or fail

The main cause for concern with this improper implementation is that if it is used with a smart contract that expects an ERC-20 token, it will behave in unexpected ways. It could even get locked in the contract forever.

Although standards aren’t always perfect, and may someday become antiquated, they foster the most secure smart contracts.

As you can see, there are many ways in which your smart contracts can be exploited. It’s vital that you fully understand each attack vector and vulnerability before building.

If you benefited from this in any way, please consider supporting me by leaving claps as well as following me on Medium and Twitter.

Also, special thanks to RobertMCForster for many excellent contributions.

Coins Kaufen: Bitcoin.deAnycoinDirektCoinbaseCoinMama (mit Kreditkarte)Paxfull

Handelsplätze / Börsen: Bitcoin.de | KuCoinBinanceBitMexBitpandaeToro

Lending / Zinsen erhalten: Celsius NetworkCoinlend (Bot)

Cloud Mining: HashflareGenesis MiningIQ Mining

Werbung: Immobilienmakler HeidelbergMakler Heidelberg

By continuing to use the site, you agree to the use of cookies. more information

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.

Close