Back to Blog

#9: MEV-Bot 0xd61492: Vom Jäger zur Beute durch einen genialen Exploit

Phalcon Security
February 21, 2024
6 min read

Am 3. August 2023 wurde ein MEV-Bot auf Arbitrum angegriffen, was zu einem Verlust von 800.000 US-Dollar führte. Die Grundursache für diesen Angriff war eine unzureichende Überprüfung der Benutzereingaben.

In Anbetracht der komplexen Interaktionen zwischen MEV-Bots und ihren nicht verifizierten Verträgen zeigt sich, dass dass der Verzicht auf Open-Source keine Sicherheit garantiert, insbesondere bei DeFi-Protokollen.

Hintergrund

MEV-Bot

Ein MEV-Bot (Maximum Extractable Value Bot) wurde entwickelt, um profitable Gelegenheiten auf der Blockchain zu identifizieren und zu nutzen. Er funktioniert durch die Analyse ausstehender Transaktionen (d. h. solche im Mempool) oder On-Chain-Zustände, um durch Arbitrage Gewinne zu erzielen.

Im Gegensatz zu typischen Front-Running- und Sandwich-Attack-MEV-Bots konzentrierte sich der bei diesem Angriff ins Visier genommene MEV-Bot auf die Ausführung von Strategien wie Dreiecksarbitrage und Schuldenliquidation. Diese Bots selbst tragen dazu bei, die Preise für AMMs zu stabilisieren und unterstützen Kreditprotokolle bei der Liquidation, um einen reibungslosen Betrieb zu gewährleisten – sie sind ein wesentlicher Bestandteil der gesunden Funktionsweise des DeFi-Ökosystems.

Flashloan

Ein Flashloan stellt eine einzigartige Innovation innerhalb des DeFi-Ökosystems dar – eine Form der unbesicherten Kreditvergabe. Sie können über einen Flashloan ohne jegliche Sicherheiten bis zu einer Milliarde Dollar leihen, vorausgesetzt, das Darlehen wird innerhalb derselben Transaktion zurückgezahlt. Wenn das Darlehen nicht innerhalb dieser Transaktion zurückgezahlt wird, wird es rückgängig gemacht, als ob die Transaktion nie stattgefunden hätte.

Dieser Mechanismus wird häufig für Arbitrage oder die Hebelung anderer DeFi-Strategien genutzt, um vorübergehende Marktineffizienzen auszunutzen.

Die Schwachstelle

Kurzfassung

Die unzureichende Validierung von Benutzereingabeparametern ermöglichte es dem Angreifer, einen FakeFlashloanProvider einzuschleusen. Der Tresor-Vertrag (Vault) nutzte diesen Provider, um einen Flashloan zu initiieren. Um den Flashloan anschließend zu begleichen, genehmigte der Tresor-Vertrag dem FakeFlashloanProvider Token-Transfers, was zur unbefugten Übertragung von Vermögenswerten aus dem Tresor führte.

Detaillierte Version

Die betroffenen Verträge sind:

  • Vault: Der angegriffene Vertrag 0xd614927acfb9744441180c2525faf4cedb70207f fungiert als „Vault“ (Tresor), stellt Reserven bereit und ermöglicht Flashloans von anderen Protokollen wie AAVE und Balancer.
  • Arbitrage Bot: Der anfällige Vertrag 0x8db0efee6a7622cd9f46a2cf1aedc8505341a1a7 fungiert als „Arbitrage Bot“ und nimmt die Rolle des Kreditnehmers im „Vault“-Vertrag ein.

Die Funktion 0x0582f20f() im „Arbitrage Bot“ ist der Haupteinstiegspunkt für den Start von Arbitrage-Geschäften. Sie ruft zuerst die borrow()-Funktion im „Vault“ auf, um das ursprüngliche Kapital zu erhalten, und führt dann die Arbitrage-Logik über einen delegatecall an einen externen Vertrag aus, der in den Calldata angegeben ist und keiner Validierung unterliegt.

function 0x0582f20f(...) {
  ...
  v67, /* uint256 */ v68 = address(0xd614927acfb9744441180c2525faf4cedb70207f).borrow(address(v39), address(v9[0]), v29).gas(msg.gas);
  ...
  // 0x4da91757 = swap(address,address,address,uint256,uint256,uint256,address)
  MEM[MEM[64] + 32] = uint224(address(MEM[0 + v4[v69]])) | 0x4da9175700000000000000000000000000000000000000000000000000000000;
  v82 = address(v76 >> 96).delegatecall(MEM[(MEM[64]) len 228], MEM[(MEM[64]) len 0]).gas(msg.gas);
  ...
  v189 = v170.refund(0x410085df, address(v9[0]), address(v39), v68, address(v9[0]), v29, v186, 4 + MEM[64] + (varg2.length << 5) - (4 + MEM[64]) + 192).gas(msg.gas);
  ...
}

Anschließend ruft er 0x512b7351() im „Vault“ auf und startet einen Flashloan zum FakeFlashloanProvider-Vertrag des Angreifers.

Die Funktion 0x512b7351() erfordert, dass msg.sender auf der Zulassungsliste steht, aber dies wurde erfolgreich durch den vorangegangenen delegatecall umgangen, wodurch die Prüfung ausgehebelt wurde. Dies ist ein sehr kritischer Schritt.

function 0x512b7351(...) public nonPayable { 
    ...
    if (_borrow[msg.sender] >= 1) {
        v0 = !_refund;
    }
    require(v0, Error('BBVault: FORBIDDEN'));
    ...
    v38 = v23.length;
    v39 = v23.data;
    _refund = keccak256(v23);
    ...
    <FakeFalshloanProvider>.flashloan(...);
    ...
}

Während des Flashloan-Callbacks überträgt die Funktion executeOperation() im „Vault“ zunächst die geliehenen Vermögenswerte an den „Arbitrage Bot“ (MEVBot 0x8db0ef) und ruft dann dessen 0x7fe3ba8b() auf.

function executeOperation(...) {
  ...
  require(_refund == keccak256(v3.data), Error('BBVault: STATUS'));

  Token.transfer(ArbitrageBot, amountBorrowed);
  <ArbitrageBot>.call(0x7fe3ba8b...);
  
}

Der „Arbitrage Bot“ vertraut diesem externen Aufruf und überträgt die erhaltenen Vermögenswerte zurück an den FakeFlashloanProvider. Der „Vault“ erkennt dies jedoch nicht und gewährt dem FakeFlashloanProvider am Ende von executeOperation() weiterhin die Genehmigung zur Rückzahlung des Flashloans.

Der Angriffsprozess

Angriffs-Tx: 0x864c8cfb8c54d3439613e6bd0d81a5ea2c5d0ad25c9af11afd190e5ea4dcfc1f

Der Angreifer ruft die Funktion 0x0582f20f() des „Arbitrage Bots“ auf, welcher wiederum einen Delegate-Call an den Vertrag des Angreifers durchführt.

Der hack_contract_2 ruft dann die Funktion 0x512b7351() des Opfer-Vertrags auf. Die Funktion 0x512b7351() erfordert, dass msg.sender auf der Zulassungsliste steht, was jedoch durch den vorherigen delegatecall erfolgreich umgangen wurde, wodurch die Prüfung ausgehebelt wurde.

Das Opfer ruft dann den FakeFlashloanProvider-Vertrag des Angreifers auf, überträgt alle per Flashloan geliehenen Mittel an das Opfer und ruft die executeOperation() des Opfers auf.

Die Funktion 0x7fe3ba8b() des „Arbitrage Bots“ führt erneut einen delegatecall an den Vertrag des Angreifers aus, wobei diesmal alle Vermögenswerte an den Angreifer zurücktransferiert werden. An diesem Punkt wurden die vom Flashloan-Provider des Angreifers geliehenen Vermögenswerte zurückgezahlt.

Das Opfer („Vault“) genehmigt dem FakeFlashloanProvider Token-Transfers, möglicherweise in der Absicht, den Flashloan zurückzuzahlen.

Der Angreifer nutzt diese Genehmigung aus, um Profite zu erzielen, indem er transferFrom verwendet, um Gelder aus dem Opfer-Vertrag abzuziehen.

Sicherheitsempfehlungen

Nicht-Open-Source-Code garantiert keine Sicherheit

Der Glaube, dass nicht-quelloffener oder obfuskierter Code Sicherheit gewährleistet, ist ein Irrtum. Dieser MEV-Bot-Vorfall zeigt, dass Geheimhaltung nicht vor Exploits schützt und Entwicklern lediglich ein falsches Gefühl von Sicherheit vermitteln kann.

Strenge Eingabevalidierung

Es ist entscheidend, alle Vertragsinteraktionen und Calldata sorgfältig zu validieren, insbesondere beim Umgang mit Standardschnittstellen wie Flashloan- und Swap-Callbacks. Die Gewährleistung der Datenintegrität und Sicherheit sollte bei der Konzeption und Implementierung von Verträgen Priorität haben.

Lesen Sie weitere Artikel dieser Serie:

Get Real-Time Protection with Phalcon Security

Audits alone are not enough. Phalcon Security detects attacks in real time and blocks threats mid-flight.

phalcon security