Back to Blog

Wöchentliche Web3 Sicherheitsvorfall-Übersicht | 9. – 15. März 2026

March 18, 2026
21 min read

In der vergangenen Woche (09.03.2026 - 15.03.2026) hat BlockSec acht Angriffsvorfälle erkannt und analysiert, mit geschätzten Gesamtschäden von ca. 1,66 Mio. $. Die folgende Tabelle fasst diese Vorfälle zusammen, und detaillierte Analysen für jeden Fall sind in den folgenden Unterabschnitten aufgeführt.

Datum Vorfall Typ Geschätzter Schaden
09.03.2026 EtherFreakers Incident Fehlerhafte Geschäftslogik ~$25K
10.03.2026 Alkemi Incident Fehlerhafte Geschäftslogik ~$89K
10.03.2026 MT Incident Fehlerhafte Geschäftslogik ~$242K
11.03.2026 AAVE Liquidation Incident Fehlkonfiguration ~$1,01M
11.03.2026 Planet Finance Incident Fehlerhafte Geschäftslogik ~$10K
12.03.2026 AM Incident Fehlerhafte Geschäftslogik ~$131K
12.03.2026 DBXen Incident Fehlerhafte Geschäftslogik ~$149K
15.03.2026 Goose Finance Incident Fehlerhafte Geschäftslogik ~$8K

EtherFreakers Incident

Kurze Zusammenfassung

Am 9. März 2026 wurde EtherFreakers, ein NFT-Spiel auf Ethereum, aufgrund einer fehlerhaften Doppelzählung ausgenutzt, was zu einem Verlust von ca. 25.000 $ führte. Jedes NFT im Spiel enthält ein abhebbares ETH-Guthaben (genannt "Energie"). Als Spielmechanik können Spieler attack() verwenden, um ein NFT ein anderes erfassen zu lassen und die Energie des Ziels zu beanspruchen. Der Vertrag zahlt jedoch das Guthaben des Ziels aus und überträgt das NFT, bevor er seine Buchhaltung abschließt. Ein Transfer-Hook liest dann 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 Ausnutzer schleifte diesen Erfassungsmechanismus, um den globalen Index aufzublähen, und zog dann das aufgeblähte Guthaben von einer Charge von NFTs ab.

Hintergrund

EtherFreakers ist ein On-Chain-NFT-Spiel, bei dem jedes NFT (ein "Freaker" genannt) ein abhebbares ETH-Guthaben namens energy enthält. Das System funktioniert wie ein Dividendenpool: Wenn bestimmte Aktionen stattfinden, wird ein Bruchteil von ETH proportional an alle Freaker verteilt. Das abrufbare ETH jedes Freakers wird von einem globalen Akkumulator freakerIndex in Kombination mit einem Token-spezifischen Anteilgewicht fortune verfolgt.

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

Schwachstellenanalyse

Die Hauptursache ist eine falsche Ausführungsreihenfolge im EtherFreak-Vertrag (0x3A27...c0f33). Wenn eine Erfassung erfolgreich ist, führt die Funktion attack() die folgenden Schritte in dieser Reihenfolge aus:

  1. Zeile 237: Zahlt targetCharge (die volle Energie des Ziel-NFTs) direkt per ETH-Überweisung an den Verteidiger. Die Energie ist nun verbraucht.
  2. Zeile 240: Ruft _transfer(defender, capturer, targetId) auf, um das NFT zu verschieben. 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: Ruft explizit _dissipateEnergyIntoPool(sourceSpent) auf. Dies ist der zweite Aufruf, der Teil der normalen Spiellogik ist.
  4. Zeilen 244-251: Aktualisiert energyBalances sowohl für sourceId als auch für targetId.

Der Fehler liegt in Schritt 2: Da energyBalances[targetId] noch nicht aktualisiert wurde, sieht der Hook immer noch das Guthaben vor der Auszahlung und leitet einen Teil der bereits ausgegebenen Energie in den Dividendenpool. Die direkte ETH-Auszahlung in Schritt 1 und die Pool-Einleitung in Schritt 2 entnehmen beide die gleiche Energie, wodurch der freakerIndex ohne neue ETH-Deckung aufgebläht wird.

freakerIndex wächst jedes Mal, wenn _dissipateEnergyIntoPool() aufgerufen wird:

Angriffsanalyse

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

  • Schritt 1: Leihen von 1.700 WETH.

  • Schritt 2: Prägen von zwei neuen Freakers, Token 590 und 591, unter Adressen, die vom Angreifer kontrolliert werden.

  • Schritt 3: Wiederholtes Aufrufen der Spielfunktion attack(590, 591) und Beibehalten der Ausführungen im erfolgreichen Erfassungszweig.

  • Schritt 4: Nach jedem Erfolg wird Token 591 an den Helfer zurückübertragen, 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, werden eine Charge von zuvor kontrollierten Freakers entladen. Die Token-IDs 496 bis 520 werden jeweils für 0,278052246002402082 Ether entladen.

  • Schritt 7: Das abgezogene Ether wird in WETH umgewandelt, der Flash-Kredit von 1.700 WETH zurückgezahlt und etwa 7,498 WETH als Gewinn behalten.

Schlussfolgerung

Die Hauptursache liegt im erfolgreichen Erfassungsfluss von attack(): EtherFreakers zahlt targetCharge aus, bevor der Energiezustand des Zieltokens abgerechnet ist. _transfer() löst dann _beforeTokenTransfer() aus, das vor der Auszahlung liegende, veraltete energyOf(targetId) liest und einen Teil davon in den Pool verteilt. Dies erhöht den freakerIndex ohne neue Ether-Deckung, so dass die gleiche Zielenergie sowohl als Auszahlung als auch als Pool-Einzahlung gezählt wird. Dies ist ein Inflationsfehler in der Geschäftslogik, kein Reentrancy-Fehler.

Um ähnliche Risiken in Zukunft zu reduzieren:

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

  • Wenn der Übertragungs-Hook eine Zustandsvariable liest, stellen Sie sicher, dass die Ausführungsreihenfolge das Ergebnis nicht beeinflusst (z. B. den Zustand vor dem Hook abwickeln, nicht danach).


Alkemi Incident

Kurze Zusammenfassung

Am 10. März 2026 wurde das Alkemi-Protokoll auf Ethereum ausgenutzt, was zu einem Verlust von ca. 89.000 $ führte. Die Hauptursache ist ein Abrechnungsfehler und eine fehlerhafte Geschäftslogik. Die fehlerhafte Liquidierungslogik erlaubt es jedem, seine eigene Position innerhalb derselben Transaktion zu liquidieren und davon zu profitieren. Darüber hinaus führt ein Abrechnungsfehler dazu, dass die Kollateralreduzierung des Angreifers während der Liquidation überschrieben wird, was es dem Angreifer ermöglicht, Liquidierungsprämien zu erhalten, ohne die beabsichtigten Kosten zu tragen.

Hintergrund

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

  1. Der aktuelle Schuldenbetrag des Kreditnehmers (currentBorrowBalance_TargetUnderwaterAsset).
  2. Die maximale Rückzahlung, die die Kollateral des Kreditnehmers nach Anwendung des Liquidierungsrabatts abdecken kann (calculateDiscountedBorrowDenominatedCollateral()).
  3. Der Rückzahlungsbetrag, der erforderlich ist, um das Konto wieder auf die Liquidierungsgrenze zu bringen (calculateDiscountedRepayToEvenAmount()), geprüft nur, wenn der Markt isSupported ist.

Schwachstellenanalyse

Die Hauptursache ist eine fehlerhafte Geschäftslogik und ein Abrechnungsfehler im Alkemi-Protokoll (0x4822...a888). Da currentBorrowBalance_TargetUnderwaterAsset notwendigerweise größer als 0 ist, solange der Kreditnehmer eine ausstehende Schuld hat, und der von calculateDiscountedBorrowDenominatedCollateral() zurückgegebene Wert ebenfalls notwendigerweise größer als 0 ist, solange der Kreditnehmer eine Kollateral hat, verlässt sich das AlkemiEarnPublic-Protokoll effektiv auf calculateDiscountedRepayToEvenAmount(), um zu bestimmen, ob ein bestimmtes Darlehen liquidiert werden kann. In dieser Funktion sollte der zu liquidierende Schuldenbetrag anhand einer Variablen namens accountShortfall_TargetUser berechnet werden.

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

Darüber hinaus zeigt sich in der Funktion liquidateBorrow(), dass die Variablen supplyBalance_TargetCollateralAsset und supplyBalance_LiquidatorCollateralAsset auf denselben Speicherplatz verweisen, wenn der Liquidator und der Kreditnehmer dieselbe Adresse haben. Die Funktion berechnet dann separat ein "reduziertes Guthaben" und ein "belohntes Guthaben" basierend auf demselben Anfangsguthaben und schreibt sie anschließend nacheinander in denselben Speicherplatz zurück. Da das reduzierte Guthaben zuerst geschrieben und das belohnte Guthaben danach geschrieben wird, geht der Reduktionseffekt verloren und es bleibt nur das belohnte Ergebnis. Dies ermöglicht es dem Angreifer, seinen Gewinn weiter zu steigern.

Angriffsanalyse

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

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

  • Schritt 2: Der Angreifer wickelt 51e18 WETH in ETH ab und liefert ihn an das Alkemi-Protokoll.

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

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

  • Schritt 5: Der Angreifer zieht 93,5e18 ETH aus Alkemi ab.

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

Schlussfolgerung

Die Hauptursache ist, dass die fehlerhafte Liquidierungslogik es dem Angreifer ermöglicht, seinen eigenen Kredit aufzunehmen und dann innerhalb derselben Transaktion zu liquidieren, um einen Gewinn zu erzielen, während die fehlerhafte Abrechnungslogik die Gewinne des Angreifers weiter steigert.

Um ähnliche Risiken in Zukunft zu reduzieren:

  • Für Guthabenaktualisierungen des Kreditnehmers und des Liquidators sollte das Protokoll direkt auf Speichervariablen operieren, anstatt die Guthaben in temporäre Speicher-Variablen zu kopieren, um separate Berechnungen und Rückschreibungen durchzuführen.

MT Incident

Kurze Zusammenfassung

Am 10. März 2026 wurde MT Token, ein deflationärer Token auf der BNB Chain, ausgenutzt, was zu einem Verlust von ca. 242.000 $ führte. Die Hauptursache ist eine fehlerhafte Logik zur Einschränkung des Handels in Kombination mit inkonsistenter Handhabung spezieller Transferbedingungen. Während der Deflationsphase schränkt der Vertrag Kaufoperationen ein, wenn die Poolreserve einen festen Schwellenwert überschreitet. Der Vertrag behandelt jedoch Überweisungen exakter Beträge (z. B. 2e17 MT) als Empfehlung-bindende Aktionen, wodurch der Angreifer die Kaufbeschränkung umgehen und anfängliche Token erwerben kann. Darüber hinaus stützt sich die Beschränkungslogik auf eine unvollständige Pfaderkennung (isBuy) und deckt indirekte Swap-Routen wie Pair zu Router nicht ab, während Whitelist-Prüfungen kritische Validierungen weiter verkürzen. Der Angreifer sammelte MT-Token an, ohne Beschränkungen oder Gebühren auszulösen, manipulierte pendingBurnAmount durch kontrollierte Liquiditätsoperationen und Handelsgeschäfte und zwang den Pool in einen abnormalen Zustand, in dem der Tokenpreis künstlich aufgebläht war.

Hintergrund

MT Token ist ein deflationärer Token auf der BNB Chain mit integrierten Handelsbeschränkungen. Während der Deflationsphase blockiert der Vertrag Kaufoperationen, wenn die MT-Reserve im Pool 21.000e18 überschreitet. Sobald die Reserve unter diesen Schwellenwert fällt, endet die Deflationsphase und der Kauf wird wieder ermöglicht. MT Token enthält auch einen Empfehlungsmechanismus: eine Überweisung von genau 2e17 MT oder 1e17 MT wird als empfehlungsbindende Aktion und nicht als normaler Handel behandelt.

Schwachstellenanalyse

Die Hauptursache war ein fehlerhaftes Design der Kaufbeschränkung im MT-Vertrag (0x037E...b449). Unter normalen Bedingungen sollten Angreifer während der eingeschränkten Phase keine MT als Startkapital erwerben können. Der Vertrag behandelt jedoch eine Überweisung von genau 2e17 MT als Empfehlungsbindung und nicht als Kauf, was es einem Angreifer ermöglicht, 2e17 MT zu kaufen und dabei die Kaufbeschränkung zu umgehen.

Darüber hinaus stützt sich die Handelsbeschränkung auf den isBuy-Zweig, um Käufe zu blockieren, deckt aber nicht den "Pair to Router"-Pfad ab. Da sowohl der Router als auch das Paar Whitelist-Adressen sind, umgehen solche Überweisungen bei der Whitelist-Prüfung und erreichen nie die Kaufbeschränkungslogik, wodurch ein Angreifer MT erwerben kann, indem er Käufe an den Router leitet und anschließend Token durch Entfernen von Liquidität zurückzieht.

Angriffsanalyse

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

  • Schritt 1: Der Angreifer hat einen Flash-Kredit von ~358.681e18 WBNB aufgenommen.

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

  • Schritt 3: Der Angreifer lieferte 4e12 WBNB und 2e17 MT an das Paar, um Liquidität hinzuzufügen. Diese Überweisung umging aus demselben Grund wie oben die Gebührenlogik.

  • Schritt 4: Der Angreifer kaufte ~10.000.000e18 MT-Token vom Paar zum Router, umging damit sowohl die Kaufbeschränkung als auch die Gebührenlogik.

  • Schritt 5: Der Angreifer entfernte die Hälfte seiner Liquiditätsposition, zog dabei alle vom Router gehaltenen MT-Token ab und verkaufte dann die zurückgewonnenen MT gegen WBNB. In diesem Schritt wurde pendingBurnAmount auf etwa 9.000.000e18 manipuliert.

  • Schritt 6: Der Angreifer kaufte erneut ~10.000.000e18 MT-Token, wodurch die MT-Reserve des Pools auf ~6.756.516e18 gesenkt wurde, was unter pendingBurnAmount lag.

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

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

Schlussfolgerung

Dieser Exploit wurde durch fehlerhafte Handelsbeschränkungen verursacht, die es dem Angreifer ermöglichten, das Kaufverbot zu umgehen, indem er genau BINDING_AMOUNT von MT-Token kaufte. Nach dem Erhalt von MT-Token konnte der Angreifer weiter sowohl die Gebührenlogik als auch die Kaufbeschränkung umgehen, indem er zuerst Liquidität hinzufügte, dann MT in den Router kaufte und schließlich Liquidität entfernte, um die Token zurückzufordern. Der Angreifer sammelte dann pendingBurnAmount durch Verkaufsoperationen und führte den Burn aus, um die Poolreserven in einen abnormalen Zustand zu versetzen, wodurch er MT zu einem aufgeblähten Preis verkaufen und Gewinn erzielen konnte.

Um ähnliche Risiken in Zukunft zu reduzieren:

  • Erzwingen Sie eine strikte Trennung zwischen Transfersemantik und Handelslogik.

AAVE Liquidation Incident

Kurze Zusammenfassung

Am 11. März 2026 erlitt AAVE auf Ethereum 21 Millionen US-Dollar an fehlerhaften Liquidationen, was zu einem Verlust von ca. 1,01 Mio. $ führte. Die Hauptursache war ein fehlerhafter Oracle-Preis für wstETH, der dazu führte, dass ursprünglich gesunde Positionen unterbesichert wurden. Infolgedessen wurden die Positionen der Benutzer liquidiert, was zu finanziellen Verlusten führte.

Hintergrund

AAVE verwendet Oracle-Adapter, um gewickelte Assets wie wstETH zu bepreisen. Der Adapter CAPO (Capped Price Oracle) leitet den wstETH-Preis ab, indem er den Basispreis ETH/USD mit einem Umrechnungsverhältnis (getRatio(), d.h. wie viel ETH ein wstETH wert ist) multipliziert. Um eine Manipulation des Verhältnisses zu verhindern, wendet CAPO eine Snapshots-basierte Wachstumsbegrenzung an:

maxRatio = snapshotRatio + maxGrowthPerSecond x (currentTime - snapshotTimestamp)

und klemmt die Ausgabe von getRatio() während der Bepreisung ein (wenn currentRatio > maxRatio, wird maxRatio verwendet). Dieser Mechanismus begrenzt effektiv den maximalen Aufwärtsdruck des Verhältnisses und des daraus resultierenden Preises.

Schwachstellenanalyse

Die Hauptursache war ein Zeit-Verhältnis-Fehler in der CAPO-Oracle-Anchor-Konfiguration (0xe1D9...61Ef): Der Snapshot-Zeitstempel und das Snapshot-Verhältnis wurden gesetzt, aber das Snapshot-Verhältnis wurde unterhalb des tatsächlichen wstETH/ETH-Verhältnisses konfiguriert. Infolgedessen lag das vom Adapter berechnete maxRatio unter dem Live-Verhältnis und klemmte getRatio() nach unten ein, wodurch der wstETH/USD-Oracle-Preis systematisch unterbewertet wurde. Diese gedrückte Kollateralbewertung reduzierte den Gesundheitsfaktor von Positionen, die wstETH als Kollateral nutzten, wodurch ansonsten gesunde Konten fälschlicherweise als ungesund eingestuft und liquidiert wurden.

Angriffsanalyse

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

  • Schritt 1: Der Liquidator hat einen Flash-Kredit von ~6304e18 WETH aufgenommen und den Kreditnehmer liquidiert.

  • Schritt 2: Der Liquidator zahlte den Flash-Kredit zurück und schloss damit die Liquidation ab.

Schlussfolgerung

Diese Liquidation wurde durch eine fehlerhafte Oracle-Preis-Konfiguration verursacht, die Kreditnehmer, die gesund hätten bleiben sollen, fälschlicherweise in einen ungesunden Zustand versetzte und damit die Liquidation ihrer Positionen auslöste.

Um ähnliche Risiken in Zukunft zu reduzieren:

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

  • Fügen Sie Validierungsprüfungen in der Implementierung hinzu, um fehlerhafte Parameter abzulehnen und die Anwendung fehlerhafter Konfigurationen zu verhindern.


Planet Finance Incident

Kurze Zusammenfassung

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

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 Benutzers und seinem gestakten Wert in anderen Assets 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 Hauptursache war, dass das Protokoll (0x4c9E...F467) bei der Abrechnung des Kreditnehmer-Rabattes in changeUserBorrowDiscount() fälschlicherweise die Erhöhung des gespeicherten Kreditbetrags des Kreditnehmers als neu aufgelaufene Zinsen behandelte. Infolgedessen wurde der Rabatt, der nur für aufgelaufene Zinsen gelten sollte, fälschlicherweise auf das neu aufgenommene Kapital angewendet, wodurch die erfasste Schuld des Kreditnehmers ordnungswidrig reduziert wurde. Ein Angreifer konnte wiederholt die Schleife borrow und dann changeUserBorrowDiscount durchführen, um übermäßige Rabatte anzuhäufen, was dazu führte, dass die On-Chain erfasste Verbindlichkeit durchweg niedriger war als der tatsächlich aufgenommene Betrag, und letztendlich aus der Diskrepanz Profit zu schlagen.

Angriffsanalyse

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

  • Schritt 1: Der Angreifer hat einen Flash-Kredit von 200.000e18 USDT aufgenommen.

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

  • Schritt 3: Der Angreifer setzte zuerst das gesamte erworbene GAMMA in den gGAMMA-Markt, lieferte dann den verbleibenden USDT als Kollateral, was seinen Rückzahlungsrabatt auf 5 % erhöhte und die nachfolgende 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 Kollateral ein und realisierte den Gewinn.

Schlussfolgerung

Dieser Vorfall wurde durch die fehlerhafte Rabattabrechnungslogik von Planet Finance in changeUserBorrowDiscount() verursacht, die fälschlicherweise die Erhöhung des gespeicherten Kreditbetrags 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 unterschätzen und letztendlich weniger zurückzuzahlen als die tatsächliche Verbindlichkeit, um Profit zu ziehen.

Um ähnliche Risiken in Zukunft zu reduzieren:

  • Unterscheiden Sie Zinsen und neue Kredite im Kreditprotokoll.

AM Incident

Kurze Zusammenfassung

Am 12. März 2026 wurde AM Token, ein deflationärer Token auf der BNB Chain, mit einem geschätzten Verlust von ca. 131.000 $ ausgenutzt. AM Token implementiert einen deflationären Mechanismus, bei dem jeder Verkauf eine zusätzliche Verbrennung aus dem Liquiditätspool auslöst, wodurch Token dauerhaft entfernt werden, um das Gesamtangebot zu reduzieren. Die Verbrennung wird jedoch nicht sofort ausgeführt - stattdessen wird der gesamte Verkaufsbetrag als toBurnAmount erfasst und die tatsächliche Verbrennung 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 auf toBurnAmount zu reduzieren. Wenn der nächste Verkauf die verschobene Verbrennung auslöst, wird die gesamte AM-Reserve ausgelöscht, was den Preis auf ein extremes Niveau treibt und es dem Angreifer ermöglicht, AM gewinnbringend zu verkaufen.

Hintergrund

AM Token ist ein deflationärer Token auf der BNB Chain. Bei jedem Verkauf erfasst der Vertrag den am Tausch beteiligten AM-Betrag als toBurnAmount und verbrennt diesen erfassten Betrag während des nächsten Verkaufs aus dem Liquiditätspool. Effektiv lösen Verkäufe eine verzögerte Verbrennung aus, die die AM-Reserve des Pools schrumpfen lässt. Darüber hinaus tauscht das Protokoll, bevor es die Verbrennung ausführt, den angesammelten totalTokenFee in USDT und verteilt ihn gemäß seiner Gebührenallokationslogik.

Schwachstellenanalyse

Die Hauptursache war, dass die Verkaufslogik des Tokens (0x27f9...213f) den gesamten getauschten AM-Betrag als toBurnAmount ansammelt und die Verbrennung erst beim nächsten Verkauf durchführt, indem Token aus dem AM/USDT-Paar entfernt und pair.sync() aufgerufen werden, 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 durch Arbitrage Gewinn zu erzielen.

Angriffsanalyse

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

  • Schritt 1: Der Angreifer hat einen Flash-Kredit von ~27.265.119e18 USDC und ~361.710e18 WBNB aufgenommen und sie dann gegen ~100.423.811e18 USDT getauscht.

  • Schritt 2: Der Angreifer tauschte ~5.062e18 AM-Token gegen USDT, was den erfassten toBurnAmount des Vertrags auf ~4.303e18 manipulierte.

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

  • Schritt 4: Der Angreifer übertrug 6 wei AM an den Pool, was die Verkaufs-Pfad-Verbrennungslogik auslöste. Infolgedessen verbrannte der Vertrag den gesamten AM-Bestand aus dem Pool, wodurch die AM-Reserve auf 0 sank. Hinweis: Das Protokoll versucht zuerst, die angesammelten Gebühren in USDT zu tauschen, bevor die Verbrennung erfolgt. Dieser Gebührenumrechnungspfad löst ebenfalls die Verkaufs-Pfad-Verbrennungslogik aus. Nachdem die Verbrennung ausgeführt wurde und die AM-Reserve 0 erreicht, schlägt der Gebührentausch fehl. Da er in einem Try/Catch-Block eingekapselt ist, schlägt die Transaktion nicht fehl. Stattdessen wird die Ausführung fortgesetzt und der Gebührenakkumulator auf 0 zurückgesetzt.

  • Schritt 5: Der Angreifer rief pool.sync() auf und übertrug die verbleibenden USDT und 1 wei AM in den Pool. Da beide Token gleichzeitig übertragen wurden, behandelte der Vertrag dies als addLiquidity, so dass toBurnAmount nicht angesammelt wurde. Die AM-Reserve wurde auf 7 aktualisiert.

  • Schritt 6: Der Angreifer tauschte die verbleibenden AM-Token gegen USDT. Während dieses Tauschs löste die Übertragung von AM in das Paar die Verkaufs-Pfad-Verbrennungslogik aus und reduzierte die AM-Reserve auf 1. Da totalFeeAmount in Schritt 4 auf 0 zurückgesetzt worden war, wurde die Gebühr-zu-USDT-Konvertierung nicht mehr ausgeführt, wodurch der Angreifer AM zu einem künstlich aufgeblähten Preis verkaufen konnte.

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

Schlussfolgerung

Dieser Vorfall wurde durch den fehlerhaften Verbrennungsmechanismus von AM Token verursacht, der den von jedem Verkauf betroffenen AM-Betrag als toBurnAmount ansammelt und diesen Betrag dann beim nächsten Verkauf aus dem AM/USDT-Paar verbrennt, während pool.sync() aufgerufen wird. Dies ermöglicht es einem Angreifer, die AM-Reserven des Paares auf ein extremes Niveau zu manipulieren und AM zu einem künstlich aufgeblähten Preis zu verkaufen, um USDT abzuschöpfen.

Um ähnliche Risiken in Zukunft zu reduzieren:

  • Begrenzen Sie den maximalen Verbrennungsbetrag pro Transaktion und begrenzen Sie die Häufigkeit, mit der eine Verbrennung ausgelöst werden kann, um zu verhindern, dass Angreifer einen großen Teil der Token-Reserven des Pools in kurzer Zeit verbrauchen.

DBXen Incident

Kurze Zusammenfassung

Am 12. März 2026 wurde DBXen, ein Burn-to-Earn-Protokoll auf Ethereum und BNB Chain, mit einem Gesamtschaden von ca. 149.000 $ ausgenutzt. Die Hauptursache 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 Zykluserfassung wird auf msg.sender (dem forwarder) aktualisiert. Diese Trennung ermöglicht es dem Angreifer, Prämien und Gebühren gegen veraltete Zyklusdatensätze zu beanspruchen, was zu ungewöhnlich hohen Auszahlungen führt.

Hintergrund

DBXen ist ein Burn-to-Earn-Protokoll: Benutzer verbrennen XEN-Token im Austausch gegen DXN-Belohnungen und einen Anteil an angesammelten Protokollgebühren. Der Schlüsselmechanismus funktioniert in Zyklen. Wenn ein Benutzer burnBatch() aufruft, geschehen zwei Dinge: (1) der verbrannte XEN-Betrag wird unter der Adresse des Aufrufers (identifiziert durch _msgSender()) erfasst, und (2) der XEN-Vertrag ruft DBXen über onTokenBurned() zurück, um die Zyklusdatensä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 Benutzers am gesamten in seinem Burn-Zyklus verbrannten XEN. Die Gebühr basiert auf den kumulativen Protokollgebühren, die seit dem letzten erfassten Zyklus des Benutzers angefallen sind. Beide Berechnungen hängen davon ab, dass die Zyklusdatensätze des Benutzers auf dem neuesten Stand sind.

Schwachstellenanalyse

Die Hauptursache 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 gesteuert werden. Die Funktion burnBatch() verbrennt jedoch direkt das von msg.sender gehaltene XEN. Infolgedessen kann ein Angreifer burnBatch() über den forwarder aufrufen, wodurch das Protokoll das vom forwarder gehaltene XEN verbrennt und die Burn-Zyklus- und Gebühren-Update-Zyklusdatensätze 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 Zyklusdatensätze der _msgSender()-Adresse nie aktualisiert wurden (sowohl Burn-Zyklus als auch lastFeeUpdateCycle bleiben bei 0), berechnet updateStats() die Belohnungen im aktuellen Zyklus und berechnet die seit Zyklus 0 angefallenen Gebühren - die gesamte Gebührenhistorie des Protokolls abdeckend. 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 zuerst die Funktion registerDomainSeparator() des Forwarder-Vertrags auf und ermöglichte damit nachfolgende Aufrufe an Forwarder.execute().

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

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

  • Schritt 4: Der Angreifer nutzte Forwarder.execute(), um DBXen zu genehmigen, die 13.900.000.000e18 XEN des Forwarder 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() zurück in DBXen rief und die relevanten Zyklusdaten auf dem 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.

Schlussfolgerung

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

Um ähnliche Risiken in Zukunft zu reduzieren:

  • Verwenden Sie _msgSender() konsistent in allen Logikpfaden oder stellen Sie sicher, dass msg.sender-abhängige Operationen und _msgSender()-abhängige Buchhaltungen immer dieselbe Adresse referenzieren.

Goose Finance Incident

Kurze Zusammenfassung

Am 15. März 2026 wurde Goose Finance, ein Yield-Farming-Protokoll auf der BNB Chain, für etwa 8.000 $ ausgenutzt. Die Hauptursache war ein Fehler in der Share-Pricing-Reihenfolge in StrategyGooseEgg: deposit() prägt Shares, bevor die geernteten Erträge in die Buchhaltung übernommen werden, so dass der für das Share-Pricing verwendete Gesamtvermögensnenner diese Erträge ausschließt und niedriger ist als der tatsächliche Wert. Dies bedeutet, dass Einleger mehr Shares erhalten, als sie sollten. Wenn withdraw() aufgerufen wird, löst es eine Ertrags-Ernte aus, die das Gesamtvermögen erhöht und jeden Share wertvoller macht. Durch das Schleifen von Deposit und Withdraw in einer einzigen Transaktion prägte der Angreifer wiederholt überteuerte Shares und löste sie zum korrigierten (höheren) Wert ein, wobei die Differenz als Gewinn entnommen wurde.

Hintergrund

Goose Finance ist ein Yield-Farming-Protokoll auf der BNB Chain, bei dem Benutzergelder von einem Vault in eine Strategie fließen, die Assets im MasterChef staket, um EGG-Belohnungen zu verdienen.

Die für diesen Vorfall relevanten Komponenten sind:

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

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

  • MasterChef (0xe70e...): empfängt gestakte Assets und zahlt EGG-Belohnungen.

  • WrappedEgg (0xb815...): wickelt EGG 1:1 in WEGG zum Staking ein.

Operationell werden Einlagen vom VaultChef an StrategyGooseEgg geleitet, dann im MasterChef gestaket. Abhebungen werden vom VaultChef initiiert und von der Strategie ausgeführt.

Eine wichtige buchhalterische Erwartung ist, dass die Share-Preisgestaltung die Gesamtstrategie-Assets zum Zeitpunkt der Preisgestaltung widerspiegeln sollte (gestaktes Kapital plus im Ruhezustand befindliche Erträge, die bereits von der Strategie gehalten werden). In StrategyGooseEgg prägt deposit() jedoch Shares, bevor _farm() im Ruhezustand befindliche Erträge in wantLockedTotal verrechnet. withdraw() kann eine Ertrags-Ernte vom MasterChef auslösen. Diese Reihenfolge ist die Grundlage für die nachfolgend analysierte Schwachstelle.

Schwachstellenanalyse

Die Hauptursache ist eine Abrechnungsdesynchronisation in StrategyGooseEgg (0x0980...b26b) zwischen Ertrags-Ernte und Share-Preisgestaltung.

In StrategyGooseEgg verwendet die Share-Preisgestaltung wantLockedTotal als Nenner: shares = deposit * sharesTotal / wantLockedTotal. Damit dies fair ist, muss wantLockedTotal alle Assets widerspiegeln, die die Strategie tatsächlich hält, einschließlich aller im Ruhezustand befindlichen EGG-Erträge im Vertrag. deposit() prägt jedoch Shares, bevor _farm() im Ruhezustand befindliche Erträge in wantLockedTotal verrechnet. Dies bedeutet, dass der Nenner nicht erfasste Erträge ausschließt und niedriger ist als die tatsächlichen Gesamtvermögenswerte, wodurch der Einleger mehr Shares erhält, als er sollte.

Darüber hinaus ruft withdraw() MasterChef.withdraw() auf, was das gestakte Kapital zuzüglich ausstehender EGG-Erträge an die Strategie zurückgibt. Die Buchhaltung der Strategie zieht nur den angeforderten _wantAmt von wantLockedTotal ab, so dass die geernteten Erträge im Bestand der Strategie verbleiben, ohne in wantLockedTotal reflektiert zu werden. Dies vergrößert die Lücke zwischen den tatsächlich gehaltenen Assets und dem erfassten wantLockedTotal, wodurch jede nachfolgende deposit()-Share-Preisgestaltung noch ungenauer wird.

Angriffsanalyse

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

  • Schritt 1: Der Angreifer hat EGG aus zwei Pancake-Paaren per Flash-Kredit geliehen.

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

  • Schritt 3: Die erste Auszahlung (12.593.884e18 EGG) erntet Erträge vom MasterChef; 359.561e18 EGG werden an StrategyGooseEgg übertragen und bleiben als im Ruhezustand befindlicher/nicht erfasster Wert (R > 0).

  • Schritt 4: Die zweite Einzahlung verwendet das abgehobene Kapital (12.593.884e18 EGG) wieder. Shares werden bepreist, bevor der im Ruhezustand befindliche Wert verrechnet wird, dies ist also der Schritt der Überprägung.

  • Schritt 5: Die zweite Auszahlung (12.826.027e18 EGG) realisiert Gewinne aus überprägten Shares (d. h. 232.143 EGG über dem Einzahlungsbetrag von Schritt 4).

  • Schritt 6: Der Angreifer zahlte Flash-Swaps zurück und behielt die Netto-Differenz.

Schlussfolgerung

Der Exploit ergibt sich aus einem Fehler in der Share-Preisgestaltung in StrategyGooseEgg: deposit() prägt Shares, bevor _farm() wantLockedTotal aktualisiert, während withdraw() Erträge vom MasterChef ernten kann, die vorübergehend im Ruhezustand und nicht erfasst bleiben. Dies ermöglicht es Einzahlungen, gegen einen veralteten Nenner zu prägen und später gegen aktualisierte Vermögenswerte abzuheben.

Um ähnliche Risiken in Zukunft zu reduzieren:

  • Verrechnen Sie Erträge und aktualisieren Sie die Buchhaltung vor allen Berechnungen von Share-Mint und Share-Burn.

  • Bepreisen Sie Shares mit einer einzigen totalAssets (gestaket + im Ruhezustand) zum exakten Berechnungspunkt.

  • Fügen Sie Invariantentests für shares_minted <= D * S / (A + R) unter Bedingungen mit nicht-null Erträgen im Ruhezustand hinzu.


Über BlockSec

BlockSec ist ein Anbieter von Blockchain-Sicherheit und Krypto-Compliance aus einer Hand. Wir entwickeln Produkte und Dienstleistungen, die Kunden bei der Durchführung von Code-Audits (einschließlich Smart Contracts, Blockchain und Wallets), der Echtzeit-Abwehr von Angriffen, der Analyse von Vorfällen, der Rückverfolgung illegaler Gelder und der Erfüllung von AML/CFT-Verpflichtungen über den gesamten Lebenszyklus von Protokollen und Plattformen hinweg unterstützen.

BlockSec hat mehrere Blockchain-Sicherheitsarbeiten auf renommierten Konferenzen veröffentlicht, mehrere Zero-Day-Angriffe auf DeFi-Anwendungen gemeldet, mehrere Hacking-Angriffe blockiert, um mehr als 20 Millionen Dollar zu retten, und Milliarden von Kryptowährungen gesichert.

Sign up for the latest updates
Building a Secure Stablecoin Payment Network: BlockSec Partners with Morph
Partnership

Building a Secure Stablecoin Payment Network: BlockSec Partners with Morph

BlockSec has partnered with Morph as an official audit partner for the $150M Morph Payment Accelerator. By offering exclusive discounts on smart contract audits and penetration testing, BlockSec provides institutional-grade security to payment builders, ensuring a safe and resilient foundation for the future of global stablecoin payments.

Weekly Web3 Security Incident Roundup | Mar 9 – Mar 15, 2026
Security Insights

Weekly Web3 Security Incident Roundup | Mar 9 – Mar 15, 2026

This BlockSec weekly security report covers eight DeFi attack incidents detected between March 9 and March 15, 2026, across Ethereum and BNB Chain, with total estimated losses of approximately $1.66M. Incidents include a $1.01M AAVE incorrect liquidation caused by oracle misconfiguration, a $242K exploit on the deflationary token MT due to flawed trading restrictions, a $149K exploit on the burn-to-earn protocol DBXen from `_msgSender()` and `msg.sender` inconsistency, and a $131K attack on AM Token exploiting a flawed delayed-burn mechanism. The report provides detailed vulnerability analysis and attack transaction breakdowns for each incident.

Venus Thena (THE) Incident: What Broke and What Was Missed

Venus Thena (THE) Incident: What Broke and What Was Missed

On March 15, 2026, an attacker bypassed the THE (Thena) supply cap on Venus Protocol (BNB Chain) through a donation attack, inflating a collateral position to 3.67x the intended limit and borrowing ~$14.9M in assets. Both sides lost money on-chain: Venus was left with ~$2.15M in bad debt after 254 liquidation bots competed across 8,048 transactions, while the attacker retained only ~$5.2M against a $9.92M investment. This deep dive examines what broke across three lines of defense (exposure limits, collateral valuation, and liquidation) and the monitoring gaps that left months of on-chain warning signals unacted upon.