EVM (Ethereum Virtual Machine)-kompatible Blockchains sind darauf ausgelegt, mit der Smart-Contract-Funktionalität, der Programmiersprache (Solidity) und dem Tooling-Ökosystem der Ethereum-Blockchain kompatibel zu sein. Bei diesem Prozess ist die Implementierung einer EVM-konformen virtuellen Maschine einer der wichtigsten Schritte. Während unserer Forschung stellen wir jedoch fest, dass die Aufrechterhaltung der EVM-Kompatibilität bei verschiedenen Implementierungen nicht einfach ist.
Zur Lösung des Problems entwickelte BlockSec ein internes System, das Bugs und Sicherheitslücken in der EVM-Implementierung systematisch lokalisieren kann. Dieses System hat sich als wirksam erwiesen. Es meldete vier Bugs in der Aurora Engine und vier Bugs in Moonbeam. Alle wurden gemeldet und behoben. Beachten Sie, dass diese Testmethodik letztes Jahr auch zur Lokalisierung zweier kritischer Schwachstellen (CVE-2021–46102, CVE-2022–23066) in der Solana rbpf-Implementierung verwendet wurde.
1. Hintergrund
Heutzutage werden viele verschiedene Blockchains mit Optimierungen für niedrige Gasgebühren, hohen Durchsatz und hervorragende Leistung vorgeschlagen. In diesem Fall werden neue virtuelle Maschinen oder Entwicklungssprachen vorgeschlagen, was die Hürde für die Umstellung für ursprüngliche Solidity-Entwickler erhöht. In diesem Fall werden viele EVM-kompatible Lösungen vorgeschlagen, die es Benutzern ermöglichen, ihre in Solidity entwickelten DApps auf diesen neuen Ketten bereitzustellen. Aurora und Moonbeam sind Vertreter dieser EVM-kompatiblen Lösungen. Die Robustheit, Zuverlässigkeit und Präzision dieser EVM-Implementierungen sind jedoch unbekannt und verdienen unsere Aufmerksamkeit. Zu diesem Zweck nutzen wir die differentielle Fuzzing-Technik und prüfen, ob es Fehler in den Implementierungen gibt.
2. Differentielle Fuzzing
Die grundlegende Idee ist, identische Eingaben in diese EVM-Implementierungen (z. B. Aurora, Moonbeam) und den hochmodernen Ethereum-Client (d. h. geth) einzuspeisen, um zu prüfen, ob sie die gleiche Ausgabe liefern. Spezifisch sammeln wir historische Transaktionen auf Ethereum und mutieren die Vertragschlüssel und Transaktionszustände mit verschiedenen Strategien, um Testfälle zu generieren. Unsere Ergebnisse zeigen, dass Aurora Engine und Moonbeam die Spezifikation in einigen Fällen nicht einhalten. Glücklicherweise wurden alle gemeldeten Probleme behoben und wir werden nun die Details teilen.
3. Gefundene Bugs
Die meisten dieser Bugs befinden sich in den vorkompilierten Verträgen, und die Grundursache und die Auswirkungen sind vielfältig. Einige der Bugs können beispielsweise die Berechnung des Nonce-Werts beeinflussen, während andere die Gasberechnung beeinflussen und weiter zu einem DoS-Angriff führen können. Alle gefundenen Bugs verstoßen gegen die vorgesehene Ausführungslogik der EVM-Spezifikation und können in bestimmten Fällen zu unerwartetem Verhalten führen. Im Folgenden finden Sie eine detaillierte Beschreibung der gefundenen Bugs.
3.1 Unzureichende Validierung
Kryptografische Logik ist komplex. In diesem Fall kann die Implementierung der entsprechenden Logik in EVM-Bytecode zu einem recht hohen Gasverbrauch führen. Stattdessen können die vorkompilierten Verträge, die in nativem Code entwickelt wurden, die Leistung steigern. Wir haben jedoch mehrere Bugs in den vorkompilierten Verträgen aufgrund unzureichender Validierung gefunden.
Aurora Engine: ecPairing
Dieser Bug wurde im vorkompilierten Vertrag ecPairing gefunden.
Die Eingabe von ecPairing besteht aus mehreren Punkten auf zwei elliptischen Kurven. Gemäß der Spezifikation ist der Punkt (0, 0) auf beiden Kurven und sollte eine gültige Eingabe sein:


Aurora Engine (Version 2.7.0) bricht jedoch ab, wenn der Punkt (0,0) in der Eingabe enthalten ist.

Der zugehörige PR ist hier.
Moonbeam: ecMul
Dieser Bug befindet sich im vorkompilierten Vertrag ecMul. Im Gegensatz zu Aurora Engine bricht Moonbeam die Transaktion ab, wenn die Eingabe gültig ist. Gemäß der Spezifikation sollte der vorkompilierte Vertrag ecMul die Eingabe mit Nullen auffüllen, wenn die Länge der Eingabe kleiner als 64 ist. Moonbeam bricht jedoch stattdessen ab, anstatt die Auffülloperation durchzuführen.

Wir haben auch festgestellt, dass die vorkompilierten Verträge ecAdd und modexp das gleiche Problem aufweisen.
Der zugehörige PR ist hier.
Moonbeam: ecRecover
Dieser Bug befindet sich im vorkompilierten Vertrag ecRecover, der zur Wiederherstellung der Ethereum-Adresse verwendet wird.
Gemäß der Spezifikation repräsentiert input[32..63] v einen U256-Identifikator und sollte entweder 27 oder 28 sein, andernfalls sollte ecRecover nichts zurückgeben (aber die gesamte Transaktion sollte nicht abbrechen).
Moonbeam macht hier jedoch zwei Fehler:
- Es prüft nur input[63] anstatt input[32..63] in einen U256-Typ umzuwandeln und dann den Wert zu prüfen.
- Die Eingabe wird als gültig betrachtet, wenn der Identifikator 0 oder 1 ist (es sollten nur 27 oder 28 sein).

Der zugehörige PR ist hier.
Moonbeam: ecPairing
Dieser Bug befindet sich im vorkompilierten Vertrag ecPairing. Moonbeam bricht die Transaktion nicht ab, wenn die Eingabe ungültig ist. Gemäß der Spezifikation muss die Eingabe des vorkompilierten Vertrags ecPairing ein Vielfaches von 192 sein. Andernfalls sollte die Transaktion abgebrochen werden.

Moonbeam bricht die Transaktion jedoch nicht ab, wenn die oben genannten Anforderungen nicht erfüllt sind.
Der zugehörige PR ist hier.
3.2 Falsche Gasberechnung
Jeder vorkompilierte Vertrag hat einen Algorithmus zur Bestimmung des Gasverbrauchs. Eine falsche Gasberechnung kann zu einem DoS-Angriff führen.
Wir haben jedoch zwei Bugs sowohl in Aurora Engine als auch in Moonbeam gefunden, bei denen die Gasberechnung falsch ist.
Aurora Engine: modexp
Der Bug befindet sich im vorkompilierten Vertrag modexp. Der Algorithmus zur Berechnung des Gasverbrauchs ist in EIP-2565 definiert. Der Gasverbrauch hängt von der Anzahl der Iterationen ab.
Der Algorithmus zur Berechnung der Anzahl der Iterationen ist der folgende.
def calculate_iteration_count(exponent_length, exponent):
iteration_count = 0
if exponent_length <= 32 and exponent == 0: iteration_count = 0
elif exponent_length <= 32: iteration_count = exponent.bit_length() - 1
elif exponent_length > 32: iteration_count = (8 * (exponent_length - 32)) + ((exponent & (2**256 - 1)).bit_length() - 1)
return max(iteration_count, 1)
Gemäß dem obigen Algorithmus ist die Anzahl der Iterationen mindestens eins. Aurora Engine gibt jedoch iteration_count direkt zurück und nicht max(iteration_count, 1). In diesem Fall kann der zurückgegebene Wert (d. h. iteration_count) 0 sein, was bedeutet, dass Aurora in bestimmten Fällen deutlich weniger Gasgebühren berechnet als erwartet.
Der zugehörige Issue-Link ist hier.
Moonbeam: modexp
Der Bug befindet sich ebenfalls in der Funktion calculate_iteration_count des vorkompilierten Vertrags modexp. Er wurde jedoch in Moonbeam gefunden.
Wenn die exponent_length größer als 32 ist, wird die iteration_count mit dem folgenden Algorithmus berechnet:
(8 * (exponent_length - 32)) + ((exponent & (2**256 - 1)).bit_length() - 1)
Beachten Sie, dass hier exponent & (2**256 - 1) verwendet wird, was die niedrigsten 32 Bytes von exponent nimmt, und die Implementierung von Moonbeam folgt diesem Algorithmus.
Gemäß der Spezifikation sollte die Formel zur Gasberechnung jedoch die höchsten 32 Bytes von exponent verwenden:

Der zugehörige PR ist hier.
3.3 Nonce-Inkrementierungs-Bug
Die Nonce eines externen Kontos (EOA) gibt die Anzahl der erfolgreichen Transaktionen an, die von dieser Adresse signiert wurden. Wir haben jedoch festgestellt, dass die Nonce durch das Senden ungültiger Transaktionen in Aurora Engine erhöht werden kann.
Gemäß EIP-1559 sollte die EVM vor der Ausführung einer Transaktion sicherstellen, dass der Unterzeichner über genügend Guthaben verfügt, um das übertragene native Token (z. B. ETH) und das erforderliche Gas zu decken. Andernfalls sollte die Transaktion verworfen und die Nonce des Unterzeichners nicht erhöht werden.

Obwohl Aurora Engine die Transaktion in dieser Situation verwirft, erhöht sie dennoch die Nonce des Unterzeichners.
Der zugehörige PR ist hier.
3.4 Falsche Opcode-Implementierung
Dieser Bug betrifft die Implementierung eines bestimmten Opcodes (d. h. PUSH). Wenn die Bytes nach dem PUSH-Opcode unvollständig sind, sollten sie rechtsbündig ausgerichtet sein. Beispielsweise kann der Bytecode 0x64ffff dekodiert werden als:
PUSH5 0xffff
Da der Operand rechtsbündig ausgerichtet sein soll, sollte der Wert 0xffff000000 auf den Stack gepusht werden. Die EVM-Implementierungen in Aurora Engine und Moonbeam pushen jedoch stattdessen 0xffff, was falsch ist.
Der zugehörige PR ist hier.
4. Unser Service
Bei BlockSec verstehen wir die Bedeutung der Aufrechterhaltung der EVM-Kompatibilität und -Sicherheit über verschiedene Blockchain-Implementierungen hinweg. Deshalb haben wir einen systematischen Ansatz zur Fehlererkennung entwickelt, der Schwachstellen in EVM-Implementierungen mühelos lokalisieren kann.
Unser internes System hat sich bei der Lokalisierung von Bugs und Sicherheitslücken in EVM-Implementierungen als äußerst wirksam erwiesen. Es hat erfolgreich vier Bugs in Aurora Engine und vier Bugs in Moonbeam gemeldet und behoben. Darüber hinaus wurde unsere Testmethodik letztes Jahr zur Lokalisierung zweier kritischer Schwachstellen (CVE-2021–46102, CVE-2022–23066) in der Solana rbpf-Implementierung eingesetzt, was die Effektivität unseres Ansatzes unterstreicht.
Durch die Implementierung unseres systematischen Ansatzes zur Fehlererkennung können unsere Kunden sicher sein, dass ihre EVM-Implementierungen sicher und zuverlässig sind. Wir sind bestrebt, erstklassige Lösungen für EVM-Kompatibilität und -Sicherheit anzubieten und unseren Kunden zu helfen, Vertrauen bei ihren Nutzern und Stakeholdern aufzubauen.
Über BlockSec
Das BlockSec-Team konzentriert sich auf die Sicherheit des Blockchain-Ökosystems und arbeitet mit führenden DeFi-Projekten zusammen, um deren Produkte zu sichern. Das Team wird von erstklassigen Sicherheitsexperten und erfahrenen Experten aus Wissenschaft und Industrie gegründet. Sie haben zahlreiche Blockchain-Sicherheitsarbeiten auf renommierten Konferenzen veröffentlicht, mehrere Zero-Day-Angriffe von DeFi-Anwendungen gemeldet und detaillierte Analyseberichte über sicherheitsrelevante Vorfälle mit hoher Auswirkung veröffentlicht.



