Sicherheit von Smart Contracts
Letzte Änderung: @Astronaut828(opens in a new tab), 22. Mai 2024
Smart Contracts sind äußerst flexibel und in der Lage, große Mengen an Werten und Daten zu kontrollieren, während sie eine unveränderliche Logik auf der Grundlage von auf der Blockchain bereitgestelltem Code ausführen. So ist ein lebendiges Ökosystem aus vertrauenswürdigen und dezentralisierten Applikationen entstanden, das viele Vorteile gegenüber den alten Systemen bietet. Sie bieten auch eine Chance für Angreifer, die durch die Ausnutzung von Schwachstellen in Smart Contracts Profit machen wollen.
Öffentliche Blockchains wie Ethereum erschweren das Problem der Sicherung von Smart Contracts zusätzlich. Der Code des veröffentlichten Vertrags kann in der Regel nicht geändert werden, um Sicherheitslücken zu schließen, während die aus Smart Contracts gestohlenen Vermögenswerte aufgrund der Unveränderlichkeit extrem schwer nachzuverfolgen und meist nicht wiederherzustellen sind.
Obwohl die Zahlen variieren, wird geschätzt, dass der Gesamtbetrag des gestohlenen oder verlorenen Werts aufgrund von Sicherheitsmängeln in Smart Contracts weit über 1 Milliarde US-Dollar beträgt. Dies beinhaltet hochkarätige Vorfälle, wie den DAO-Hack(opens in a new tab) (3,6 Mio. ETH gestohlen, nach heutigen Preisen über 1 Milliarde US-Dollar wert), den Parity Multi-Sig Wallet-Hack(opens in a new tab) (30 Mio. US-Dollar von Hackern verloren) und das Problem mit den eingefrorenen Parity-Wallets(opens in a new tab) (über 300 Mio. US-Dollar in ETH gesperrt).
Die oben genannten Probleme machen es für Entwickler zwingend erforderlich, in die Entwicklung sicherer, robuster und widerstandsfähiger Smart Contracts zu investieren. Die Sicherheit von Smart Contracts ist eine ernste Angelegenheit, die jeder Entwickler lernen sollte. In diesem Ratgeber werden Sicherheitsüberlegungen für Ethereum-Entwickler behandelt und Ressourcen zur Verbesserung der Smart Contract-Sicherheit vorgestellt.
Voraussetzungen
Stellen Sie sicher, dass Sie mit den Grundlagen der Smart Contract-Entwicklung vertraut sind, bevor Sie sich mit der Sicherheit befassen.
Richtlinien für die Erstellung sicherer Ethereum Smart Contracts
1. Gestaltung geeigneter Zugriffskontrollen
Bei Smart Contracts können Funktionen, die als public
oder external
markiert sind, von beliebigen extern verwalteten Konten (EOAs) oder Vertragskonten aufgerufen werden. Die Festlegung der öffentlichen Sichtbarkeit von Funktionen ist notwendig, wenn Sie möchten, dass andere Personen mit Ihrem Vertrag interagieren können. Funktionen, die als private
gekennzeichnet sind, können jedoch nur von Funktionen innerhalb des Smart Contracts aufgerufen werden, nicht von externen Accounts. Jedem Netzwerkteilnehmer Zugang zu Vertragsfunktionen zu gewähren, kann zu Problemen führen, insbesondere wenn dies bedeutet, dass jeder Nutzer sensible Operationen durchführen kann (z. B. das Minting neuer Token).
Um die unbefugte Nutzung von Smart Contract-Funktionen zu verhindern, müssen sichere Zugriffskontrollen implementiert werden. Die Zugriffskontrolle beschränkt die Möglichkeit, bestimmte Funktionen in einem Smart Contract zu nutzen, auf zugelassene Stellen, wie z. B. die für die Verwaltung des Vertrags zuständigen Konten. Das Ownable-Modell und Rollenbasierte Kontrolle sind zwei Parameter, die für die Implementierung der Zugriffskontrolle in Smart Contracts nützlich sind:
Ownable-Modell
Beim Ownable-Modell wird während der Vertragserstellung eine Adresse als „Eigentümer“ des Vertrags festgelegt. Geschützten Funktionen wird ein OnlyOwner
-Modifikator zugewiesen, der sicherstellt, dass der Vertrag die Identität der aufrufenden Adresse authentifiziert, bevor die Funktion ausgeführt wird. Aufrufe geschützter Funktionen von anderen Adressen als der des Vertragseigentümers werden immer zurückgewiesen, um unerwünschte Zugriffe zu verhindern.
Rollenbasierte Zugriffskontrolle
Die Registrierung einer einzigen Adresse als Eigentümer
in einem Smart Contract birgt das Risiko der Zentralisierung und stellt einen einzelnen Ausfallpunkt dar. Wenn die Kontoschlüssel des Eigentümers gefährdet sind, können Angreifer den entsprechenden Vertrag angreifen. Aus diesem Grund kann die Verwendung eines rollenbasierten Zugriffskontrollmusters mit mehreren administrativen Konten eine bessere Option sein.
Bei der rollenbasierten Zugriffskontrolle wird der Zugriff auf sensible Funktionen auf eine Reihe von vertrauenswürdigen Teilnehmern verteilt. So kann beispielsweise ein Konto für das Minting von Token zuständig sein, während ein anderes Konto Upgrades durchführt oder den Vertrag pausiert. Durch diese dezentrale Zugriffskontrolle werden „einzelne Ausfallpunkte“ eliminiert und die Vertrauensvoraussetzungen für Benutzer reduziert.
Verwendung von Wallets mit Multi-Signature-Option
Ein weiterer Ansatz für die Implementierung einer sicheren Zugriffskontrolle ist die Verwendung eines Multi-Signatur-Kontos zur Verwaltung eines Vertrags. Im Gegensatz zu einem regulären EOA sind Multi-Signatur-Konten das Eigentum von mehreren Instanzen und erfordern Signaturen von einer Mindestanzahl von Konten, beispielsweise 3 von 5, um Transaktionen auszuführen.
Die Verwendung einer Mehrfachsignatur für die Zugriffskontrolle führt eine zusätzliche Sicherheitsebene ein, da Aktionen auf dem Zielvertrag die Zustimmung von mehreren Parteien erfordern. Dies ist besonders nützlich, wenn die Verwendung der Ownable-Funktion erforderlich ist, da es für einen Angreifer oder einen böswilligen Insider schwieriger ist, sensible Vertragsfunktionen für böswillige Zwecke zu manipulieren.
2. Verwenden Sie die Anweisungen require(), assert() und revert(), um Vertragsoperationen zu schützen.
Wie bereits erwähnt, kann jeder Nutzer öffentliche Funktionen in Ihrem Smart Contract aufrufen, sobald dieser auf der Blockchain veröffentlicht wurde. Da Sie nicht im Voraus wissen können, wie externe Konten mit einem Vertrag interagieren werden, ist es ideal, interne Schutzmaßnahmen gegen problematische Funktionen zu implementieren, bevor Sie sie Veröffentlichen. Sie können korrektes Verhalten in Smart Contracts durch die Verwendung der Anweisungen require()
, assert()
und revert()
erzwingen, um Ausnahmen auszulösen und Zustandsänderungen rückgängig zu machen, wenn die Ausführung bestimmte Anforderungen nicht erfüllt.
require()
: require
werden am Anfang von Funktionen definiert und stellen sicher, dass vordefinierte Bedingungen erfüllt sind, bevor die aufgerufene Funktion ausgeführt wird. Eine require
-Anweisung kann verwendet werden, um Nutzereingaben zu validieren, Zustandsvariablen zu überprüfen oder die Identität des aufrufenden Accounts zu authentifizieren, bevor eine Funktion ausgeführt wird.
assert()
: assert()
wird verwendet, um interne Fehler zu erkennen und Verletzungen von „Invarianten“ in Ihrem Code zu überprüfen. Eine Invariante ist eine logische Behauptung über den Zustand eines Vertrags, die für alle Funktionsausführungen gelten soll. Ein Beispiel für eine Invariante ist das maximale Gesamtangebot oder der maximale Saldo eines Token-Vertrags. Die Verwendung von assert()
stellt sicher, dass Ihr Vertrag niemals einen verwundbaren Zustand erreicht, und falls doch, werden alle Änderungen an den Zustandsvariablen zurückgesetzt.
revert()
: revert()
kann in einer if-else-Anweisung verwendet werden, die eine Ausnahme auslöst, wenn die erforderliche Bedingung nicht erfüllt ist. Der folgende Mustervertrag verwendet revert()
, um die Ausführung von Funktionen zu überwachen:
1pragma solidity ^0.8.4;23contract VendingMachine {4 address owner;5 error Unauthorized();6 function buy(uint amount) public payable {7 if (amount > msg.value / 2 ether)8 revert("Not enough Ether provided.");9 // Perform the purchase.10 }11 function withdraw() public {12 if (msg.sender != owner)13 revert Unauthorized();1415 payable(msg.sender).transfer(address(this).balance);16 }17}Alles anzeigen
3. Testen Sie Smart Contracts und überprüfen Sie die Richtigkeit des Codes
Die Unveränderlichkeit des Codes, der auf der Ethereum Virtual Machine läuft, bedeutet, dass Smart Contracts ein höheres Maß an Qualitätsbewertung während der Entwicklungsphase erfordern. Wenn Sie Ihren Vertrag ausgiebig testen und auf unerwartete Ergebnisse achten, verbessern Sie die Sicherheit erheblich und schützen Ihre Nutzer auf lange Sicht.
Die übliche Methode besteht darin, kleine Unit-Tests mit Scheindaten zu schreiben, die der Vertrag von den Nutzern erhalten würde. Unit-Testing ist gut, um die Funktionalität bestimmter Funktionen zu testen und sicherzustellen, dass ein Smart Contract wie erwartet funktioniert.
Leider sind Unit-Tests für die Verbesserung der Sicherheit von Smart Contracts nur wenig effektiv, wenn sie nur isoliert angewendet werden. Ein Unit-Test kann beweisen, dass eine Funktion bei Mock-Daten korrekt ausgeführt wird, Unit-Tests sind jedoch nur so effektiv wie die Tests, die verfasst werden. Das macht es schwierig, unentdeckte Sonderfälle und Schwachstellen zu erkennen, die die Sicherheit Ihres Smart Contracts gefährden könnten.
Ein besserer Ansatz besteht darin, Unit-Tests mit eigenschaftsbasierten Tests zu kombinieren, die mit statischer und dynamischer Analyse durchgeführt werden. Die statische Analyse stützt sich auf Low-Level-Darstellungen, wie Kontrollflussdiagramme(opens in a new tab) und abstrakte Syntaxstrukturen(opens in a new tab), um die erreichbaren Programmzustände und Ausführungspfade zu analysieren. Bei dynamischen Analysetechniken wie Fuzzing wird Vertragscode mit zufälligen Eingabewerten ausgeführt, um Operationen zu erkennen, die gegen Sicherheitseigenschaften verstoßen.
Die formale Verifizierung ist eine weitere Technik zur Überprüfung der Sicherheitseigenschaften von Smart Contracts. Im Gegensatz zu regulären Tests kann die formale Verifizierung schlüssig beweisen, dass ein Smart Contract keine Fehler enthält. Dies wird erreicht, indem eine formale Spezifikation erstellt wird, die die gewünschten Sicherheitseigenschaften festhält, um dann zu gewährleisten, dass ein Formmodell des Vertrags mit dieser Spezifikation übereinstimmt.
4. Bitten Sie um eine unabhängige Überprüfung Ihres Codes
Nachdem Sie Ihren Vertrag getestet haben, sollten Sie andere bitten, den Quellcode auf Sicherheitsprobleme zu prüfen. Beim Testen werden nicht alle Schwachstellen in einem Smart Contract aufgedeckt, eine unabhängige Überprüfung erhöht jedoch die Wahrscheinlichkeit, dass Schwachstellen entdeckt werden.
Audits (Prüfungen)
Die Beauftragung eines Smart Contract-Audits ist eine Möglichkeit zur Durchführung einer unabhängigen Code-Überprüfung. Prüfer spielen eine wichtige Rolle, wenn es darum geht sicherzustellen, dass Smart Contracts sicher und frei von Qualitätsmängeln und Planungsfehlern sind.
Dennoch sollten Sie Audits nicht als Wunderwaffe betrachten. Smart Contract-Audits können nicht jeden Fehler aufspüren und sind hauptsächlich dazu gedacht, eine zusätzliche Runde von Überprüfungen durchzuführen, die dazu beitragen können, Probleme zu entdecken, die von den Entwicklern während der anfänglichen Entwicklung und Tests übersehen wurden. Sie sollten auch die Best Practices für die Zusammenarbeit mit Prüfern(opens in a new tab) befolgen, z. B. den Code ordnungsgemäß dokumentieren und Inline-Kommentare hinzufügen, um den Nutzen eines Smart Contract-Audits zu maximieren.
Aufdecken von Fehlern
Die Einrichtung eines Prämienprogramms für das Aufdecken von Fehlern (Bug Bounty Program) ist ein weiterer Ansatz zur Durchführung externer Codeüberprüfungen. Ein Bug Bounty ist eine finanzielle Belohnung für Personen (in der Regel Whitehat-Hacker), die Schwachstellen in einer Applikation entdecken.
Wenn sie richtig eingesetzt werden, geben Bug Bounties den Mitgliedern der Hacker-Community einen Anreiz, Ihren Code auf kritische Fehler zu untersuchen. Ein reales Beispiel ist der „Infinite Money Bug“, der es einem Angreifer ermöglicht hätte, eine unbegrenzte Menge an Ether auf Optimism(opens in a new tab), einem Layer 2-Protokoll, das auf Ethereum läuft, zu erzeugen. Glücklicherweise entdeckte ein Whitehat-Hacker den Fehler(opens in a new tab) und meldete ihn dem Team, und erhielt dafür eine hohe Belohnung(opens in a new tab).
Eine sinnvolle Strategie besteht darin, die Auszahlung eines Bug-Bounty-Programms im Verhältnis zur Höhe der auf dem Spiel stehenden Mittel festzulegen. Dieser als „Skalierung zum Aufdecken von Fehlern(opens in a new tab)“ bezeichnete Ansatz bietet finanzielle Anreize für Einzelpersonen, Schwachstellen verantwortungsbewusst offenzulegen, anstatt sie auszunutzen.
5. Befolgen Sie bei der Entwicklung von Smart Contracts die bewährten Methoden
Die Verfügbarkeit von Audits und Bug Bounties entbindet Sie nicht von Ihrer Verantwortung, qualitativ hochwertigen Code zu schreiben. Die Sicherheit von Smart Contracts beginnt mit der Einhaltung geeigneter Planungs- und Entwicklungsprozesse:
Speichern Sie den gesamten Code in einem Versionskontrollsystem, z. B. Git
Nehmen Sie alle Codeänderungen über Pull Requests vor
Stellen Sie sicher, dass Pull-Requests mindestens einen unabhängigen Reviewer haben. Wenn Sie alleine an einem Projekt arbeiten, sollten Sie überlegen, ob Sie nicht andere Entwickler finden und mit diesen Code-Reviews austauschen
Verwendung einer Entwicklungsumgebung zum Testen, Kompilieren und Bereitstellen von Smart Contracts
Überprüfen Sie Ihren Code mit grundlegenden Code-Analysetools wie Mythril und Slither. Idealerweise sollten Sie dies tun, noch bevor eine Pull-Anfrage eingebunden wird, und die Unterschiede in der Ergebnisausgabe vergleichen
Stellen Sie sicher, dass Ihr Code ohne Fehler kompiliert wird und der Solidity-Compiler keine Warnungen ausgibt
Dokumentieren Sie Ihren Code ordnungsgemäß (unter Verwendung von NatSpec(opens in a new tab)) und beschreiben Sie Einzelheiten der Vertragsarchitektur in leicht verständlicher Sprache. Dies erleichtert es anderen, Ihren Code zu überprüfen und zu kontrollieren.
6. Umsetzung solider Pläne für die Notfallwiederherstellung
Die Entwicklung sicherer Zugriffskontrollen, die Implementierung von Funktionsmodifikatoren und andere Vorschläge können die Sicherheit von Smart Contracts verbessern, jedoch können sie die Möglichkeit böswilliger Angriffe nicht ausschließen. Der Aufbau sicherer Smart Contracts erfordert eine „Vorbereitung auf Fehler“ und einen Notfallplan, um wirksam auf Angriffe reagieren zu können. Ein angemessener Notfallwiederherstellungsplan umfasst einige oder alle der folgenden Komponenten:
Aktualisierungen von Verträgen
Obwohl Ethereum Smart Contracts standardmäßig unveränderlich sind, ist es möglich, durch die Verwendung von Upgrade-Mustern einen gewissen Grad an Veränderbarkeit zu erreichen. Die Aktualisierung von Verträgen ist dann erforderlich, wenn ein kritischer Fehler Ihren alten Vertrag unbrauchbar macht und die Einführung einer neuen Logik die sinnvollste Option darstellt.
Die Mechanismen zur Aktualisierung von Verträgen funktionieren unterschiedlich, wobei jedoch das „Proxy-Muster“ einer der beliebtesten Ansätze für die Aktualisierung von Smart Contracts ist. Proxy-Muster teilen den Zustand und die Logik einer Anwendung zwischen zwei Verträgen auf. Der erste Vertrag (ein so genannter „Proxy-Vertrag“) speichert Zustandsvariablen (z. B. Benutzerguthaben), während der zweite Vertrag (ein so genannter „Logik-Vertrag“) den Code für die Ausführung von Vertragsfunktionen enthält.
Konten interagieren mit dem Proxy-Vertrag, der alle Funktionsaufrufe über den delegatecall()
(opens in a new tab) ein Low-Level-Aufruf, an den Logik-Vertrag weiterleitet. Im Gegensatz zu einem normalen Aufruf stellt delegatecall()
sicher, dass der Code, welcher unter der Adresse des logischen Vertrags läuft, im Kontext des aufrufenden Vertrags ausgeführt wird. Das bedeutet, dass der Logikvertrag immer in den Speicher des Proxys schreibt (anstatt in seinen eigenen Speicher) und die ursprünglichen Werte von msg.sender
und msg.value
erhalten bleiben.
Die Übertragung von Aufrufen an den Logikvertrag erfordert die Speicherung seiner Adresse im Speicher des Proxy-Vertrags. Um die Logik des Vertrags zu aktualisieren, muss daher nur ein anderer Logikvertrag eingesetzt und die neue Adresse im Proxy-Vertrag gespeichert werden. Da nachfolgende Aufrufe des Proxy-Vertrags automatisch an den neuen Logik-Vertrag weitergeleitet werden, hätten Sie den Vertrag „aktualisiert“, ohne den Code tatsächlich zu ändern.
Mehr zum Thema Aktualisieren von Verträgen.
Notausschalter
Wie bereits erwähnt, können umfangreiche Prüfungen und Tests unmöglich alle Fehler in einem Smart Contract aufdecken. Wenn eine Schwachstelle in Ihrem Code nach der Veröffentlichung auftritt, ist es unmöglich, sie zu beheben, da Sie den Code, der unter der Vertragsadresse läuft, nicht ändern können. Außerdem kann die Implementierung von Upgrade-Mechanismen (z. B. Proxy-Muster) einige Zeit in Anspruch nehmen (sie erfordern oft die Zustimmung verschiedener Parteien), was den Angreifern nur mehr Zeit gibt, um mehr Schaden anzurichten.
Die einzige Möglichkeit besteht darin, eine „Not-Aus“-Funktion zu implementieren, die Aufrufe anfälliger Funktionen in einem Vertrag blockiert. Notausschalter bestehen in der Regel aus den folgenden Komponenten:
Eine globale Boolesche Variable, die angibt, ob sich der Smart Contract in einem gestoppten Zustand befindet oder nicht. Diese Variable wird bei der Einrichtung des Vertrags auf
false
gesetzt, schaltet aber auftrue
um, sobald der Vertrag gestoppt wird.Funktionen, die bei ihrer Ausführung auf die boolesche Variable verweisen. Auf diese Funktionen kann zugegriffen werden, wenn der Smart Contract in Betrieb ist, und sie werden unzugänglich, wenn die Notausfunktion ausgelöst wird.
Eine Person, die Zugriff auf die Notausfunktion hat, die die Boolesche Variable auf
true
schaltet. Um böswillige Aktionen zu verhindern, kann der Aufruf dieser Funktion auf eine vertrauenswürdige Adresse (z. B. den Vertragsinhaber) beschränkt werden.
Sobald der Vertrag den Notausschalter aktiviert, sind bestimmte Funktionen nicht mehr aufrufbar. Dies wird erreicht, indem die ausgewählten Funktionen in einen Modifikator verpackt werden, der auf die globale Variable verweist. Im Folgenden wird ein Beispiel(opens in a new tab) für die Umsetzung dieses Konzepts in einem Vertrag beschrieben:
1// This code has not been professionally audited and makes no promises about safety or correctness. Use at your own risk.23contract EmergencyStop {45 bool isStopped = false;67 modifier stoppedInEmergency {8 require(!isStopped);9 _;10 }1112 modifier onlyWhenStopped {13 require(isStopped);14 _;15 }1617 modifier onlyAuthorized {18 // Check for authorization of msg.sender here19 _;20 }2122 function stopContract() public onlyAuthorized {23 isStopped = true;24 }2526 function resumeContract() public onlyAuthorized {27 isStopped = false;28 }2930 function deposit() public payable stoppedInEmergency {31 // Deposit logic happening here32 }3334 function emergencyWithdraw() public onlyWhenStopped {35 // Emergency withdraw happening here36 }37}Alles anzeigenKopieren
Dieses Beispiel zeigt die grundlegenden Merkmale von Notstopps:
isStopped
ist ein Boolescher Wert, der zu Beginnfalse
ergibt undtrue
, wenn der Vertrag in den Notfallmodus wechselt.Die Funktionsmodifikatoren
onlyWhenStopped
undstoppedInEmergency
überprüfen die VariableisStopped
.stoppedInEmergency
wird verwendet, um Funktionen zu steuern, die nicht zugänglich sein sollten, wenn der Vertrag gefährdet ist (z. B.deposit()
). Aufrufe dieser Funktionen werden einfach zurückgewiesen.
onlyWhenStopped
wird für Funktionen verwendet, die in einem Notfall aufrufbar sein sollten (z. B. emergencyWithdraw()
). Diese Funktionen können zur Lösung des Problems beitragen, weshalb sie nicht in der Liste der „eingeschränkten Funktionen“ aufgeführt sind.
Die Verwendung einer Notstopp-Funktion ist eine wirksame Notlösung für den Umgang mit schwerwiegenden Schwachstellen in Ihrem Smart Contract. Allerdings müssen die Nutzer darauf vertrauen können, dass die Entwickler sie nicht aus eigennützigen Gründen aktivieren. Zu diesem Zweck kann die Kontrolle über den Notstopp dezentralisiert werden, indem er entweder einem On-Chain-Abstimmungsmechanismus, einer Zeitsperre oder der Genehmigung durch eine Multisig-Wallet unterworfen wird.
Überwachung von Ereignissen
Ereignisse(opens in a new tab) ermöglichen es Ihnen, Aufrufe von Smart Contract-Funktionen zu verfolgen und Änderungen an Zustandsvariablen zu überwachen. Ideal ist es, wenn Sie Ihren Smart Contract so programmieren, dass er immer dann ein Ereignis auslöst, wenn eine Partei eine sicherheitskritische Aktion durchführt (z. B. das Abheben von Guthaben).
Die Protokollierung von Ereignissen und deren Überwachung off-chain bietet Einblicke in Vertragsvorgänge und hilft, böswillige Handlungen schneller zu entdecken. Das bedeutet, dass Ihr Team schneller auf Hacks reagieren und Maßnahmen ergreifen kann, um die Auswirkungen auf die Benutzer zu minimieren, z. B. das Anhalten von Funktionen oder die Durchführung eines Upgrades.
Sie können sich auch für ein handelsübliches Überwachungsprogramm entscheiden, das automatisch Warnmeldungen weiterleitet, sobald jemand mit Ihren Verträgen interagiert. Mit diesen Tools können Sie benutzerdefinierte Warnmeldungen erstellen, die auf verschiedenen Auslösern basieren, z. B. dem Transaktionsvolumen, der Häufigkeit von Funktionsaufrufen oder den spezifischen Funktionen. Sie könnten zum Beispiel eine Warnung programmieren, die eingeht, wenn der in einer einzigen Transaktion abgehobene Betrag einen bestimmten Schwellenwert überschreitet.
7. Sichere Governance-Systeme (Verwaltungssysteme) entwerfen
Vielleicht möchten Sie Ihre Anwendung dezentralisieren, indem Sie die Kontrolle über die wichtigsten Smart Contracts an Community-Mitglieder übergeben. In diesem Fall wird das Smart Contract-System ein Governance-Modul enthalten – einen Mechanismus, der es den Community-Mitgliedern ermöglicht, administrative Maßnahmen über ein On-Chain-Governance-System zu genehmigen. So können die Token-Inhaber beispielsweise über einen Vorschlag abstimmen, einen Proxy-Vertrag auf eine neue Implementierung zu aktualisieren.
Eine dezentrale Verwaltung kann von Vorteil sein, insbesondere weil sie die Interessen von Entwicklern und Endnutzern in Einklang bringt. Dennoch können die Mechanismen zur Steuerung von Smart Contracts bei falscher Umsetzung neue Risiken mit sich bringen. Ein plausibles Szenario ist, dass ein Angreifer durch die Aufnahme eines Flash-Darlehens enorme Stimmkraft (gemessen an der Anzahl der gehaltenen Token) erlangt und einen böswilligen Vorschlag durchsetzt.
Eine Möglichkeit zur Vermeidung von Problemen im Zusammenhang mit der On-Chain-Governance besteht darin, eine Zeitsperre zu nutzen(opens in a new tab). Eine Zeitsperre verhindert, dass ein Smart Contract bestimmte Aktionen ausführt, bis eine bestimmte Zeitspanne verstrichen ist. Andere Strategien bestehen darin, jedem Token ein „Stimmgewicht“ zuzuweisen, das sich danach richtet, wie lange er gesperrt war, oder die Stimmkraft einer Adresse in einem historischen Zeitraum (z. B. 2-3 Blöcke in der Vergangenheit) anstelle des aktuellen Blocks zu messen. Beide Methoden verringern die Möglichkeit, schnell Stimmrechte anzuhäufen, um On-Chain-Abstimmungen zu beeinflussen.
Mehr über die Planung sicherer Governance-Systeme(opens in a new tab) und verschiedene Abstimmungsmechanismen in DAOs(opens in a new tab).
8. Reduzierung der Komplexität des Codes auf ein Minimum
Traditionelle Softwareentwickler sind mit dem KISS-Prinzip („Keep it simple, stupid“) vertraut, das davon abrät, unnötige Komplexität in das Softwaredesign einzubringen. Dies entspricht der seit langem vertretenen Auffassung, dass „komplexe Systeme auf komplexe Weise versagen“ und anfälliger für kostspielige Fehler sind.
Beim Schreiben von Smart Contracts ist es besonders wichtig, die Inhalte einfach zu halten, da Smart Contracts potenziell große Wertbeträge kontrollieren. Ein Tipp zur Vereinfachung beim Schreiben von intelligenten Verträgen ist die Wiederverwendung bestehender Bibliotheken, wie OpenZeppelin Contracts(opens in a new tab), wo immer möglich. Da diese Bibliotheken von den Entwicklern ausgiebig geprüft und getestet wurden, verringert sich durch ihre Verwendung die Wahrscheinlichkeit, dass durch das Schreiben neuer Funktionen von Grund auf Fehler eingeführt werden.
Ein weiterer allgemeiner Ratschlag lautet, kleine Funktionen zu schreiben und Verträge modulartig zu halten, indem die Logik auf mehrere Verträge aufgeteilt wird. Das Schreiben von einfacherem Code verringert nicht nur die Angriffsfläche in einem Smart Contract, sondern macht es auch einfacher, Rückschlüsse auf die Korrektheit des Gesamtsystems zu ziehen und mögliche Planungsfehler frühzeitig zu erkennen.
9. Schutz vor häufigen Schwachstellen in Smart Contracts
Wiederholungsangriffe
Die EVM erlaubt keine Nebenläufigkeit, was bedeutet, dass zwei Verträge, die an einem Nachrichtenaufruf beteiligt sind, nicht gleichzeitig ausgeführt werden können. Ein externer Aufruf unterbricht die Ausführung und den Speicher des aufrufenden Vertrags, bis der Aufruf erwidert wird, woraufhin die Ausführung normal fortgesetzt wird. Dieser Vorgang kann formal als Übertragung des Kontrollflusses(opens in a new tab) auf einen anderen Vertrag beschrieben werden.
Die Übertragung des Kontrollflusses an nicht vertrauenswürdige Verträge ist zwar meist harmlos, kann aber Probleme verursachen, wie z. B. Wiederholungsangriffe. Ein Wiederholungsangriff liegt vor, wenn ein böswilliger Vertrag in einen gefährdeten Vertrag eingreift, bevor der ursprüngliche Funktionsaufruf abgeschlossen ist. Diese Art des Angriffs lässt sich am besten anhand eines Beispiels erklären.
Nehmen wir einen einfachen Smart Contract („Opfer“), der es jedem erlaubt, Ether einzuzahlen und abzuheben:
1// This contract is vulnerable. Do not use in production23contract Victim {4 mapping (address => uint256) public balances;56 function deposit() external payable {7 balances[msg.sender] += msg.value;8 }910 function withdraw() external {11 uint256 amount = balances[msg.sender];12 (bool success, ) = msg.sender.call.value(amount)("");13 require(success);14 balances[msg.sender] = 0;15 }16}Alles anzeigenKopieren
Dieser Vertrag stellt eine withdraw()
-Funktion zur Verfügung, die es den Nutzern ermöglicht, zuvor in den Vertrag eingezahlte ETH abzuheben. Bei der Bearbeitung einer Abhebung führt der Vertrag die folgenden Vorgänge durch:
- Überprüft das ETH-Guthaben des Nutzers
- Sendet Guthaben an die anrufende Adresse
- Setzt das Guthaben auf 0 zurück und verhindert so weitere Abhebungen durch den Nutzer
Die Funktion withdraw()
im Victim
-Vertrag folgt einem „Prüfungen-Auswirkungen-Interaktionen“-Modell. Sie prüft, ob die für die Ausführung notwendigen Bedingungen erfüllt sind (d. h. der Nutzer hat ein positives ETH-Guthaben) und führt die Interaktion durch, indem sie ETH an die Adresse des Aufrufers sendet, bevor sie die Auswirkungen der Transaktion anwendet (d. h. das Guthaben des Nutzers reduziert).
Wenn withdraw()
von einem extern betriebenen Konto (EOA) aufgerufen wird, wird die Funktion wie erwartet ausgeführt: msg.sender.call.value()
sendet ETH an den Aufrufer. Wenn msg.sender
jedoch ein Smart Contract-Konto ist, welches withdraw()
aufruft, wird das Senden von Geldmitteln mit msg.sender.call.value()
auch die Ausführung von Code auslösen, der unter dieser Adresse gespeichert ist.
Stellen Sie sich vor, dass dies der Code ist, der an der Vertragsadresse veröffentlicht wird:
1 contract Attacker {2 function beginAttack() external payable {3 Victim(victim_address).deposit.value(1 ether)();4 Victim(victim_address).withdraw();5 }67 function() external payable {8 if (gasleft() > 40000) {9 Victim(victim_address).withdraw();10 }11 }12}Alles anzeigenKopieren
Dieser Vertrag ist darauf ausgelegt, drei Dinge zu tun:
- Eine Einzahlung von einem anderen Konto akzeptieren (wahrscheinlich von der EOA des Angreifers)
- 1 ETH in den Vertrag des Opfers einzahlen
- Die im Smart Contract gespeicherten 1 ETH abheben
Hier ist nichts verkehrt, außer dass Attacker
eine weitere Funktion hat, die withdraw()
im Victim
erneut aufruft, wenn das Gas, das vom eingehenden msg.sender.call.value
übrig bleibt, mehr als 40.000 beträgt. Dies gibt Attacker
die Möglichkeit, Victim
erneut zu betreten und mehr Geld abzuheben, bevor der erste Aufruf von withdraw
abgeschlossen ist. Der Kreislauf sieht folgendermaßen aus:
1- Attacker's EOA calls `Attacker.beginAttack()` with 1 ETH2- `Attacker.beginAttack()` deposits 1 ETH into `Victim`3- `Attacker` calls `withdraw() in `Victim`4- `Victim` checks `Attacker`’s balance (1 ETH)5- `Victim` sends 1 ETH to `Attacker` (which triggers the default function)6- `Attacker` calls `Victim.withdraw()` again (note that `Victim` hasn’t reduced `Attacker`’s balance from the first withdrawal)7- `Victim` checks `Attacker`’s balance (which is still 1 ETH because it hasn’t applied the effects of the first call)8- `Victim` sends 1 ETH to `Attacker` (which triggers the default function and allows `Attacker` to reenter the `withdraw` function)9- The process repeats until `Attacker` runs out of gas, at which point `msg.sender.call.value` returns without triggering additional withdrawals10- `Victim` finally applies the results of the first transaction (and subsequent ones) to its state, so `Attacker`’s balance is set to 0Alles anzeigenKopieren
Da das Guthaben des Aufrufers nicht auf 0 gesetzt wird, bevor die Funktion ausgeführt wurde, können nachfolgende Aufrufe erfolgreich sein und dem Aufrufer ermöglichen, sein Guthaben mehrmals abzuheben. Diese Art von Angriff kann genutzt werden, um einem Smart Contract das Kapital zu entziehen, wie es beim 2016 DAO-Hack(opens in a new tab) geschehen ist. Wiederholungsangriffe sind auch heute noch ein kritisches Thema für Smart Contracts, wie öffentliche Auflistungen von Reentrancy-Exploits(opens in a new tab) zeigen.
So verhindert man Wiederholungsangriffe
Ein Ansatz für den Umgang mit Wiederholungsangriffen ist das Prüfungen-Auswirkungen-Interaktionen-Modell(opens in a new tab). Dieses Modell ordnet die Ausführung von Funktionen so an, dass Code, der vor der Ausführung notwendige Überprüfungen durchführt, zuerst kommt, gefolgt von Code, der den Vertragsstatus manipuliert, und Code, der mit anderen Verträgen oder EOAs interagiert, als letztes erfolgt.
Das „Prüfungen-Auswirkungen-Interaktionen“-Modell wird in einer überarbeiteten Version des Victim
-Vertrags verwendet, wie unten gezeigt:
1contract NoLongerAVictim {2 function withdraw() external {3 uint256 amount = balances[msg.sender];4 balances[msg.sender] = 0;5 (bool success, ) = msg.sender.call.value(amount)("");6 require(success);7 }8}Kopieren
Dieser Vertrag führt eine Überprüfung des Guthabens des Nutzers durch, wendet die Auswirkungen der withdraw()
-Funktion an (indem das Guthaben des Nutzers auf 0 zurückgesetzt wird) und fährt mit der Interaktion (Senden von ETH an die Adresse des Nutzers) fort. Auf diese Weise wird sichergestellt, dass der Vertrag seinen Speicher vor dem externen Aufruf aktualisiert und die Bedingung der Wiederverknüpfung, die den ersten Angriff ermöglichte, beseitigt. Der Attacker
-Vertrag könnte immer noch zurück in NoLongerAVictim
aufrufen, aber da balances[msg.sender]
auf 0 gesetzt wurde, werden zusätzliche Abhebungen einen Fehler auslösen.
Eine andere Möglichkeit ist die Verwendung einer gegenseitigen Ausschlusssperre (allgemein als „Mutex“ bezeichnet), die einen Teil des Vertragsstatus sperrt, bis ein Funktionsaufruf abgeschlossen ist. Dies wird durch eine Boolesche Variable realisiert, die vor der Ausführung der Funktion auf true
gesetzt wird und nach Beendigung des Aufrufs wieder auf false
zurückkehrt. Wie im folgenden Beispiel zu sehen ist, schützt die Verwendung einer „Mutex“ eine Funktion vor wiederholten Aufrufen, während der ursprüngliche Aufruf noch in Bearbeitung ist, wodurch Wiederholungsangriffe effektiv verhindert werden.
1pragma solidity ^0.7.0;23contract MutexPattern {4 bool locked = false;5 mapping(address => uint256) public balances;67 modifier noReentrancy() {8 require(!locked, "Blocked from reentrancy.");9 locked = true;10 _;11 locked = false;12 }13 // This function is protected by a mutex, so reentrant calls from within `msg.sender.call` cannot call `withdraw` again.14 // The `return` statement evaluates to `true` but still evaluates the `locked = false` statement in the modifier15 function withdraw(uint _amount) public payable noReentrancy returns(bool) {16 require(balances[msg.sender] >= _amount, "No balance to withdraw.");1718 balances[msg.sender] -= _amount;19 bool (success, ) = msg.sender.call{value: _amount}("");20 require(success);2122 return true;23 }24}Alles anzeigenKopieren
Sie können auch ein Pull-Zahlungssystem(opens in a new tab) verwenden, bei dem die Nutzer Geld von den Smart Contracts abheben müssen, anstelle eines „Push-Zahlungssystems“, das Guthaben an Konten sendet. Dies verhindert die Möglichkeit, unbeabsichtigt Code an unbekannten Adressen auszulösen (und kann auch bestimmte Denial-of-Service-Angriffe verhindern).
Integer-Unterläufe und -Überläufe
Ein Integer-Überlauf tritt auf, wenn das Ergebnis einer arithmetischen Operation außerhalb des zulässigen Wertebereichs liegt, so dass es auf den niedrigsten darstellbaren Wert „überläuft“. Zum Beispiel kann ein uint8
nur Werte bis zu 2^8-1=255 speichern. Arithmetische Operationen, die zu höheren Werten als 255
führen, führen zu einem Überlauf und setzen uint
auf 0
zurück, ähnlich wie der Kilometerzähler eines Autos auf 0 zurückgesetzt wird, wenn er den maximalen Kilometerstand (999999) erreicht hat.
Integer-Unterläufe treten aus ähnlichen Gründen auf: Die Ergebnisse einer arithmetischen Operation liegen unterhalb des zulässigen Bereichs. Angenommen, Sie versuchen, 0
in einem uint8
zu dekrementieren, würde das Ergebnis einfach auf den maximal darstellbaren Wert (255
) übergehen.
Sowohl Integer-Überläufe als auch -Unterläufe können zu unerwarteten Änderungen an den Zustandsvariablen eines Vertrags führen und eine ungeplante Ausführung zur Folge haben. Das folgende Beispiel zeigt, wie ein Angreifer einen arithmetischen Überlauf in einem Smart Contract ausnutzen kann, um eine ungültige Operation durchzuführen:
1pragma solidity ^0.7.6;23// This contract is designed to act as a time vault.4// User can deposit into this contract but cannot withdraw for at least a week.5// User can also extend the wait time beyond the 1 week waiting period.67/*81. Deploy TimeLock92. Deploy Attack with address of TimeLock103. Call Attack.attack sending 1 ether. You will immediately be able to11 withdraw your ether.1213What happened?14Attack caused the TimeLock.lockTime to overflow and was able to withdraw15before the 1 week waiting period.16*/1718contract TimeLock {19 mapping(address => uint) public balances;20 mapping(address => uint) public lockTime;2122 function deposit() external payable {23 balances[msg.sender] += msg.value;24 lockTime[msg.sender] = block.timestamp + 1 weeks;25 }2627 function increaseLockTime(uint _secondsToIncrease) public {28 lockTime[msg.sender] += _secondsToIncrease;29 }3031 function withdraw() public {32 require(balances[msg.sender] > 0, "Insufficient funds");33 require(block.timestamp > lockTime[msg.sender], "Lock time not expired");3435 uint amount = balances[msg.sender];36 balances[msg.sender] = 0;3738 (bool sent, ) = msg.sender.call{value: amount}("");39 require(sent, "Failed to send Ether");40 }41}4243contract Attack {44 TimeLock timeLock;4546 constructor(TimeLock _timeLock) {47 timeLock = TimeLock(_timeLock);48 }4950 fallback() external payable {}5152 function attack() public payable {53 timeLock.deposit{value: msg.value}();54 /*55 if t = current lock time then we need to find x such that56 x + t = 2**256 = 057 so x = -t58 2**256 = type(uint).max + 159 so x = type(uint).max + 1 - t60 */61 timeLock.increaseLockTime(62 type(uint).max + 1 - timeLock.lockTime(address(this))63 );64 timeLock.withdraw();65 }66}Alles anzeigen
Wie man Integer-Unterläufe und -Überläufe verhindert
Ab Version 0.8.0 weist der Solidity-Compiler Code zurück, der zu Integer-Unterläufen und -Überläufen führt. Verträge, die mit einer niedrigeren Compiler-Version kompiliert wurden, sollten jedoch entweder Überprüfungen für Funktionen durchführen, die arithmetische Operationen beinhalten, oder eine Bibliothek (z. B. SafeMath(opens in a new tab)) verwenden, die auf Unterlauf/Überlauf prüft.
Oracle-Manipulation
Oracles beziehen Off-Chain-Informationen und senden sie on-chain, damit Smart Contracts diese nutzen können. Mit Orakeln können Sie Smart Contracts entwerfen, die mit Off-Chain-Systemen wie z. B. Kapitalmärkten interagieren, was ihre Anwendung erheblich erweitert.
Wenn das Orakel jedoch beschädigt ist und falsche Informationen on-chain sendet, werden Smart Contracts auf der Grundlage falscher Informationen ausgeführt, was zu Problemen führen kann. Dies ist die Grundlage des „Orakelproblems“, bei dem es darum geht sicherzustellen, dass die Informationen aus einem Blockchain-Orakel korrekt, aktuell und zeitnah sind.
Ein damit zusammenhängendes Sicherheitsproblem ist die Verwendung eines On-Chain-Orakels, z. B. einer dezentralen Börse, um den Spotpreis für ein Asset zu ermitteln. Leihplattformen in der dezentralen Finanzbranche (DeFi) tun dies oft, um den Wert der Beleihungsobjekte eines Nutzers zu ermitteln, anhand derer er bestimmen kann, wie viel er leihen kann.
Die DEX-Preise sind häufig korrekt, was vor allem darauf zurückzuführen ist, dass Arbitrageure die Gleichheit auf den Märkten wiederherstellen. Sie sind jedoch anfällig für Manipulationen, insbesondere wenn das On-Chain-Orakel die Preise von Assets auf der Grundlage historischer Handelsdaten berechnet (was normalerweise der Fall ist).
So könnte ein Angreifer beispielsweise den Spotpreis eines Assets künstlich in die Höhe treiben, indem er einen Blitzkredit aufnimmt, kurz bevor er mit Ihrem Kreditvertrag interagiert. Die Abfrage der DEX nach dem Preis des Assets würde einen höheren als den normalen Wert ergeben (da die große „Kaufbestellung“ des Angreifers die Nachfrage nach dem Asset verzerrt), so dass er mehr Geld leihen kann, als er sollte. Solche „Flash-Darlehensangriffe“ wurden genutzt, um das Vertrauen in Preis-Orakel bei DeFi-Anwendungen auszunutzen, was Protokolle Millionen an verlorenen Guthaben gekostet hat.
So verhindert man Orakelmanipulation
Die Mindestanforderung zur Vermeidung von Orakelmanipulationen ist die Verwendung eines dezentralen Orakelnetzes, das Informationen aus mehreren Quellen abfragt, um einzelne Fehlerquellen zu vermeiden. In den meisten Fällen verfügen dezentrale Orakel über eingebaute kryptoökonomische Anreize, die die Nodes des Orakels dazu bringen, korrekte Informationen zu melden, was sie sicherer macht als zentralisierte Orakel.
Wenn Sie vorhaben, ein On-Chain-Orakel für Asset-Preise abzufragen, sollten Sie ein Orakel verwenden, das einen Mechanismus für zeitgewichtete Durchschnittspreise (TWAP) implementiert. Ein TWAP-Orakel(opens in a new tab) fragt den Preis eines Assets zu zwei verschiedenen Zeitpunkten ab (die Sie ändern können) und berechnet den Spotpreis auf der Grundlage des erhaltenen Durchschnitts. Die Wahl längerer Zeiträume schützt Ihr Protokoll vor Preismanipulationen, da große Aufträge, die erst kürzlich ausgeführt wurden, keinen Einfluss auf die Preise der Assets haben können.
Ressourcen zur Sicherheit von Smart Contracts für Entwickler
Tools für die Analyse von Smart Contracts und die Überprüfung der Korrektheit des Codes
Testing-Tools und -Bibliotheken - Sammlung von branchenüblichen Tools und Bibliotheken zur Durchführung von Unit-Tests, statischer Analyse und dynamischer Analyse von Smart Contracts.
Formale Verifizierungstools - Tools zur Verifizierung der funktionalen Korrektheit in Smart Contracts und zur Überprüfung von Invarianten.
Smart Contract-Auditing-Dienste - Liste von Organisationen, die Smart Contract-Auditing-Dienste für Ethereum-Entwicklungsprojekte anbieten.
Plattformen zum Aufdecken von Fehlern - Plattformen zur Koordinierung des Aufdeckens von Fehlern und zur Belohnung der verantwortungsvollen Offenlegung kritischer Schwachstellen in Smart Contracts.
Fork Checker(opens in a new tab) - Ein kostenloses Tool zur Überprüfung aller verfügbaren Informationen bezüglich Fork-Verträgen.
ABI Encoder(opens in a new tab) - Ein frei nutzbarer Online-Service zum Kodieren Ihrer Solidity-Vertragsfunktionen und Konstruktor-Argumente.
Tools für die Überwachung von Smart Contracts
OpenZeppelin Defender Sentinels(opens in a new tab) - _Ein Tool zur automatischen Überwachung und Reaktion auf Ereignisse, Funktionen und Transaktionsparameter in Ihren Smart Contracts._v
Tenderly Real-Time Alerting(opens in a new tab) - Ein Tool, um Echtzeit-Benachrichtigungen zu erhalten, wenn ungewöhnliche oder unerwartete Ereignisse auf Ihren Smart Contracts oder Wallets auftreten.
Tools für die sichere Verwaltung von Smart Contracts
OpenZeppelin Defender Admin(opens in a new tab) - Schnittstelle für die Verwaltung von Smart Contracts, einschließlich Zugriffskontrollen, Upgrades und Pausieren.
Safe(opens in a new tab) - Smart Contract-Wallet auf Ethereum, die eine Mindestanzahl von Personen benötigt, um eine Transaktion zu genehmigen, bevor sie stattfinden kann (M-of-N).
OpenZeppelin Contracts(opens in a new tab) - Vertragsbibliotheken für die Implementierung von Verwaltungsfunktionen, einschließlich Vertragseigentum, Upgrades, Zugriffskontrollen, Governance, Pausierbarkeit und mehr.
Dienstleistungen zur Prüfung von Smart Contracts
ConsenSys Diligence(opens in a new tab) - Audit-Dienst für Smart Contracts, der Projekten im gesamten Blockchain-Ökosystem dabei hilft sicherzustellen, dass ihre Protokolle zur Veröffentlichung bereit sind und dem Schutz der Nutzer dienen.
CertiK(opens in a new tab) - Blockchain-Sicherheitsunternehmen, das Pionierarbeit beim Einsatz modernster formaler Verifizierungstechnologie für Smart Contracts und Blockchain-Netzwerke leistet.
Trail of Bits(opens in a new tab) - Cybersicherheitsunternehmen, das Sicherheitsforschung mit der Mentalität von Angreifern kombiniert, um Risiken zu verringern und Code zu stärken.
PeckShield(opens in a new tab) - Blockchain-Sicherheitsunternehmen, das Produkte und Dienstleistungen für die Sicherheit, den Datenschutz und die Nutzbarkeit des gesamten Blockchain-Ökosystems bietet.
QuantStamp(opens in a new tab) - Audit-Dienst, der die allgemeine Einführung der Blockchain-Technologie durch Sicherheits- und Risikobewertungsdienste erleichtert.
OpenZeppelin(opens in a new tab) - Sicherheitsunternehmen für Smart Contracts, das Sicherheitsprüfungen für verteilte Systeme durchführt.
Runtime Verification(opens in a new tab) - Sicherheitsunternehmen, spezialisiert auf die formale Modellierung und Verifizierung von Smart Contracts.
Hacken(opens in a new tab) - Web3 Cybersicherheitsauditor mit 360-Grad-Ansatz für die Sicherheit der Blockchain.
(opens in a new tab) - Solidity und Cairo Audit-Dienste sorgen für Datenintegrität der Smart Contracts und Sicherheit der Nutzer im Ethereum- und Starknet-Ökosystem.
HashEx(opens in a new tab) - HashEx konzentriert sich auf die Prüfung von Blockchain und Smart Contracts, um die Sicherheit von Kryptowährungen zu gewährleisten, und bietet Dienstleistungen wie die Entwicklung von Smart Contracts, Penetrationstests und Blockchain-Beratung.
Code4rena(opens in a new tab) - Eine wettbewerbsorientierte Plattform, die Anreize für Sicherheitsexperten zum Aufspüren von Schwachstellen bietet, um das Web3 sicherer zu machen.
Plattformen zum Aufdecken von Fehlern
Immunefi(opens in a new tab) - Bug-Bounty-Plattform für Smart Contracts und DeFi-Projekte, auf der Sicherheitsforscher Code überprüfen, Schwachstellen aufdecken, bezahlt werden und Krypto sicherer machen.
HackerOne(opens in a new tab) - Schwachstellen-Koordinations- und Bug-Bounty-Plattform, die Unternehmen mit Penetrationstestern und Cybersecurity-Forschern zusammenbringt.
HackenProof(opens in a new tab) - Experten-Bug-Bounty-Plattform für Krypto-Projekte (DeFi, Smart Contracts, Wallets, CEX und mehr), auf der Sicherheitsexperten Triage-Dienste anbieten und Forscher für relevante, verifizierte Fehlerberichte bezahlt werden.
Veröffentlichungen bekannter Schwachstellen und Exploits von Smart Contracts
ConsenSys: Smart Contract Known Attacks(opens in a new tab) - Einsteigerfreundliche Erklärung der wichtigsten Vertragsschwachstellen, mit Beispielcode für die meisten Fälle.
SWC Registry(opens in a new tab) - Ausgewählte Liste von Common Weakness Enumeration (CWE) Elementen, die auf Ethereum Smart Contracts zutreffen.
Rekt(opens in a new tab) - Regelmäßig aktualisierte Veröffentlichung von hochkarätigen Krypto-Hacks und Exploits, zusammen mit detaillierten Post-Mortem-Berichten.
Herausforderungen beim Erlernen der Sicherheit von Smart Contracts
Awesome BlockSec CTF(opens in a new tab) - Ausgewählte Liste von Blockchain Security War Games, Challenges und Capture The Flag(opens in a new tab) Wettbewerben und Lösungsbeschreibungen.
Damn Vulnerable DeFi(opens in a new tab) - War Game zum Erlernen der offensiven Sicherheit von DeFi Smart Contracts und zum Aufbau von Fähigkeiten in der Fehlersuche und Sicherheitsprüfung.
Ethernaut(opens in a new tab) - Web3/Solidity-basiertes War Game, bei dem jedes Level ein Smart Contract ist, der „gehackt“ werden muss.
Bewährte Praktiken für die Sicherung von Smart Contracts
ConsenSys: Ethereum Smart Contract Security Best Practices(opens in a new tab) - Umfassende Liste von Richtlinien zur Sicherung von Ethereum Smart Contracts.
Nascent: Simple Security Toolkit(opens in a new tab) - Sammlung praktischer, sicherheitsorientierter Anleitungen und Checklisten für die Entwicklung von Smart Contracts.
Solidity Patterns(opens in a new tab) - Nützliche Zusammenstellung von sicheren Modellen und Best Practices für die Smart Contract-Programmiersprache Solidity.
Solidity Docs: Security Considerations(opens in a new tab) - Richtlinien zum Schreiben sicherer Smart Contracts mit Solidity.
Smart Contract Security Verification Standard(opens in a new tab) - Vierzehnteilige Checkliste zur Standardisierung der Sicherheit von Smart Contracts für Entwickler, Architekten, Sicherheitsüberprüfer und Anbieter.