Der Angriff besteht aus zwei Hauptschritten. Der erste Schritt ist die Änderung des Keepers und der zweite Schritt ist der Entzug der Token (Ausführung der unlock-Funktion). 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 jedoch überhaupt eine gültige Transaktion hat, um diesen Aufruf zu tätigen, ist 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 nicht über ausreichende Validierungsmechanismen für Transaktionen von der Ontology-Kette verfügt.
- Der Angreifer die Funktion
putCurEpochConPubKeyBytesinEthCrossChainDatadirekt aufrufen kann, 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 unsere Ergebnisse 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 den Angriff auf Ethereum als Beispiel.
Dies ist ein Cross-Chain-Angriff, der drei Ketten (und ihre entsprechenden Relayer) involviert: 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 Chain;
- Der Angreifer modifizierte 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 enthält:

Sie werden bemerken, dass diese Nutzlast einen manipulierten Funktionsnamen enthält (beginnend mit 6631, d. h. f1121318093 nach Umwandlung). Dieser Name ist sorgfältig gewählt, da der Angreifer ihn verwenden würde, um die Funktion putCurEpochConPubKeyBytes (siehe EthCrossChainData-Vertrag auf Ethereum) durch Ausnutzung der Hash-Kollision von Funktionssignaturen aufzurufen. Wir werden die Details der Hash-Kollision hier nicht erläutern, da sie bereits viel diskutiert wurden.
Danach wurde diese Transaktion erfolgreich von der Ontology Chain Relayer akzeptiert. Beachten Sie, dass keine strikte Überprüfung existiert. 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) überprüfte, war jedoch nur LockProxy erlaubt.
Daher wurde die Verarbeitung abgebrochen. Die Transaktion mit der bösartigen Nutzlast wurde jedoch auf der Poly-Kette gespeichert, was zur Einleitung eines Angriffs 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 umging sie die Verifizierung (einschließlich der Signaturen und des Merkle-Beweises) in der Funktion verifyHeaderAndExecuteTx. Danach wurde die Funktion putCurEpochConPubKeyBytes des EthCrossChainData-Vertrags aufgerufen, um die ursprünglichen vier Keeper durch einen neuen (d. h. 0xA87fB85A93Ca072Cd4e5F0D4f178Bc831Df8a00B) zu ersetzen, der vom Angreifer kontrolliert wurde.
0x2.3 Der dritte Schritt
Nach der Modifikation 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 digitaler Vermögenswerte von Ethereum zu stehlen. Die detaillierte Analyse finden Sie in unserem vorherigen Bericht.
0x3. Relayer
Sowohl der Ontology- als auch der Ethereum-Relayer sind in Go implementiert. Sie verfügen jedoch über nicht genügend Validierung, so dass
- Der Angreifer eine bösartige Transaktion konstruieren kann, die in die Poly-Kette gepackt wird
- Der Angreifer direkt Funktionen im
EthCrossChainData-Smart-Contract auf Ethereum aufrufen kann
0x3.1 Der Ontology-Relayer vertraut blind den Cross-Chain-Transaktionen von Ontology
Der ont_relayer ist dafür zuständig, Cross-Chain-Transaktionen von der Ontology-Kette abzufangen 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, und die Routine zur Überprüfung des Status der Cross-Chain-Transaktion (Zeile 71).

In der obigen Abbildung ruft der Ontology-Relayer die von der Ontology-Kette bereitgestellte RPC-Schnittstelle auf (GetSmartContractEventByBlock in Zeile 215), um Ereignisse auf der Kette zu erhalten. Ab Zeile 228 und 232 sehen wir, dass diese Routine nur das Ereignis makeFromOntProof überwacht, 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 sie die Transaktion an die Poly-Kette (Zeile 183).

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

Die Funktion ProcessToAliiance**Check**AndRetry prüft nur, ob die Transaktion fehlgeschlagen ist. Wenn ja, wird die Transaktion erneut gesendet.
Zusammenfassend lässt sich sagen, dass ont-relayer alle makeFromOntProof-Ereignisse von CrossChainContractAddress von der Ontology-Kette abhört. 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 zuständig, Transaktionen von der Poly-Kette abzufangen und sie dann an Ethereum zu senden.

Der Ethereum Relayer startet eine Goroutine, um die Poly Chain zu überwachen;

Er überwacht die Cross-Chain-Transaktion, deren Ziel Ethereum ist (Zeile 275 - 278). Dann prüft er, ob der Zielvertrag (ToContractAddress) zu den in config.TargetContracts konfigurierten Verträgen gehört. Andernfalls 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 verpackt 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-Beweis (ECCUtils.merkleProve) bestanden werden, da eine gültige Transaktion auf der Poly-Kette vorhanden ist.
Durch die Verwendung der beiden vorherigen Methoden kann der Angreifer erfolgreich ToContractAddress.method auf Ethereum aufrufen. In Kombination 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



