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:
- Zeile 237: Zahlung von
targetCharge(die vollständige Energie des Ziel-NFT) als direkte ETH-Überweisung an den Verteidiger. Die Energie ist damit verbraucht. - 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% vonenergyOf(targetId)aufruft. Dies ist der erste Aufruf von_dissipateEnergyIntoPool(), und er liest einen veralteten Wert, da Schritt 5 noch nicht stattgefunden hat. - Zeile 241: Expliziter Aufruf von
_dissipateEnergyIntoPool(sourceSpent). Dies ist der zweite Aufruf, der Teil der normalen Spiellogik ist. - Zeilen 244-251: Aktualisierung von
energyBalancesfür sowohlsourceIdals auchtargetId.
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.700WETHper Flash-Loan. -
Schritt 2: Präge zwei neue Freaker, Token
590und Token591, 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
591zurü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
496bis520werden jeweils für0,278052246002402082Ether entladen. -
Schritt 7: Wandle das entzogene Ether in
WETHum, zahle das1.700WETHFlash-Darlehen zurück und behalte etwa7,498WETHals 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:
- Das aktuelle Kreditguthaben des Kreditnehmers (
currentBorrowBalance_TargetUnderwaterAsset). - Die maximale Rückzahlung, die die Sicherheiten des Kreditnehmers nach Anwendung des Liquidationsabschlags decken können (
calculateDiscountedBorrowDenominatedCollateral()). - Der Rückzahlungsbetrag, der erforderlich ist, um das Konto zurück an die Liquidationsgrenze zu bringen (
calculateDiscountedRepayToEvenAmount()), nur geprüft, wenn der MarktisSupportedist.


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
51e18WETHvon Balancer auf. -
Schritt 2: Der Angreifer wandelt
51e18WETHinETHum und stellt es dem Alkemi-Protokoll bereit. -
Schritt 3: Der Angreifer leiht sich
39,5e18ETHvon Alkemi. -
Schritt 4: Der Angreifer liquidiert seine eigene Position mit
39,5395e18ETH. -
Schritt 5: Der Angreifer hebt
93,5e18ETHvon Alkemi ab. -
Schritt 6: Der Angreifer zahlt das Flash-Darlehen zurück und erzielt einen Gewinn von
43,4e18ETH.

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.681e18WBNBauf. -
Schritt 2: Der Angreifer kaufte
2e17MT, wodurch er die Kaufbeschränkung umging. -
Schritt 3: Der Angreifer stellte
4e12WBNBund2e17MTdem 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.000e18MT-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ückgewonneneMTgegenWBNB. In diesem Schritt wurdependingBurnAmountauf etwa9.000.000e18manipuliert.
-
Schritt 6: Der Angreifer kaufte erneut
~10.000.000e18MT-Tokens, wodurch dieMT-Reserve des Pools auf~6.756.516e18gedrückt wurde, was niedriger war alspendingBurnAmount.
-
Schritt 7: Der Angreifer entfernte die verbleibende Hälfte seiner Liquiditätsposition, hob die gekauften
MT-Tokens ab und rief danndistributeDailyRewards()auf, umMTaus dem Pool zu verbrennen. Dadurch wurde dieMT-Reserve auf21.000e18reduziert.
-
Schritt 8: Der Angreifer tauschte alle
MT-Tokens zurück gegen~1.198e18WBNB, 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
~6304e18WETHauf 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.000e18USDTauf. -
Schritt 2: Der Angreifer nutzte
5.000e18USDT, umWBNBzu kaufen, und verwendete dann das erworbeneWBNB, um~8.726.524e18GAMMAzu kaufen. -
Schritt 3: Der Angreifer stakte zunächst das gesamte erworbene
GAMMAin den gGAMMA-Markt, stellte dann das verbleibendeUSDTals Sicherheit bereit, was seinen Rückzahlungsrabatt auf 5% erhöhte und weitere Kreditaufnahme ermöglichte. -
Schritt 4: Der Angreifer rief wiederholt
borrowund dannupdateUserDiscountauf, 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.119e18USDCund~361.710e18WBNBauf und tauschte diese dann in~100.423.811e18USDTum. -
Schritt 2: Der Angreifer tauschte
~5.062e18AM-Tokens gegenUSDT, wodurch das vom Vertrag erfasstetoBurnAmountauf~4.303e18manipuliert wurde.
-
Schritt 3: Der Angreifer tauschte
USDTgegen AM Token, wodurch dieAM-Reserve des Pools auf~4.303e18gedrückt wurde.
-
Schritt 4: Der Angreifer überwies
6 weiAMan den Pool und löste dadurch die Verkaufspfad-Burn-Logik aus. Infolgedessen verbrannte der Vertrag das gesamteAM-Guthaben aus dem Pool, wodurch dieAM-Reserve auf 0 gedrückt wurde. Hinweis: Das Protokoll versucht zunächst, die aufgelaufenen Gebühren vor dem Burn inUSDTumzutauschen. Dieser Gebührenumtausch-Pfad löst ebenfalls die Verkaufszweig-Burn-Logik aus. Nachdem der Burn ausgeführt wurde und dieAM-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 verbleibendeUSDTsowie1 weiAMan den Pool. Da beide Tokens gleichzeitig überwiesen wurden, behandelte der Vertrag dies als addLiquidity, sodasstoBurnAmountnicht akkumuliert wurde. DieAM-Reserve wurde auf 7 aktualisiert.

-
Schritt 6: Der Angreifer tauschte die verbleibenden
AM-Tokens gegenUSDT. Während dieses Swaps löste die Übertragung vonAMan das Pair die Verkaufspfad-Burn-Logik aus, wodurch dieAM-Reserve auf 1 reduziert wurde. DatotalFeeAmountzudem in Schritt 4 auf 0 zurückgesetzt worden war, wurde die Gebühr-zu-USDT-Umwandlung nicht mehr ausgeführt, sodass der AngreiferAMzu 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()desForwarder-Vertrags auf, wodurch nachfolgende Aufrufe vonForwarder.execute()ermöglicht wurden. -
Schritt 2: Der Angreifer tauschte
0,14e18ETHin einem Uniswap-V2-Pool gegen13.900.000.000e18XEN. -
Schritt 3: Der Angreifer überwies
13.900.000.000e18XENan denForwarder-Vertrag. -
Schritt 4: Der Angreifer nutzte
Forwarder.execute(), um DBXen zu genehmigen, die vomForwardergehaltenen13.900.000.000e18XENauszugeben. -
Schritt 5: Der Angreifer nutzte
Forwarder.execute(), umDBXen.burnBatch()aufzurufen, und verbrannte13.900.000.000e18XEN. Der Burn-Betrag wurde unter der Adresse0x425D3eC2DCeBE2c04bA1687504D43AFC6be7328derfasst, während während der Burn-AusführungXENüberonTokenBurned()inDBXenzurückrief und die relevanten Zyklus-Datensätze für denForwarderaktualisierte.
-
Schritt 6: Der Angreifer nutzte
Forwarder.execute(), umDBXen.claimFees()aufzurufen, und erhielt65,36e18ETH. -
Schritt 7: Der Angreifer nutzte
Forwarder.execute(), umDBXen.claimRewards()aufzurufen, und prägte2.305,4e18DXN.
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 vonmsg.senderabhä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 anStrategyGooseEggweiter. -
StrategyGooseEgg(0x0980...): führt die Buchhaltung auf Strategieebene mitsharesTotalundwantLockedTotal. -
MasterChef(0xe70e...): erhält gestakte Vermögenswerte und zahltEGG-Belohnungen aus. -
WrappedEgg(0xb815...): verpacktEGG1:1 inWEGGzum 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
EGGvon zwei Pancake-Pairs. -
Schritt 2: Erste Einzahlung in
VaultChef/StrategyGooseEgg(10.170.000e18EGG). -
Schritt 3: Erste Abhebung (
12.593.884e18EGG) erntet Belohnungen vonMasterChef;359.561e18EGGwerden anStrategyGooseEggüberwiesen und verbleiben als inaktiver/unverbuchter Wert (R > 0). -
Schritt 4: Zweite Einzahlung nutzt das abgehobene Kapital erneut (
12.593.884e18EGG). Anteile werden bepreist, bevor der inaktive Wert eingerechnet wird, sodass dies der Übermäßig-Präge-Schritt ist. -
Schritt 5: Zweite Abhebung (
12.826.027e18EGG) realisiert Gewinn aus übermäßig geprägten Anteilen (d. h.232.143EGGü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.
-
Offizielle Website: https://blocksec.com/
-
Offizieller Twitter-Account: https://twitter.com/BlockSecTeam



