Soliditätsoptimierer und Abiencoderv2 -Bug -Ankündigung
Im Rahmen des Ethereum Bug Bounty -Programms erhielten wir einen Bericht über einen Fehler innerhalb des neuen experimentellen ABI -Encoders (als Abiencoderv2 bezeichnet). Bei der Untersuchung wurde festgestellt, dass die Komponente unter einigen verschiedenen Variationen desselben Typs leidet. Der erste Teil dieser Ankündigung erklärt diesen Fehler im Detail. Der neue ABI -Encoder ist immer noch als experimentell markiert, aber wir denken jedoch, dass dies eine herausragende Ankündigung verdient, da er bereits auf dem Mainnet verwendet wird.
Darüber hinaus wurden in den letzten zwei Wochen zwei Fehler mit niedriger Auswirkung im Optimierer identifiziert, von denen eines mit Solidität v0.5.6 fixiert war. Beide wurden mit Version 0.5.5 eingeführt. Weitere Informationen finden Sie im zweiten Teil dieser Ankündigung.
Der 0.5.7 Release Enthält die Korrekturen an allen in diesem Blog -Beitrag erläuterten Fehler.
Alle hier genannten Fehler sollten in Tests, die die entsprechenden Codepfade berühren, leicht sichtbar sein, zumindest wenn sie mit allen Kombinationen mit Null- und ungleich Null -Werten ausgeführt werden.
Credits an das Melonport-Team (Travis Jacobs & Jenna Zenk) und der Melon Council (Nick Munoz-McDonald, Martin Lundfall, Matt Di Ferrante und Adam Kolar), der dies über das Ethereum Bug Bounty-Programm berichtete!
Wer sollte besorgt sein
Wenn Sie Verträge eingesetzt haben, die den experimentellen ABI -Encoder V2 verwenden, sind diese möglicherweise betroffen. Dies bedeutet, dass nur Verträge betroffen sein können, die die folgende Richtlinie im Quellcode verwenden:
pragma experimental ABIEncoderV2;
Darüber hinaus gibt es eine Reihe von Anforderungen für den Auslösen des Fehlers. Weitere Informationen finden Sie weiter unten.
Soweit wir das beurteilen können, gibt es etwa 2500 Verträge auf dem Hauptnetz, die den experimentellen Abiencoderv2 verwenden. Es ist nicht klar, wie viele von ihnen den Fehler enthalten.
So überprüfen Sie, ob Vertrag anfällig ist
Der Fehler manifestiert sich nur, wenn alle folgenden Bedingungen erfüllt sind:
- Speicherdaten mit Arrays oder Strukturen werden direkt an einen externen Funktionsaufruf gesendet ABI.CODE oder zu Ereignisdaten ohne vorherige Zuordnung zu einer lokalen (Speicher-) Variablen und
- Es gibt ein Array, das Elemente mit einer Größe von weniger als 32 Bytes oder einer Struktur enthält, die Elemente enthält, die einen Speicherplatz oder einen Typ -Typ -Typ teilen Bytesnn Kürzer als 32 Bytes.
Darüber hinaus ist Ihr Code in den folgenden Situationen nicht betroffen:
- Wenn alle Ihre Strukturen oder Arrays nur verwenden Uint256 oder INT256 Typen
- Wenn Sie nur Ganzzahltypen verwenden (das kann kürzer sein) und höchstens ein Array gleichzeitig codieren
- Wenn Sie solche Daten nur zurückgeben und sie nicht verwenden ABI.CODEexterne Anrufe oder Ereignisdaten.
Wenn Sie einen Vertrag haben, der diesen Bedingungen entspricht und überprüfen möchten, ob der Vertrag tatsächlich anfällig ist, können Sie uns über uns wenden Security@ethereum.org.
Wie man diese Art von Männern in Zukunft verhindern
Um über Veränderungen konservativ zu sein, stand der experimentelle ABI -Encoder nur, wenn es explizit aktiviert ist, damit die Menschen damit interagieren und sie testen können, ohne zu viel Vertrauen in ihn zu setzen, bevor es als stabil angesehen wird.
Wir geben unser Bestes, um eine hohe Qualität zu gewährleisten, und haben kürzlich begonnen Oss-Fuzz (Wir haben den Compiler zuvor mit Crash-Fuzzer gestrichen, aber das hat den Compiler-Korrektheit nicht getestet.)
Für Entwickler-Fehler im Soliditäts Compiler sind schwer mit Tools wie Schwachstellendetektoren zu erkennen, da Tools, die mit Quellcode oder AST-Repräsentationen arbeiten, keine Mängel erkennen, die nur in den kompilierten Bytecode eingeführt werden.
Der beste Weg, um vor diesen Arten von Männern zu schützen, besteht darin, eine Reihe von End-to-End-Tests für Ihre Verträge (alle Codepfade zu überprüfen) zu haben, da Fehler in einem Compiler sehr wahrscheinlich nicht “still” sind und stattdessen in ungültigen Daten manifestieren.
Mögliche Konsequenzen
Natürlich kann jeder Fehler in Abhängigkeit vom Programmkontrollfluss stark unterschiedliche Konsequenzen haben. Wir gehen jedoch davon aus, dass dies eher zu Fehlfunktionen als zu Ausbeulichkeit führt.
Der Fehler sendet unter bestimmten Umständen unter bestimmten Umständen korrupte Parameter für Methodenaufrufe an andere Verträge.
Zeitleiste
2019-03-16:
- Bericht über Bug Bounty, über Korruption, das beim Lesen von Arrays von Booleschen direkt vom Speicher in ABI -Encoder verursacht wurde.
2019-03-16 bis 2019-03-21:
- Untersuchung der Grundursache, Analyse betroffener Verträge. Eine unerwartet hohe Anzahl von Verträgen, die mit dem experimentellen Encoder zusammengestellt wurden, wurden auf dem Mainnet bereitgestellt, viele ohne verifizierte Quellcode.
- Die Untersuchung von Bug fand mehr Möglichkeiten, den Fehler auszulösen, z. B. mit Strukturen. Darüber hinaus wurde in derselben Routine ein Array -Überlauffehler gefunden.
- Eine Handvoll Verträge auf Github wurden überprüft, und es wurde festgestellt, dass keiner betroffen war.
- Es wurde ein Bugfix zum ABI -Encoder gemacht.
2019-03-20:
- Entscheidung, Informationen öffentlich zu machen.
- Argumentation: Es wäre nicht möglich, alle gefährdeten Verträge zu erkennen und alle Autoren rechtzeitig zu erreichen, und es wäre gut, eine weitere Verbreitung verletzlicher Verträge am Mainnet zu verhindern.
2019-03-26:
- Neue Compiler -Veröffentlichung, Version 0.5.7.
- Dieser Beitrag veröffentlichte.
Technische Details
Hintergrund
Der Vertrag ABI ist eine Spezifikation, wie Daten mit Verträgen von außen (einem DAPP) oder bei der Interaktion zwischen Verträgen ausgetauscht werden können. Es unterstützt eine Vielzahl von Datenarten, einschließlich einfacher Werte wie Zahlen, Bytes und Zeichenfolgen sowie komplexeren Datentypen, einschließlich Arrays und Strukturen.
Wenn ein Vertrag Eingabedaten empfängt, muss er entschlüsselt werden (dies wird durch den “ABI -Decoder”) und vor dem Rückgabedaten oder dem Senden von Daten an einen anderen Vertrag erfolgt, muss er ihn codieren (dies wird vom “ABI -Encoder” durchgeführt). Der Solidity Compiler generiert diese beiden Codeteile für jede definierte Funktion in einem Vertrag (und auch für ABI.CODE Und Abi.decode). Im Soliditäts Compiler wird das Subsystem, das den Encoder und Decoder erzeugt, als “ABI -Encoder” bezeichnet.
Mitte 2017 begann das Solidity-Team an einer neuen Implementierung mit dem Namen “ABI Encoder V2” mit dem Ziel, einen flexibleren, sichereren, leistungsfähigeren und prüfbaren Codegenerator zu haben. Dieser experimentelle Codegenerator wird seit Ende 2017 mit der Veröffentlichung von 0.4.19 den Benutzern ausdrücklich aktiviert.
Der Fehler
Der experimentelle ABI-Encoder verarbeitet keine Nichttegerwerte, die kürzer als 32 Bytes ordnungsgemäß sind. Dies gilt für Bytesnn Typen, boolAnwesend Aufreum und andere Typen, wenn sie Teil eines Arrays oder einer Struktur sind und direkt aus der Speicherung codiert werden. Dies bedeutet, dass diese Speicherreferenzen direkt darin verwendet werden müssen ABI.CODE (…)als Argumente in externen Funktionen oder in Ereignisdaten ohne vorherige Zuordnung zu einer lokalen Variablen. Verwendung zurückkehren löst den Fehler nicht aus. Die Typen Bytesnn Und bool führt während zu beschädigten Daten, während Aufreum könnte zu einem Ungültigen führen zurückkehren.
Darüber hinaus werden Arrays mit Elementen, die kürzer als 32 Bytes sind, möglicherweise nicht korrekt behandelt, selbst wenn der Basistyp ein ganzzahliger Typ ist. Die Codierung solcher Arrays in der oben beschriebenen Art und Weise kann zu anderen Daten führen, die überschrieben werden, wenn die Anzahl der codierten Elemente kein Vielfaches der Anzahl der Elemente ist, die zu einem einzigen Steckplatz passen. Wenn nichts dem Array in der Codierung folgt (beachten Sie, dass dynamisch große Arrays immer nach statischgroßen Arrays mit statisch großer Inhalt codiert werden), oder wenn nur ein einzelnes Array codiert ist, werden keine anderen Daten überschrieben.
Nicht mit dem oben erläuterten ABI -Encoder -Problem wurden zwei Fehler im Optimierer gefunden. Beide wurden mit 0,5,5 eingeführt (veröffentlicht am 5. März). Es ist unwahrscheinlich, dass sie im vom Compiler generierten Code auftreten, es sei denn, Inline -Montage wird verwendet.
Diese beiden Fehler wurden durch die jüngste Zugabe von Solidität zu identifiziert Oss-Fuzz – Ein Sicherheits -Toolkit zum Auffinden von Unstimmigkeiten oder Problemen in verschiedenen Projekten. Für die Solidität haben wir mehrere verschiedene Fuzzers eingeschlossen, die verschiedene Aspekte des Compilers testen.
- Der Optimierer dreht Opcode -Sequenzen wie ((x << a) << b)))Wo A Und B sind Konstanten für Kompilierzeiten in (x << (a + b)) ohne Überlauf in der Zugabe ordnungsgemäß.
- Der Optimierer behandelt fälschlicherweise die Byte Opcode Wenn die Konstante 31 als zweites Argument verwendet wird. Dies kann bei der Durchführung des Indexzugriffs auf passieren Bytesnn Typen mit einem Kompilierzeitkonstantenwert (nicht des Index) von 31 oder bei Verwendung des Byte-Opcode in der Inline-Montage.
Dieser Beitrag wurde gemeinsam von @axic, @chriseth, @holiman komponiert

