Der Angriff besteht aus zwei Hauptschritten. Der erste Schritt ist der Wechsel des Keepers und der zweite Schritt ist der Abzug der Token (Ausführung der Entsperrfunktion). Der zweite Schritt wurde vollständig analysiert. Für den ersten Schritt hat Kevin darauf hingewiesen, dass die Hash-Kollision ein cleverer Trick ist, den der Hacker nutzt, um die Funktion putCurEpochConPubKeyBytes aufzurufen. Warum der Angreifer überhaupt eine gültige Transaktion haben kann, um diesen Aufruf zu tätigen, ist jedoch noch unbekannt.
In diesem Blog verwenden wir die bösartige Transaktion von Ontology (0xf771ba610625d5a37b67d30bf2f8829703540c86ad76542802567caaffff280c), um den gesamten Prozess zu veranschaulichen.
Zusammenfassend stellen wir fest, dass:
- Der Ontology-Relayer über keine ausreichenden Validierungsmechanismen für Transaktionen von der Ontology-Kette verfügt.
- Der Angreifer kann die Funktion
putCurEpochConPubKeyBytesinEthCrossChainDatadirekt aufrufen, ohne den Ethereum-Relayer zu durchlaufen, solange es einen gültigen Block auf der Poly-Kette gibt. - Die von Kevin angesprochene Hash-Kollision.
Haftungsausschluss: Dieser Blog enthält die Analyseergebnisse unseres Teams, die auf dem öffentlich zugänglichen Quellcode und den On-Chain-Transaktionen basieren. Ohne weitere Informationen von Poly Network können wir unser Ergebnis nicht verifizieren.
0x.1 Transaktionen und Verträge
Angriffsfluss
Ontology-Transaktion -> Ontology-Relayer -> Poly-Kette -> Ethereum-Relayer -> Ethereum
Ethereum
0x838bf9e95cb12dd76a54c9f9d2e3082eaf928270: EthCrossChainManager
0xcf2afe102057ba5c16f899271045a0a37fcb10f2: EthCrossChainData
0x250e76987d838a75310c34bf422ea9f1ac4cc906: LockProxy
Transaktion: 0xb1f70464bd95b774c6ce60fc706eb5f9e35cb5f06e6cfe7c17dcda46ffd59581
Ontology
Transaktion: 0xf771ba610625d5a37b67d30bf2f8829703540c86ad76542802567caaffff280c
Poly
Transaktion: 0x1a72a0cf65e4c08bb8aab2c20da0085d7aee3dc69369651e2e08eb798497cc80
0x2. Angriffsfluss
Nehmen wir als Beispiel den Angriff auf Ethereum.
Dies ist ein Cross-Chain-Angriff, an dem drei Ketten (und ihre entsprechenden Relayer) beteiligt sind: Ontology Chain, Poly Chain und Ethereum.
Der gesamte Angriffsfluss besteht aus drei Schritten:
- Der Angreifer initiierte zuerst eine bösartige Transaktion (0xf771ba610625d5a37b67d30bf2f8829703540c86ad76542802567caaffff280c) auf der Ontology-Kette.
- Der Angreifer änderte dann den öffentlichen Schlüssel des Keepers, der im
EthCrossChainData-Vertrag auf Ethereum gespeichert ist. - Der Angreifer erstellte schließlich eine bösartige Transaktion, um Krypto-Assets zu ernten.
0x2.1 Der erste Schritt
Der Angreifer initiierte zuerst eine Cross-Chain-Transaktion (0xf771ba610625d5a37b67d30bf2f8829703540c86ad76542802567caaffff280c) von Ontology, die eine bösartige Nutzlast enthielt:

Sie bemerken vielleicht, dass diese Nutzlast einen präparierten Funktionsnamen enthält (beginnend mit 6631, d.h. f1121318093 nach der Umwandlung). Dieser Name ist auf jeden Fall sorgfältig gewählt, da der Angreifer ihn nutzen würde, um die Funktion putCurEpochConPubKeyBytes (siehe EthCrossChainData-Vertrag auf Ethereum) durch Ausnutzung der Hash-Kollision von Funktionssignaturen aufzurufen. Hier werden wir die Details der Hash-Kollision nicht erläutern, da sie bereits ausführlich besprochen wurden.
Danach wurde diese Transaktion erfolgreich vom Ontology Chain Relayer akzeptiert. Beachten Sie, dass es keine strenge Verifizierung gab. Infolgedessen wurde sie zu einer gültigen neuen Transaktion (0x1a72a0cf65e4c08bb8aab2c20da0085d7aee3dc69369651e2e08eb798497cc80) auf der Poly-Kette.
Die neue Transaktion wurde dann vom Ethereum Relayer wahrgenommen und ZURÜCKGEWIESEN. Da der Ethereum Relayer die Zielvertragsadresse (d.h. in diesem Fall EthCrossChainData) verifizierte, wäre jedoch nur LockProxy erlaubt gewesen.
Somit wurde die Verarbeitung beendet. Die Transaktion mit der bösartigen Nutzlast wurde jedoch auf der Poly-Kette gespeichert, was für einen Angriff ausgenutzt werden kann.
0x2.2 Der zweite Schritt
Der Angreifer sendete manuell eine Transaktion an Ethereum, indem er die Funktion verifyHeaderAndExecuteTx des EthCrossChainManager-Vertrags aufrief. Die auf der Poly-Kette gespeicherten bösartigen Transaktionsdaten wurden als Eingabe verwendet. Als gültige Poly-Ketten-Transaktion konnte sie die Verifizierung (einschließlich Signaturen und Merkle-Proof) in der Funktion verifyHeaderAndExecuteTx umgehen. Danach wurde die Funktion putCurEpochConPubKeyBytes des EthCrossChainData-Vertrags aufgerufen, um die ursprünglichen vier Keeper durch einen neuen zu ersetzen (d.h. 0xA87fB85A93Ca072Cd4e5F0D4f178Bc831Df8a00B), der vom Angreifer kontrolliert wurde.
0x2.3 Der dritte Schritt
Nach der Änderung des Keepers konnte der Angreifer die Funktion verifyHeaderAndExecuteTx direkt aufrufen, ohne die Poly-Kette zu verwenden. Schließlich wurde die Funktion unlock des LockProxy-Vertrags aufgerufen, um riesige Mengen an digitalen Vermögenswerten von Ethereum zu stehlen. Eine detaillierte Analyse finden Sie in unserem früheren Bericht.
0x3. Relayer
Sowohl der Ontology- als auch der Ethereum-Relayer sind in Go implementiert. Es fehlt ihnen jedoch an ausreichender Validierung, so dass
- Der Angreifer kann eine bösartige Transaktion konstruieren, die in die Poly-Kette gepackt wird.
- Der Angreifer kann Funktionen im
EthCrossChainData-Smart-Contract auf Ethereum direkt aufrufen.
0x3.1 Der Ontology-Relayer vertraut den Cross-Chain-Transaktionen von Ontology blind
Der ont-relayer ist dafür verantwortlich, Cross-Chain-Transaktionen von der Ontology-Kette zu überwachen und an die Poly-Kette zu senden.
- Side bedeutet die Ontology-Kette; Alliance bedeutet die Poly-Kette.
CrossChainContractAddressist der native Smart Contract (Nummer 09) auf der Ontology-Kette.

Die obige Abbildung zeigt, dass der Ontology-Relayer zwei Routinen startet, um Cross-Chain-Transaktionen von und zur Ontology-Kette zu überwachen, sowie die Routine zur Überprüfung des Status der Cross-Chain-Transaktion (Zeile 71).

In der obigen Abbildung ruft der Ontology-Relayer die vom Ontology-Kette bereitgestellte RPC-Schnittstelle (Zeile 215 GetSmartContractEventByBlock) auf, um Ereignisse auf der Kette zu erhalten. Aus Zeile 228 und 232 geht hervor, dass diese Routine nur auf das makeFromOntProof-Ereignis lauscht, das von CrossChainContractAddress ausgelöst wird.

In der obigen Abbildung gibt es bei der Verarbeitung der Cross-Chain-Transaktion fünf Prüfungen. Die ersten beiden sind Prüfungen der RPC-Anfragen (Prüfung 1 und 4) an die Ontology-Kette und drei Prüfungen, ob die Parameter null sind (Prüfung 2, 3 und 5). Es gibt jedoch keine Prüfung der Semantik in der Cross-Chain-Transaktion, d.h. ob der Vertrags- und Funktionsname angemessen sind. Schließlich sendet er die Transaktion an die Poly-Kette (Zeile 183).

Der Ontology-Relayer konstruiert und sendet die Transaktion mit der RPC-Schnittstelle (Zeile 164 - SendTransaction) an die Poly-Kette.

Die Funktion ProcessToAliianceCheckAndRetry prüft nur, ob die Transaktion fehlgeschlagen ist. Wenn dies der Fall ist, wird die Transaktion erneut gesendet.
Zusammenfassend lässt sich sagen, dass ont-relayer auf alle makeFromOntProof-Ereignisse lauscht, die von CrossChainContractAddress von der Ontology-Kette ausgelöst werden. Dann wird die Transaktion an die Poly-Kette gesendet. Beachten Sie, dass eine Cross-Chain-Transaktion von jedem auf der Ontology-Kette das makeFromOntProof-Ereignis auslöst, was dazu führt, dass sie an die Poly-Kette gesendet wird.
0x3.2 Umgehung des Ethereum-Relayers
Der Ethereum Relayer ist dafür verantwortlich, Transaktionen von der Poly-Kette zu überwachen und diese dann an Ethereum zu senden.

Der Ethereum Relayer startet eine Goroutine, um die Poly-Kette zu überwachen.

Er überwacht die Cross-Chain-Transaktion, deren Ziel Ethereum ist (Zeile 275 - 278). Dann prüft er, ob der Zielvertrag (ToContractAddress) einer der in config.TargetContracts konfigurierten Verträge ist. Wenn nicht, wird die Cross-Chain-Transaktion nicht an die Zielkette (Ethereum) gesendet.
Der Angreifer kann jedoch direkt mit der Zielkette interagieren und die Funktion in EthCrossChainManager aufrufen. Anders ausgedrückt, die Prüfung im Ethereum-Relayer kann umgangen werden. Solange die bösartige Transaktion auf der Poly-Kette gepackt wurde (was im vorherigen Schritt über den Ontology-Relayer erreicht wurde), kann der Angreifer direkt mit EthCrossChainManager interagieren. Während dieses Prozesses können die Signaturprüfung (ECCUtils.verifySig) und der Merkle-Proof (ECCUtils.merkleProve) bestanden, da eine gültige Transaktion auf der Poly-Kette vorhanden ist.
Durch die Verwendung der beiden vorherigen Methoden kann der Angreifer erfolgreich die Funktion ToContractAddress.method auf Ethereum aufrufen. In Verbindung mit der Hash-Kollision wird schließlich die Funktion putCurEpochConPubKeyBytes aufgerufen, um den Keeper zu ändern.
Credits
Yufeng Hu, Siwei Wu, Lei Wu, Yajin Zhou @ BlockSec
Offizielle Website: https://blocksec.com/
Offizieller Twitter-Account: https://twitter.com/BlockSecTeam



