Back to Blog

Wöchentlicher Web3-Sicherheitsvorfälle-Überblick | 9. – 15. März 2026

March 18, 2026
23 min read

In der vergangenen Woche (09.03.2026 - 15.03.2026) hat BlockSec acht Angriffsvorfälle erkannt und analysiert, mit geschätzten Gesamtverlusten von ~1,66 Mio. $. Die folgende Tabelle fasst diese Vorfälle zusammen, und detaillierte Analysen zu jedem Fall werden in den folgenden Unterabschnitten bereitgestellt.

Datum Vorfall Typ Geschätzter Verlust
09.03.2026 EtherFreakers-Vorfall Fehlerhafte Geschäftslogik ~25.000 $
10.03.2026 Alkemi-Vorfall Fehlerhafte Geschäftslogik ~89.000 $
10.03.2026 MT-Vorfall Fehlerhafte Geschäftslogik ~242.000 $
11.03.2026 AAVE-Liquidations-Vorfall Fehlkonfiguration ~1,01 Mio. $
11.03.2026 Planet Finance-Vorfall Fehlerhafte Geschäftslogik ~10.000 $
12.03.2026 AM-Vorfall Fehlerhafte Geschäftslogik ~131.000 $
12.03.2026 DBXen-Vorfall Fehlerhafte Geschäftslogik ~149.000 $
15.03.2026 Goose Finance-Vorfall Fehlerhafte Geschäftslogik ~8.000 $

EtherFreakers-Vorfall

Kurzzusammenfassung

Am 9. März 2026 wurde EtherFreakers, ein NFT-Spiel auf Ethereum, aufgrund einer fehlerhaften Doppelzählung ausgenutzt, was zu einem Verlust von ~25.000 $ führte. Jedes NFT im Spiel besitzt ein abhebbares ETH-Guthaben (genannt "Energie"). Als Spielmechanik können Spieler attack() nutzen, um mit einem NFT ein anderes zu erobern und die Energie des Ziels zu beanspruchen. Der Vertrag zahlt jedoch das Guthaben des Ziels aus und überträgt das NFT, bevor die Buchführung abgeschlossen ist. Ein Transfer-Hook liest daraufhin veraltete, vor der Auszahlung liegende Daten und speist einen Teil davon zurück in einen globalen Dividendenpool, wodurch der Pool ohne neue ETH-Deckung aufgebläht wird. Der Angreifer wiederholte diesen Eroberungsmechanismus in einer Schleife, um den globalen Index zu erhöhen, und entzog anschließend das aufgeblähte Guthaben aus einer Reihe von NFTs.

Hintergrund

EtherFreakers ist ein On-Chain-NFT-Spiel, bei dem jedes NFT (genannt "Freaker") ein abhebbares ETH-Guthaben namens energy besitzt. Das System funktioniert wie ein Dividendenpool: Wenn bestimmte Aktionen auftreten, wird ein Bruchteil des ETH proportional auf alle Freaker verteilt. Das abhebbare ETH jedes Freakers wird durch einen globalen Akkumulator freakerIndex in Kombination mit einem token-spezifischen Gewichtungsfaktor fortune verfolgt.

Konkret lautet die Buchhaltungsformel: energyOf = basic + (freakerIndex - index) * fortune. Der freakerIndex erhöht sich, wenn _dissipateEnergyIntoPool(amount) ausgeführt wird, wobei 80% des amount an alle Freaker und 20% an die Ersteller verteilt werden. Direkte Einzahlungen über charge() erhöhen nur basic, ohne den freakerIndex zu beeinflussen. Daher sollten Erhöhungen des freakerIndex immer durch tatsächlich in das System fließendes Ether gedeckt sein. Wenn der freakerIndex ohne entsprechenden ETH-Zufluss wächst, können Freaker mehr Ether einlösen, als der Vertrag tatsächlich hält.

Schwachstellenanalyse

Die Ursache liegt in einer fehlerhaften Ausführungsreihenfolge im EtherFreak-Vertrag (0x3A27...c0f33). Wenn eine Eroberung erfolgreich ist, führt die Funktion attack() folgende Schritte in dieser Reihenfolge aus:

  1. Zeile 237: Zahlung von targetCharge (die vollständige Energie des Ziel-NFT) als direkte ETH-Überweisung an den Verteidiger. Die Energie ist damit verbraucht.
  2. Zeile 240: Aufruf von _transfer(defender, capturer, targetId), um das NFT zu übertragen. Intern ruft _transfer() den ERC-721-Hook _beforeTokenTransfer() auf, der _dissipateEnergyIntoPool() mit 0,1% von energyOf(targetId) aufruft. Dies ist der erste Aufruf von _dissipateEnergyIntoPool(), und er liest einen veralteten Wert, da Schritt 5 noch nicht stattgefunden hat.
  3. Zeile 241: Expliziter Aufruf von _dissipateEnergyIntoPool(sourceSpent). Dies ist der zweite Aufruf, der Teil der normalen Spiellogik ist.
  4. Zeilen 244-251: Aktualisierung von energyBalances für sowohl sourceId als auch targetId.

Der Fehler liegt in Schritt 2: Da energyBalances[targetId] noch nicht aktualisiert wurde, sieht der Hook weiterhin das Guthaben vor der Auszahlung und speist einen Teil der bereits verbrauchten Energie in den Dividendenpool ein. Sowohl die direkte ETH-Auszahlung in Schritt 1 als auch der Pooleintrag in Schritt 2 greifen auf dieselbe Energie zu, wodurch der freakerIndex ohne neue ETH-Deckung aufgebläht wird.

freakerIndex wächst, wann immer _dissipateEnergyIntoPool() aufgerufen wird:

Angriffsanalyse

Die folgende Analyse basiert auf der Transaktion 0x89e24d...9abd2942.

  • Schritt 1: Leihe 1.700 WETH per Flash-Loan.

  • Schritt 2: Präge zwei neue Freaker, Token 590 und Token 591, unter vom Angreifer kontrollierten Adressen.

  • Schritt 3: Rufe wiederholt die Spielfunktion attack(590, 591) auf und halte die Ausführungen auf dem erfolgreichen Eroberungspfad.

  • Schritt 4: Übertrage nach jedem Erfolg Token 591 zurück an den Helfer, damit dasselbe Paar wiederverwendet werden kann.

  • Schritt 5: Jede erfolgreiche Schleife bläht den freakerIndex über das tatsächlich vom System erhaltene Ether hinaus auf.

  • Schritt 6: Sobald der Index hoch genug ist, entlade eine Reihe zuvor kontrollierter Freaker. Token-IDs 496 bis 520 werden jeweils für 0,278052246002402082 Ether entladen.

  • Schritt 7: Wandle das entzogene Ether in WETH um, zahle das 1.700 WETH Flash-Darlehen zurück und behalte etwa 7,498 WETH als Gewinn.

Fazit

Die Ursache liegt im erfolgreichen Eroberungsablauf von attack(): EtherFreakers zahlt targetCharge aus, bevor der Energiestatus des Ziel-Tokens abgeschlossen ist. _transfer() löst dann _beforeTokenTransfer() aus, der einen veralteten, vor der Auszahlung liegenden energyOf(targetId)-Wert liest und einen Teil davon in den Pool einspeist. Dies erhöht den freakerIndex ohne neue Ether-Deckung, sodass dieselbe Ziel-Energie sowohl als Auszahlung als auch als Pooleintrag gezählt wird. Dies ist ein Fehler in der Geschäftslogik (Aufblähung), kein Reentrancy-Fehler.

Um ähnliche Risiken künftig zu reduzieren:

  • Vermeiden Sie die Neuberechnung wirtschaftlicher Werte aus veränderlichem Zustand innerhalb von Transfer-Hooks, während dieselbe Transaktion noch abgewickelt wird.

  • Wenn der Transfer-Hook eine Zustandsvariable liest, stellen Sie sicher, dass die Ausführungsreihenfolge das Ergebnis nicht beeinflusst (z. B. den Zustand vor Ausführung des Hooks abschließen, nicht danach).


Alkemi-Vorfall

Kurzzusammenfassung

Am 10. März 2026 wurde das Alkemi-Protokoll auf Ethereum ausgenutzt, was zu einem Verlust von ~89.000 $ führte. Die Ursache ist ein Buchhaltungsfehler und eine fehlerhafte Geschäftslogik. Die fehlerhafte Liquidationslogik erlaubt es jedem, seine eigene Position innerhalb derselben Transaktion zu liquidieren und davon zu profitieren. Zusätzlich führt ein Buchhaltungsfehler dazu, dass der Abzug der eigenen Sicherheiten des Angreifers während der Liquidation überschrieben wird, sodass der Angreifer Liquidationsbelohnungen erhält, ohne die vorgesehenen Kosten zu tragen.

Hintergrund

Alkemi ist ein Kreditprotokoll. Wenn die Position eines Kreditnehmers unterbesichert wird, kann jeder liquidateBorrow() aufrufen, um einen Teil der Schuld zurückzuzahlen und Sicherheiten mit einem Abschlag zu beschlagnahmen. Um übermäßige Liquidation zu verhindern, begrenzt das Protokoll den rückzahlbaren Betrag pro Transaktion auf das Minimum von drei Werten:

  1. Das aktuelle Kreditguthaben des Kreditnehmers (currentBorrowBalance_TargetUnderwaterAsset).
  2. Die maximale Rückzahlung, die die Sicherheiten des Kreditnehmers nach Anwendung des Liquidationsabschlags decken können (calculateDiscountedBorrowDenominatedCollateral()).
  3. Der Rückzahlungsbetrag, der erforderlich ist, um das Konto zurück an die Liquidationsgrenze zu bringen (calculateDiscountedRepayToEvenAmount()), nur geprüft, wenn der Markt isSupported ist.

Schwachstellenanalyse

Die Ursache ist eine fehlerhafte Geschäftslogik und ein Buchhaltungsfehler im Alkemi-Protokoll (0x4822...a888). Da currentBorrowBalance_TargetUnderwaterAsset zwangsläufig größer als 0 ist, solange der Kreditnehmer eine offene Schuld hat, und der von calculateDiscountedBorrowDenominatedCollateral() zurückgegebene Wert ebenfalls zwangsläufig größer als 0 ist, solange der Kreditnehmer Sicherheiten hat, verlässt sich das AlkemiEarnPublic-Protokoll effektiv auf calculateDiscountedRepayToEvenAmount(), um zu bestimmen, ob ein bestimmter Kredit liquidiert werden kann. In dieser Funktion sollte die Höhe der zu liquidierenden Schuld basierend auf einer Variable namens accountShortfall_TargetUser berechnet werden.

In der tatsächlichen Implementierung verwendet die Funktion jedoch stattdessen eine globale Variable closeFactorMantissa, um eine Obergrenze für den zulässigen Rückzahlungsbetrag zu berechnen, und gibt diesen Wert zurück. Dadurch kann ein Angreifer innerhalb derselben Transaktion Kredit aufnehmen und sofort seine eigene Position liquidieren.

Zusätzlich zeigen in der Funktion liquidateBorrow(), wenn Liquidator und Kreditnehmer dieselbe Adresse sind, die Variablen supplyBalance_TargetCollateralAsset und supplyBalance_LiquidatorCollateralAsset auf denselben Speicherplatz. Die Funktion berechnet dann ein "reduziertes Guthaben" und ein "belohntes Guthaben" separat basierend auf demselben ursprünglichen Guthaben und schreibt sie anschließend nacheinander an denselben Speicherplatz zurück. Da das reduzierte Guthaben zuerst geschrieben wird und das belohnte Guthaben danach, wird der Reduktionseffekt überschrieben und geht verloren, sodass nur das belohnte Ergebnis übrig bleibt. Dies ermöglicht es dem Angreifer, seinen Gewinn weiter zu vergrößern.

Angriffsanalyse

Die folgende Analyse basiert auf der Transaktion 0xa170...6d9d.

  • Schritt 1: Der Angreifer nimmt ein Flash-Darlehen von 51e18 WETH von Balancer auf.

  • Schritt 2: Der Angreifer wandelt 51e18 WETH in ETH um und stellt es dem Alkemi-Protokoll bereit.

  • Schritt 3: Der Angreifer leiht sich 39,5e18 ETH von Alkemi.

  • Schritt 4: Der Angreifer liquidiert seine eigene Position mit 39,5395e18 ETH.

  • Schritt 5: Der Angreifer hebt 93,5e18 ETH von Alkemi ab.

  • Schritt 6: Der Angreifer zahlt das Flash-Darlehen zurück und erzielt einen Gewinn von 43,4e18 ETH.

Fazit

Die Ursache ist, dass die fehlerhafte Liquidationslogik es dem Angreifer erlaubt, innerhalb derselben Transaktion Kredit aufzunehmen und dann seine eigene Position zu liquidieren, um einen Gewinn zu erzielen, während die fehlerhafte Buchhaltungslogik die Gewinne des Angreifers weiter verstärkt.

Um ähnliche Risiken künftig zu reduzieren:

  • Für Guthabenaktualisierungen bei Kreditnehmer und Liquidator sollte das Protokoll direkt auf Speichervariablen operieren, anstatt die Guthaben zur separaten Berechnung und Zurückschreibung in temporäre Speichervariablen zu kopieren.

MT-Vorfall

Kurzzusammenfassung

Am 10. März 2026 wurde MT Token, ein deflationäres Token auf der BNB Chain, ausgenutzt, was zu einem Verlust von ~242.000 $ führte. Die Ursache ist eine fehlerhafte Handelsbeschränkungslogik in Kombination mit einer inkonsistenten Behandlung von Sonderbedingungen bei Transfers. Während der Deflationsphase beschränkt der Vertrag Kaufvorgänge, wenn der Pool-Reservebestand einen festen Schwellenwert überschreitet. Der Vertrag behandelt jedoch Transfers exakter Beträge (z. B. 2e17 MT) als Referral-Bindungsaktionen, wodurch der Angreifer die Kaufbeschränkung umgehen und anfängliche Tokens erwerben konnte. Zusätzlich beruht die Beschränkungslogik auf unvollständiger Pfad-Erkennung (isBuy) und deckt indirekte Swap-Routen wie Pair-zu-Router nicht ab, während Whitelist-Prüfungen kritische Validierungen zusätzlich außer Kraft setzen (Short-Circuit). Der Angreifer sammelte MT-Tokens an, ohne Beschränkungen oder Gebühren auszulösen, manipulierte pendingBurnAmount über kontrollierte Liquiditätsoperationen und Trades und zwang den Pool in einen abnormalen Zustand, in dem der Token-Preis künstlich aufgebläht wurde.

Hintergrund

MT Token ist ein deflationäres Token auf der BNB Chain mit integrierten Handelsbeschränkungen. Während der Deflationsphase blockiert der Vertrag Kaufvorgänge, wenn die MT-Reserve im Pool 21.000e18 übersteigt. Sobald die Reserve unter diesen Schwellenwert fällt, endet die Deflationsphase und der Kauf wird wieder aktiviert. MT Token beinhaltet auch einen Referral-Mechanismus: Ein Transfer von genau 2e17 MT oder 1e17 MT wird als Referral-Bindungsaktion behandelt und nicht als normaler Handel.

Schwachstellenanalyse

Die Ursache lag in einem fehlerhaften Design der Kaufbeschränkung im MT-Vertrag (0x037E...b449). Unter normalen Bedingungen sollten Angreifer während der Beschränkungsphase kein MT als Startkapital erwerben können. Der Vertrag behandelt jedoch einen Transfer von genau 2e17 MT als Referral-Bindungsaktion statt als Kauf, was es einem Angreifer ermöglicht, 2e17 MT zu erwerben und dabei die Kaufbeschränkung zu umgehen.

Zusätzlich stützt sich die Handelsbeschränkung auf den isBuy-Zweig, um Käufe zu blockieren, deckt aber den Pfad "Pair zu Router" nicht ab. Da sowohl Router als auch Pair Whitelist-Adressen sind, werden solche Transfers bei der Whitelist-Prüfung kurzgeschlossen und erreichen nie die Kaufbeschränkungslogik, wodurch ein Angreifer MT erwerben kann, indem er Käufe über den Router leitet und anschließend Tokens durch Entfernen von Liquidität an sich selbst zurückführt.

Angriffsanalyse

Die folgende Analyse basiert auf der Transaktion 0xfb57...fca6.

  • Schritt 1: Der Angreifer nahm per Flash-Darlehen ~358.681e18 WBNB auf.

  • Schritt 2: Der Angreifer kaufte 2e17 MT, wodurch er die Kaufbeschränkung umging.

  • Schritt 3: Der Angreifer stellte 4e12 WBNB und 2e17 MT dem Pair zur Verfügung, um Liquidität hinzuzufügen. Dieser Transfer umging aus demselben Grund wie oben die Gebührenlogik.

  • Schritt 4: Der Angreifer kaufte ~10.000.000e18 MT-Tokens vom Pair an den Router, wodurch sowohl die Kaufbeschränkung als auch die Gebührenlogik umgangen wurden.

  • Schritt 5: Der Angreifer entfernte die Hälfte seiner Liquiditätsposition, wodurch alle vom Router gehaltenen MT-Tokens entnommen wurden, und verkaufte anschließend das zurückgewonnene MT gegen WBNB. In diesem Schritt wurde pendingBurnAmount auf etwa 9.000.000e18 manipuliert.

  • Schritt 6: Der Angreifer kaufte erneut ~10.000.000e18 MT-Tokens, wodurch die MT-Reserve des Pools auf ~6.756.516e18 gedrückt wurde, was niedriger war als pendingBurnAmount.

  • Schritt 7: Der Angreifer entfernte die verbleibende Hälfte seiner Liquiditätsposition, hob die gekauften MT-Tokens ab und rief dann distributeDailyRewards() auf, um MT aus dem Pool zu verbrennen. Dadurch wurde die MT-Reserve auf 21.000e18 reduziert.

  • Schritt 8: Der Angreifer tauschte alle MT-Tokens zurück gegen ~1.198e18 WBNB, zahlte das Flash-Darlehen zurück und realisierte den Gewinn.

Fazit

Dieser Exploit wurde durch fehlerhafte Handelsbeschränkungen verursacht, die es dem Angreifer ermöglichten, das Kaufverbot durch den Kauf von genau BINDING_AMOUNT an MT-Tokens zu umgehen. Nachdem der Angreifer MT-Tokens erhalten hatte, konnte er sowohl die Gebührenlogik als auch die Kaufbeschränkung umgehen, indem er zunächst Liquidität hinzufügte, dann MT in den Router kaufte und schließlich Liquidität entfernte, um die Tokens zurückzuerhalten. Der Angreifer akkumulierte anschließend pendingBurnAmount durch Verkaufsoperationen und führte den Burn aus, um die Pool-Reserven in einen abnormalen Zustand zu versetzen, wodurch er MT zu einem aufgeblähten Preis verkaufen und Gewinn erzielen konnte.

Um ähnliche Risiken künftig zu reduzieren:

  • Erzwingen Sie eine strikte Trennung zwischen Transfer-Semantik und Handelslogik.

AAVE-Liquidations-Vorfall

Kurzzusammenfassung

Am 11. März 2026 erlitt AAVE fehlerhafte Liquidationen im Wert von 21 Mio. $ auf Ethereum, was zu einem Verlust von ~1,01 Mio. $ führte. Die Ursache war ein fehlerhafter Oracle-Preis für wstETH, der dazu führte, dass ursprünglich gesunde Positionen unterbesichert wurden. Infolgedessen wurden die Positionen der Nutzer liquidiert, was zu finanziellen Verlusten führte.

Hintergrund

AAVE verwendet Oracle-Adapter, um verpackte Vermögenswerte wie wstETH zu bepreisen. Der Adapter CAPO (Capped Price Oracle) leitet den wstETH-Preis ab, indem er den Basis-ETH/USD-Preis mit einem Umrechnungsverhältnis multipliziert (getRatio(), d. h. wie viel ETH ein wstETH wert ist). Um Manipulationen des Verhältnisses zu verhindern, wendet CAPO eine snapshot-basierte Wachstumsobergrenze an:

maxRatio = snapshotRatio + maxGrowthPerSecond x (currentTime - snapshotTimestamp)

und begrenzt die Ausgabe von getRatio() bei der Preisbildung (wenn currentRatio > maxRatio, wird maxRatio verwendet). Dieser Mechanismus begrenzt effektiv die maximale Aufwärtsdrift des Verhältnisses und des daraus resultierenden Preises.

Schwachstellenanalyse

Die Ursache war eine Zeit-Verhältnis-Diskrepanz in der Anker-Konfiguration des CAPO-Oracles (0xe1D9...61Ef): Der Snapshot-Zeitstempel und das Snapshot-Verhältnis wurden gesetzt, aber das Snapshot-Verhältnis war unter dem tatsächlichen wstETH/ETH-Verhältnis konfiguriert. Dadurch fiel die vom Adapter berechnete maxRatio unter das aktuelle Verhältnis und begrenzte getRatio() nach unten, was den wstETH/USD-Oracle-Preis systematisch unterbewertete. Diese gedrückte Sicherheitenbewertung reduzierte den Health-Faktor von Positionen, die wstETH als Sicherheit verwendeten, wodurch eigentlich gesunde Konten fälschlicherweise als ungesund eingestuft und liquidiert wurden.

Angriffsanalyse

Die folgende Analyse basiert auf der Transaktion 0x9064...8a9c.

  • Schritt 1: Der Liquidator nahm per Flash-Darlehen ~6304e18 WETH auf und liquidierte den Kreditnehmer.

  • Schritt 2: Der Liquidator zahlte das Flash-Darlehen zurück und schloss die Liquidation ab.

Fazit

Diese Liquidation wurde durch eine fehlerhafte Oracle-Preiskonfiguration verursacht, die Kreditnehmer, die eigentlich gesund geblieben wären, fälschlicherweise in einen ungesunden Zustand versetzte und dadurch die Liquidation ihrer Positionen auslöste.

Um ähnliche Risiken künftig zu reduzieren:

  • Stellen Sie sicher, dass kritische Parameter vor jeder Aktualisierung auf ihre Korrektheit geprüft werden.

  • Fügen Sie in der Implementierung Validierungsprüfungen hinzu, um fehlerhafte Parameter abzulehnen und zu verhindern, dass falsche Konfigurationen erfolgreich angewendet werden.


Planet Finance-Vorfall

Kurzzusammenfassung

Am 11. März 2026 wurde Planet Finance auf der BNB Chain ausgenutzt, was zu einem geschätzten Verlust von ~10.000 $ führte. Die Ursache war, dass das Protokoll fälschlicherweise Erhöhungen des gespeicherten Kreditguthabens eines Kreditnehmers als aufgelaufene Zinsen behandelte, wodurch ein Angreifer wiederholt Kredite aufnehmen und die Rabattabrechnung auslösen konnte, um seine erfasste Schuld zu untertreiben.

Hintergrund

Planet Finance ist ein Kreditprotokoll, das es Kreditnehmern erlaubt, mit einem Zinsrabatt zurückzuzahlen. Der Rabatt ist gestaffelt und wird durch das Verhältnis zwischen dem gestakten GAMMA eines Nutzers und seinem gestakten Wert in anderen Vermögenswerten bestimmt: Je höher dieses Verhältnis, desto höher der Rückzahlungsrabatt. Der Rabattplan umfasst drei Stufen, die von 0% (Minimum) bis 50% (Maximum) reichen.

Schwachstellenanalyse

Die Ursache war, dass das Protokoll (0x4c9E...F467) bei der Abrechnung des Rabatts eines Kreditnehmers in changeUserBorrowDiscount() fälschlicherweise die Erhöhung des gespeicherten Kreditguthabens des Kreditnehmers als neu aufgelaufene Zinsen behandelte. Dadurch wurde der eigentlich nur für aufgelaufene Zinsen vorgesehene Rabatt fälschlicherweise auf das neu geliehene Kapital angewendet, was die erfasste Schuld des Kreditnehmers unzulässig verringerte. Ein Angreifer konnte die Schleife aus borrow und anschließendem changeUserBorrowDiscount wiederholt ausführen, um übermäßige Rabatte anzuhäufen, wodurch die on-chain erfasste Verbindlichkeit dauerhaft unter dem tatsächlich geliehenen Betrag lag, und schließlich von der Diskrepanz profitieren.

Angriffsanalyse

Die folgende Analyse basiert auf der Transaktion 0x5f45...5ec9.

  • Schritt 1: Der Angreifer nahm per Flash-Darlehen 200.000e18 USDT auf.

  • Schritt 2: Der Angreifer nutzte 5.000e18 USDT, um WBNB zu kaufen, und verwendete dann das erworbene WBNB, um ~8.726.524e18 GAMMA zu kaufen.

  • Schritt 3: Der Angreifer stakte zunächst das gesamte erworbene GAMMA in den gGAMMA-Markt, stellte dann das verbleibende USDT als Sicherheit bereit, was seinen Rückzahlungsrabatt auf 5% erhöhte und weitere Kreditaufnahme ermöglichte.

  • Schritt 4: Der Angreifer rief wiederholt borrow und dann updateUserDiscount auf, um seine erfasste Schuld kontinuierlich zu reduzieren.

  • Schritt 5: Der Angreifer zahlte schließlich die Schuld zurück, löste die Sicherheit ein und realisierte den Gewinn.

Fazit

Dieser Vorfall wurde durch die fehlerhafte Rabattabrechnungslogik von Planet Finance in changeUserBorrowDiscount() verursacht, die fälschlicherweise die Erhöhung des gespeicherten Kreditguthabens eines Kreditnehmers als neu aufgelaufene Zinsen behandelt und den Zinsrabatt auf diese Differenz anwendet. Ein Angreifer kann wiederholt borrow gefolgt von updateUserDiscount aufrufen, um seine erfasste Schuld zu untertreiben und schließlich weniger als die tatsächliche Verbindlichkeit zurückzuzahlen, um Gewinn zu erzielen.

Um ähnliche Risiken künftig zu reduzieren:

  • Unterscheiden Sie im Kreditprotokoll zwischen Zinsen und neuen Krediten.

AM-Vorfall

Kurzzusammenfassung

Am 12. März 2026 wurde AM Token, ein deflationäres Token auf der BNB Chain, ausgenutzt, mit einem geschätzten Verlust von ~131.000 $. AM Token implementiert einen deflationären Mechanismus, bei dem jeder Verkauf einen zusätzlichen Burn aus dem Liquiditätspool auslöst, wodurch Tokens dauerhaft entfernt werden, um das Gesamtangebot zu reduzieren. Der Burn wird jedoch nicht sofort ausgeführt - stattdessen wird der vollständige Verkaufsbetrag als toBurnAmount erfasst, und der eigentliche Burn wird auf den nächsten Verkauf verschoben. Diese Verzögerung schafft ein Zeitfenster zwischen Erfassung und Ausführung, in dem ein Angreifer AM zurückkaufen kann, um die AM-Reserve des Pools bis auf toBurnAmount zu schrumpfen. Wenn der nächste Verkauf den verzögerten Burn auslöst, wird die gesamte AM-Reserve vollständig aufgebraucht, was den Preis auf ein extremes Niveau treibt und es dem Angreifer ermöglicht, AM gewinnbringend zu verkaufen.

Hintergrund

AM Token ist ein deflationäres Token auf der BNB Chain. Bei jedem Verkauf erfasst der Vertrag den am Swap beteiligten AM-Betrag als toBurnAmount und verbrennt diesen erfassten Betrag beim nächsten Verkauf aus dem Liquiditätspool. Effektiv lösen Verkäufe einen verzögerten Burn aus, der die AM-Reserve des Pools schrumpfen lässt. Zusätzlich tauscht das Protokoll vor der Ausführung des Burns das aufgelaufene totalTokenFee in USDT um und verteilt es gemäß seiner Gebührenverteilungslogik.

Schwachstellenanalyse

Die Ursache war, dass die Verkaufslogik des Tokens (0x27f9...213f) den vollständigen getauschten AM-Betrag als toBurnAmount akkumuliert und den Burn erst beim nächsten Verkauf ausführt, indem Tokens aus dem AM/USDT-Pair entfernt und pair.sync() aufgerufen wird, um die Reserven zu aktualisieren. Dieses Design ermöglicht es einem Angreifer, die AM-Reserven des Pools zu manipulieren, den On-Chain-Preis zu verzerren und über Arbitrage zu profitieren.

Angriffsanalyse

Die folgende Analyse basiert auf der Transaktion 0xd0d1...f859.

  • Schritt 1: Der Angreifer nahm per Flash-Darlehen ~27.265.119e18 USDC und ~361.710e18 WBNB auf und tauschte diese dann in ~100.423.811e18 USDT um.

  • Schritt 2: Der Angreifer tauschte ~5.062e18 AM-Tokens gegen USDT, wodurch das vom Vertrag erfasste toBurnAmount auf ~4.303e18 manipuliert wurde.

  • Schritt 3: Der Angreifer tauschte USDT gegen AM Token, wodurch die AM-Reserve des Pools auf ~4.303e18 gedrückt wurde.

  • Schritt 4: Der Angreifer überwies 6 wei AM an den Pool und löste dadurch die Verkaufspfad-Burn-Logik aus. Infolgedessen verbrannte der Vertrag das gesamte AM-Guthaben aus dem Pool, wodurch die AM-Reserve auf 0 gedrückt wurde. Hinweis: Das Protokoll versucht zunächst, die aufgelaufenen Gebühren vor dem Burn in USDT umzutauschen. Dieser Gebührenumtausch-Pfad löst ebenfalls die Verkaufszweig-Burn-Logik aus. Nachdem der Burn ausgeführt wurde und die AM-Reserve 0 erreicht, schlägt der Gebührentausch fehl. Da dieser in ein try/catch eingebettet ist, führt der Fehlschlag nicht zu einem Revert der Transaktion. Stattdessen wird die Ausführung fortgesetzt und der Gebührenakkumulator auf 0 zurückgesetzt.

  • Schritt 5: Der Angreifer rief pool.sync() auf und überwies das verbleibende USDT sowie 1 wei AM an den Pool. Da beide Tokens gleichzeitig überwiesen wurden, behandelte der Vertrag dies als addLiquidity, sodass toBurnAmount nicht akkumuliert wurde. Die AM-Reserve wurde auf 7 aktualisiert.

  • Schritt 6: Der Angreifer tauschte die verbleibenden AM-Tokens gegen USDT. Während dieses Swaps löste die Übertragung von AM an das Pair die Verkaufspfad-Burn-Logik aus, wodurch die AM-Reserve auf 1 reduziert wurde. Da totalFeeAmount zudem in Schritt 4 auf 0 zurückgesetzt worden war, wurde die Gebühr-zu-USDT-Umwandlung nicht mehr ausgeführt, sodass der Angreifer AM zu einem künstlich aufgeblähten Preis verkaufen konnte.

  • Schritt 7: Der Angreifer zahlte das Flash-Darlehen zurück und realisierte den verbleibenden Gewinn.

Fazit

Dieser Vorfall wurde durch den fehlerhaften Burn-Mechanismus von AM Token verursacht, der den bei jedem Verkauf am Swap beteiligten AM-Betrag als toBurnAmount akkumuliert und diesen Betrag dann beim nächsten Verkauf aus dem AM/USDT-Pair verbrennt, während gleichzeitig pool.sync() aufgerufen wird. Dies ermöglicht es einem Angreifer, die AM-Reserven des Pairs auf ein extremes Niveau zu manipulieren und AM zu einem künstlich aufgeblähten Preis zu verkaufen, um USDT abzuziehen.

Um ähnliche Risiken künftig zu reduzieren:

  • Begrenzen Sie den maximalen Burn-Betrag pro Transaktion und beschränken Sie die Häufigkeit, mit der der Burn ausgelöst werden kann, um zu verhindern, dass Angreifer einen großen Teil der Token-Reserven des Pools innerhalb kurzer Zeit verbrauchen.

DBXen-Vorfall

Kurzzusammenfassung

Am 12. März 2026 wurde DBXen, ein Burn-to-Earn-Protokoll auf Ethereum und der BNB Chain, ausgenutzt, mit einem Gesamtverlust von ~149.000 $. Die Ursache war eine Inkonsistenz zwischen _msgSender() und msg.sender. Wenn burnBatch() über den forwarder aufgerufen wird, wird der verbrannte XEN-Betrag unter _msgSender() (vom Angreifer kontrolliert) erfasst, aber die Zyklus-Datensätze werden unter msg.sender (dem forwarder) aktualisiert. Diese Aufspaltung ermöglicht es dem Angreifer, Belohnungen und Gebühren gegen veraltete Zyklus-Datensätze zu beanspruchen, was zu ungewöhnlich hohen Auszahlungen führt.

Hintergrund

DBXen ist ein Burn-to-Earn-Protokoll: Nutzer verbrennen XEN-Tokens im Austausch für DXN-Belohnungen und einen Anteil an den angesammelten Protokollgebühren. Der Kernmechanismus arbeitet in Zyklen. Wenn ein Nutzer burnBatch() aufruft, passieren zwei Dinge: (1) Der verbrannte XEN-Betrag wird unter der Adresse des Aufrufers erfasst (identifiziert durch _msgSender()), und (2) der XEN-Vertrag ruft über onTokenBurned() in DBXen zurück, um die Zyklus-Datensätze des Aufrufers (Burn-Zyklus und lastFeeUpdateCycle) auf den aktuellen Zyklus zu aktualisieren.

Belohnungen und Gebühren werden über updateStats() abgerechnet. Die Belohnung ist proportional zum Anteil des Nutzers am gesamten verbrannten XEN in seinem Burn-Zyklus. Die Gebühr basiert auf den kumulativen Protokollgebühren, die seit dem letzten erfassten Zyklus des Nutzers angefallen sind. Beide Berechnungen hängen davon ab, dass die Zyklus-Datensätze des Nutzers aktuell sind.

Schwachstellenanalyse

Die Ursache ist eine fehlerhafte Geschäftslogik im DBXen-Protokoll (0xf5c8...2abd). Die Funktion _msgSender() prüft, ob msg.sender der forwarder ist. Wenn ja, gibt sie die letzten 20 Bytes von calldata zurück, und dieser zurückgegebene Wert kann im forwarder-Kontext beliebig kontrolliert werden. burnBatch() verbrennt jedoch direkt das von msg.sender gehaltene XEN. Dadurch kann ein Angreifer burnBatch() über den forwarder aufrufen, was dazu führt, dass das Protokoll das vom forwarder gehaltene XEN verbrennt und sowohl den Burn-Zyklus-Datensatz als auch den Gebührenaktualisierungs-Zyklus-Datensatz des forwarder auf den aktuellen Zyklus aktualisiert. Gleichzeitig erfasst das Protokoll jedoch den verbrannten XEN-Betrag unter der Adresse, die _msgSender() entspricht.

Danach ruft der Angreifer claimFees() auf, was updateStats() aufruft. Da die Zyklus-Datensätze der _msgSender()-Adresse nie aktualisiert wurden (sowohl Burn-Zyklus als auch lastFeeUpdateCycle bleiben bei 0), berechnet updateStats() Belohnungen im aktuellen Zyklus und berechnet Gebühren, die seit Zyklus 0 angefallen sind - über die gesamte Gebührenhistorie des Protokolls hinweg. Der Angreifer profitiert dann, indem er claimFees() und claimRewards() aufruft.

Angriffsanalyse

Die folgende Analyse basiert auf der Transaktion 0x914a5a...b808bc37.

  • Schritt 1: Der Angreifer rief zunächst die Funktion registerDomainSeparator() des Forwarder-Vertrags auf, wodurch nachfolgende Aufrufe von Forwarder.execute() ermöglicht wurden.

  • Schritt 2: Der Angreifer tauschte 0,14e18 ETH in einem Uniswap-V2-Pool gegen 13.900.000.000e18 XEN.

  • Schritt 3: Der Angreifer überwies 13.900.000.000e18 XEN an den Forwarder-Vertrag.

  • Schritt 4: Der Angreifer nutzte Forwarder.execute(), um DBXen zu genehmigen, die vom Forwarder gehaltenen 13.900.000.000e18 XEN auszugeben.

  • Schritt 5: Der Angreifer nutzte Forwarder.execute(), um DBXen.burnBatch() aufzurufen, und verbrannte 13.900.000.000e18 XEN. Der Burn-Betrag wurde unter der Adresse 0x425D3eC2DCeBE2c04bA1687504D43AFC6be7328d erfasst, während während der Burn-Ausführung XEN über onTokenBurned() in DBXen zurückrief und die relevanten Zyklus-Datensätze für den Forwarder aktualisierte.

  • Schritt 6: Der Angreifer nutzte Forwarder.execute(), um DBXen.claimFees() aufzurufen, und erhielt 65,36e18 ETH.

  • Schritt 7: Der Angreifer nutzte Forwarder.execute(), um DBXen.claimRewards() aufzurufen, und prägte 2.305,4e18 DXN.

Fazit

Die Ursache dieses Vorfalls war, dass das DBXen-Protokoll _msgSender() und msg.sender inkonsistent verwendete. Da sich diese beiden Werte unterscheiden konnten, wurde die interne Buchhaltung des Protokolls inkonsistent, was es dem Angreifer ermöglichte, die Diskrepanz zu Gewinnzwecken auszunutzen.

Um ähnliche Risiken künftig zu reduzieren:

  • Verwenden Sie _msgSender() konsistent in allen Logikpfaden, oder stellen Sie sicher, dass Operationen, die von msg.sender abhängen, und Buchhaltung, die von _msgSender() abhängt, immer auf dieselbe Adresse verweisen.

Goose Finance-Vorfall

Kurzzusammenfassung

Am 15. März 2026 wurde Goose Finance, ein Yield-Farming-Protokoll auf der BNB Chain, für etwa 8.000 $ ausgenutzt. Die Ursache war ein Fehler in der Reihenfolge der Anteilspreisbildung in StrategyGooseEgg: deposit() prägt Anteile, bevor geerntete Belohnungen in die Buchhaltung eingerechnet werden, sodass der für die Anteilspreisbildung verwendete Gesamtvermögensnenner diese Belohnungen ausschließt und niedriger als der tatsächliche Wert ist. Das bedeutet, dass Einleger mehr Anteile erhalten, als sie sollten. Wenn withdraw() aufgerufen wird, löst es eine Belohnungsernte aus, die das Gesamtvermögen erhöht, wodurch jeder Anteil mehr wert ist. Durch wiederholtes Einzahlen und Abheben innerhalb einer einzigen Transaktion prägte der Angreifer wiederholt überteuerte Anteile und löste sie zum korrigierten (höheren) Wert ein, wodurch er die Differenz als Gewinn abschöpfte.

Hintergrund

Goose Finance ist ein Yield-Farming-Protokoll auf der BNB Chain, bei dem Nutzergelder von einem Vault in eine Strategie fließen, die Vermögenswerte in MasterChef einsetzt, um EGG-Belohnungen zu verdienen.

Die für diesen Vorfall relevanten Komponenten sind:

  • VaultChef (0x3f64...): verfolgt Nutzerpositionen und leitet Kapital an StrategyGooseEgg weiter.

  • StrategyGooseEgg (0x0980...): führt die Buchhaltung auf Strategieebene mit sharesTotal und wantLockedTotal.

  • MasterChef (0xe70e...): erhält gestakte Vermögenswerte und zahlt EGG-Belohnungen aus.

  • WrappedEgg (0xb815...): verpackt EGG 1:1 in WEGG zum Staken.

Operativ werden Einzahlungen von VaultChef an StrategyGooseEgg weitergeleitet und dann in MasterChef gestakt. Abhebungen werden von VaultChef initiiert und von der Strategie ausgeführt.

Eine wichtige buchhalterische Erwartung ist, dass die Anteilspreisbildung das Gesamtvermögen der Strategie zum Zeitpunkt der Preisbildung widerspiegeln sollte (gestaktes Kapital plus inaktive, bereits von der Strategie gehaltene Belohnungen). In StrategyGooseEgg prägt deposit() jedoch Anteile, bevor _farm() inaktive Vermögenswerte in wantLockedTotal einrechnet, während withdraw() eine Belohnungsernte von MasterChef auslösen kann. Diese Reihenfolge ist die Grundlage der im Folgenden analysierten Schwachstelle.

Schwachstellenanalyse

Die Ursache ist eine buchhalterische Desynchronisation in StrategyGooseEgg (0x0980...b26b) zwischen Belohnungsernte und Anteilspreisbildung.

In StrategyGooseEgg verwendet die Anteilspreisbildung wantLockedTotal als Nenner: shares = deposit * sharesTotal / wantLockedTotal. Damit dies fair ist, muss wantLockedTotal alle Vermögenswerte widerspiegeln, die die Strategie tatsächlich hält, einschließlich aller inaktiven EGG-Belohnungen, die sich im Vertrag befinden. deposit() prägt jedoch Anteile, bevor _farm() inaktive Belohnungen in wantLockedTotal einrechnet. Das bedeutet, dass der Nenner unverbuchte Belohnungen ausschließt und niedriger als das tatsächliche Gesamtvermögen ist, wodurch der Einleger mehr Anteile erhält, als er sollte.

Darüber hinaus ruft withdraw() MasterChef.withdraw() auf, was gestaktes Kapital plus ausstehende EGG-Belohnungen an die Strategie zurückgibt. Die Buchhaltung der Strategie zieht nur den angeforderten _wantAmt von wantLockedTotal ab, sodass die geernteten Belohnungen im Guthaben der Strategie verbleiben, ohne sich in wantLockedTotal widerzuspiegeln. Dies vergrößert die Lücke zwischen den tatsächlich gehaltenen Vermögenswerten und dem erfassten wantLockedTotal, wodurch jede nachfolgende Anteilspreisbildung bei deposit() noch ungenauer wird.

Angriffsanalyse

Die folgende Analyse basiert auf der Transaktion 0x86efdf...ce316223.

  • Schritt 1: Der Angreifer leiht sich per Flash-Swap EGG von zwei Pancake-Pairs.

  • Schritt 2: Erste Einzahlung in VaultChef/StrategyGooseEgg (10.170.000e18 EGG).

  • Schritt 3: Erste Abhebung (12.593.884e18 EGG) erntet Belohnungen von MasterChef; 359.561e18 EGG werden an StrategyGooseEgg überwiesen und verbleiben als inaktiver/unverbuchter Wert (R > 0).

  • Schritt 4: Zweite Einzahlung nutzt das abgehobene Kapital erneut (12.593.884e18 EGG). Anteile werden bepreist, bevor der inaktive Wert eingerechnet wird, sodass dies der Übermäßig-Präge-Schritt ist.

  • Schritt 5: Zweite Abhebung (12.826.027e18 EGG) realisiert Gewinn aus übermäßig geprägten Anteilen (d. h. 232.143 EGG über dem Einzahlungsbetrag aus Schritt 4).

  • Schritt 6: Der Angreifer zahlt die Flash-Swaps zurück und behält die Netto-Differenz.

Fazit

Der Exploit resultiert aus einem Fehler in der Reihenfolge der Anteilspreisbildung in StrategyGooseEgg: deposit() prägt Anteile, bevor _farm() wantLockedTotal aktualisiert, während withdraw() Belohnungen von MasterChef ernten kann, die vorübergehend inaktiv und unverbucht bleiben. Dies ermöglicht es, dass Einzahlungen gegen einen veralteten Nenner geprägt werden und spätere Abhebungen gegen aktualisierte Vermögenswerte erfolgen.

Um ähnliche Risiken künftig zu reduzieren:

  • Rechnen Sie Belohnungen ab und aktualisieren Sie die Buchhaltung, bevor sowohl Anteilsprägung als auch Anteilsverbrennung berechnet werden.

  • Bepreisen Sie Anteile gegen ein einziges totalAssets (gestakt + inaktiv) genau zum Berechnungszeitpunkt.

  • Fügen Sie Invarianztests für shares_minted <= D * S / (A + R) unter Bedingungen mit von null verschiedenen inaktiven Belohnungen hinzu.


Über BlockSec

BlockSec ist ein Full-Stack-Anbieter für Blockchain-Sicherheit und Krypto-Compliance. Wir entwickeln Produkte und Dienstleistungen, die Kunden helfen, Code-Audits durchzuführen (einschließlich Smart Contracts, Blockchain und Wallets), Angriffe in Echtzeit abzufangen, Vorfälle zu analysieren, illegale Gelder zurückzuverfolgen und AML/CFT-Verpflichtungen zu erfüllen - über den gesamten Lebenszyklus von Protokollen und Plattformen hinweg.

BlockSec hat mehrere Fachartikel zur Blockchain-Sicherheit auf renommierten Konferenzen veröffentlicht, mehrere Zero-Day-Angriffe auf DeFi-Anwendungen gemeldet, mehrere Hacks blockiert, um mehr als 20 Millionen Dollar zu retten, und Kryptowährungen im Milliardenwert abgesichert.

Wöchentlicher Web3-Sicherheitsvorfälle-Überblick | 9. – 15. März 2026