Back to Blog

Wöchentlicher Web3-Sicherheitsvorfall-Rundruf | 30. März – 5. April 2026

April 8, 2026
32 min read

Im vergangenen Jahr (30.03.2026 - 05.04.2026) hat BlockSec neun Angriffsereignisse erkannt und analysiert, mit geschätzten Gesamtschäden von ca. 287 Mio. $. Die folgende Tabelle fasst diese Vorfälle zusammen. Detaillierte Analysen für jeden Fall sind in den folgenden Unterabschnitten aufgeführt.

Datum Vorfall Typ Geschätzter Schaden
30.03.2026 Unbekannter Protokollvorfall Fehlerhafte Geschäftslogik ~10.000 $
30.03.2026 WDGG Token Vorfall Zugriffskontrolle ~40.000 $
31.03.2026 i6Token Vorfall Fehlerhafte Geschäftslogik ~273.800 $
01.04.2026 Drift Protocol Vorfall Phishing-Angriff ~285,3 Mio. $
01.04.2026 LML Staking Protocol Vorfall Fehlerhafte Geschäftslogik ~950.000 $
01.04.2026 Tactile Vorfall Preismanipulation ~12.000 $
02.04.2026 SAS Token Vorfall Fehlerhafte Geschäftslogik ~12.000 $
03.04.2026 Unbekannter EIP-7702 Vorfall Zugriffskontrolle ~17.200 $
03.04.2026 Silo Finance Vorfall Fehlkonfiguration ~359.000 $

1. Unbekannter Protokollvorfall

Kurze Zusammenfassung

Am 30. März 2026 verlor ein unbekanntes Protokoll auf der BNB Chain aufgrund fehlerhafter Geschäftslogik rund 10.000 $. Das Protokoll wies einen Teil der Einlagen von Benutzern zu, um seinen Plattform-Token PSTART zu kaufen und Liquidität hinzuzufügen, was bedeutet, dass die Benutzer effektiv LP-Positionen hielten, die Preisschwankungen auf dem Markt unterlagen. Beim Abheben rechnete das Protokoll jedoch nicht den tatsächlichen einlösbaren Wert der LP zu diesem Zeitpunkt ab. Stattdessen versprach es weiterhin einen festen Betrag an Stablecoins basierend auf der historischen Einlage und vordefinierten Regeln. Infolgedessen konnte der Angreifer nach der Kapitalbindung durch erzwungene Investitionen Gelder zu einem voreingestellten festen Wert abheben, wodurch Verluste, die eigentlich von der LP-Position hätten getragen werden müssen, auf das Protokoll verlagert wurden und letztendlich ein kostenloses Gewinn erzielt wurde.

Hintergrund

Das Protokoll funktioniert wie folgt: Nach einer Einlage von BUSD durch einen Benutzer verwendet das Protokoll automatisch einen Teil der Gelder, um PSTART zu kaufen, und kombiniert diesen dann mit dem verbleibenden BUSD, um Liquidität in den Pool einzubringen. Die resultierenden LP-Anteile werden dann vom Vault verwahrt, während das Protokoll in seinem internen Hauptbuch eine Anweisung für den Benutzer aufzeichnet, die eine feste tägliche Rendite verspricht.

Anschließend kann der Benutzer Belohnungen zu einem festen Zinssatz beanspruchen und beim Ausstieg rechnet der Vault das Kapital und die Rendite gemäß vordefinierten Regeln ab, anstatt streng nach dem aktuellen Nettoinventarwert der zugrunde liegenden LP-Position abzurechnen.

Schwachstellenanalyse

Diese Schwachstelle ergibt sich aus einem unangemessenen Protokolldesign (0x587984...73a43c): Die Abrechnungslogik ist vom tatsächlichen Wert der zugrunde liegenden Vermögenswerte entkoppelt.

Nachdem ein Benutzer BUSD eingezahlt hat, verwendet das Protokoll einen Teil davon, um PSTART zu kaufen und Liquidität hinzuzufügen. Das bedeutet, die tatsächliche zugrunde liegende Position des Benutzers ist eine LP-Exposition, deren Wert mit den Marktpreisen schwankt. Wenn der Benutzer jedoch aussteigt, rechnet das Protokoll nicht basierend auf dem tatsächlichen einlösbaren Wert der LP zu diesem Zeitpunkt ab. Stattdessen verspricht es weiterhin, eine feste Menge an Stablecoins gemäß dem historischen Einlagebetrag und vordefinierten Abrechnungsregeln zu zahlen.

Der Angreifer nutzte diesen Fehler aus, indem er einen Flash-Loan verwendete, um eine große Menge an Kapital zu erhalten, und dann wiederholt deposit() ausführte. Auf diese Weise zwang der Angreifer das Protokoll, kontinuierlich PSTART zu kaufen und die Vermögenszusammensetzung des Pools zu ändern, wodurch der PSTART-Preis künstlich in die Höhe getrieben und eine Arbitragemöglichkeit geschaffen wurde.

Der Angreifer führte dann withdraw() aus und löste Gelder zum voreingestellten festen Wert ein, wodurch die Verluste, die von der zugrunde liegenden LP-Position hätten getragen werden müssen, effektiv auf das Protokoll selbst übertragen wurden, was letztendlich zu einem kostenlosen Gewinn führte.

Angriffsanalyse

Die folgende Analyse basiert auf der Transaktion 0xf3b8...55e7.

  • Schritt 1: Der Angreifer erhielt durch einen Flash-Loan etwa 2.000.000e18 BUSD und tauschte diese im Pool gegen 19.013.120e18 PSTART.

  • Schritt 2: Der Angreifer rief wiederholt die deposit()-Funktion des Vertrags auf, um Gelder zu staken. Bei jeder Einzahlung berechnete das Protokoll, wie viel BUSD zum Kauf von Token verwendet werden sollte, damit das endgültige Token-zu-BUSD-Verhältnis für die Hinzufügung von Liquidität besser mit dem aktuellen Verhältnis des Pools übereinstimmt. Durch wiederholte Einzahlungen injizierte der Angreifer kontinuierlich BUSD in den Pool, während die Menge an PSTART nahezu unverändert blieb. Infolgedessen stieg der Wert von PSTART weiter an. In dieser Phase wurde die durch die Einzahlungen des Angreifers erhaltene LP tatsächlich mit Verlust erworben.

  • Schritt 3: Der Angreifer verkaufte dann den in Schritt 1 gekauften PSTART zurück in den Pool. Da Schritt 2 die BUSD-Reserven des Pools erhöht hatte, brachte dieser Tausch etwa 2.010.655e18 BUSD ein, was einem Gewinn von etwa 10.655 BUSD in einem einzigen Angriffszyklus entspricht.

  • Schritt 4: Schließlich führte der Angreifer withdraw() für alle in Schritt 2 eröffneten Staking-Positionen aus. Zu diesem Zeitpunkt war der Marktwert der Vermögenswerte, die diesen Positionen entsprachen, bereits weit unter ihrem ursprünglichen Einlagebetrag. Nach normaler wirtschaftlicher Logik wäre eine vollständige Rückerstattung nicht möglich gewesen. Das Protokoll berechnete jedoch den einlösbaren BUSD-Betrag basierend auf dem historischen Einlagebetrag, was es dem Angreifer ermöglichte, alle zuvor erzwungenen Investitionskosten vollständig zurückzuerhalten, ohne Verluste zu tragen.

Schlussfolgerung

Die Hauptursache dieses Vorfalls liegt darin, dass das Protokoll Benutzereinlagen in LP-Positionen investierte, die Marktschwankungen unterworfen waren, und dennoch eine Abrechnung in fester BUSD-Menge basierend auf historischen Einlagebeträgen und vordefinierten Regeln versprach. Dies führte zu einer Diskrepanz zwischen den Verbindlichkeiten des Protokolls und dem tatsächlichen Wert seiner zugrunde liegenden Vermögenswerte.

Der Angreifer nutzte diesen Fehler aus, indem er wiederholt deposit() verwendete, um die Vermögensstruktur des Pools zu verändern und den Preis von PSTART in die Höhe zu treiben, dann durch eine externe Position eine Arbitrage abschloss und schließlich withdraw() verwendete, um die zuvor verlustbringenden Positionen zum Buchwert einzulösen. Auf diese Weise wurden Verluste, die von den Positionen selbst hätten getragen werden müssen, auf das Protokoll verlagert, was letztendlich einen risikofreien Gewinn ermöglichte.


2. WDGG Token Vorfall

Kurze Zusammenfassung

Am 30. März 2026 wurde der WDGG-Token auf der BNB Chain ausgenutzt, was zu Verlusten von rund 40.000 $ führte. Die Hauptursache war das Fehlen einer Zugriffskontrolle in der Funktion burnFrom(). Insbesondere erlaubte die Funktion burnFrom(), dass beliebige Benutzer WDGG-Token von jeder beliebigen Adresse verbrennen konnten. Der Angreifer nutzte dies aus, indem er WDGG-Token aus dem PancakeSwap-Pool verbrannte, dann die Funktion sync() aufrief, um die WDGG-Reserven des Pools zu reduzieren, und anschließend einen umgekehrten Swap durchführte, um Profit zu erzielen.

Hintergrund

Dieser Vorfall betrifft einen einzelnen Token, WDGG, der ein dividendenverteilender Token ist, der bei jeder Übertragung eine Gebühr erhebt.

Schwachstellenanalyse

Der WDGG-Token-Vertrag (0x512de7...6b90c5) gab burnFrom() ohne jegliche Aufrufer-Autorisierung frei. Infolgedessen konnte jede Adresse WDGG-Token von jedem Halter verbrennen, einschließlich des PancakeSwap-Pools selbst. Gepaart mit dem öffentlich aufrufbaren sync() von PancakeSwap, das die aufgezeichneten Reserven mit den tatsächlichen Guthaben abgleicht, ermöglichte dieser Fehler, dass die WDGG-Reserve des Pools willkürlich reduziert und die Konstante des Produktinvariante gebrochen wurde, ohne dass ein legitimer Handel stattfand, wodurch der Pool Preisungleichgewichten ausgesetzt wurde.

Ein sekundärer Fehler in setWdgAddress() erlaubte es jedem Aufrufer, eine beliebige Adresse als gebührenbefreit zu markieren, was den durch diese Angriffsfläche extrahierbaren Gewinn weiter maximierte.

Angriffsanalyse

Die folgende Analyse basiert auf der Transaktion 0x2da5...0bd1.

  • Schritt 1: Der Angreifer rief zuerst setWdgAddress() auf, um seine eigene Adresse als gebührenbefreit zu setzen, was es nachfolgenden Übertragungen ermöglichte, die Gebühr des Tokens zu umgehen.
  • Schritt 2: Der Angreifer tauschte dann eine kleine Menge BNB gegen WDGG-Token über den PancakeSwap-Pool.

  • Schritt 3: Nach Erhalt von WDGG rief der Angreifer burnFrom() auf, um WDGG-Token direkt aus der PancakeSwap-Paaradresse zu verbrennen.

  • Schritt 4: Der Angreifer rief anschließend sync() auf, was das Paar zwang, seine Reserven anzupassen, um den manipulierten Token-Salden zu entsprechen. Infolgedessen wurde die WDGG-Reserve im Pool auf nur 1 Wei reduziert.

  • Schritt 5: Da die Poolreserven stark verzerrt waren, führte der Angreifer einen umgekehrten Swap durch und entnahm Profit aus dem Preisungleichgewicht.

Schlussfolgerung

Dieser Vorfall wurde letztendlich durch das Fehlen einer Zugriffskontrolle in der Funktion burnFrom() des WDGG-Token-Vertrags verursacht. Infolgedessen konnte ein Angreifer Token direkt aus dem PancakeSwap-Pool verbrennen, die Reserven des Pools über sync() manipulieren und das daraus resultierende Preisungleichgewicht gewinnbringend ausnutzen.


3. i6Token Vorfall

Kurze Zusammenfassung

Am 31. März 2026 verlor der i6-Token auf der BNB Chain rund 273.800 $, da invest() den Spotpreis des Pools verschob, während withdraw() Salden über einen nachlaufenden TWAP abwickelte, und die beiden in derselben Transaktion kombiniert werden konnten. Der Angreifer blähte den Spotpreis über invest() auf, löste überschüssiges i6 zum veralteten TWAP über withdraw() ein und verkaufte das i6 zurück in den aufgeblähten Pool, um Profit zu erzielen.

Hintergrund

Das Protokoll funktioniert wie folgt: Wenn ein Benutzer invest() aufruft, werden USDT eingezahlt und teilweise zum Kauf von i6 auf PancakeSwap verwendet. Das erworbene i6 wird zusammen mit den verbleibenden USDT als Liquidität in den USDT/i6-Pool eingebracht, und die resultierenden LP-Token werden verbrannt. Das Protokoll zeichnet Benutzer- und Empfehlungsbilanzen in USDT auf.

Wenn withdraw() aufgerufen wird, berechnet das Protokoll den aufgelaufenen Wert des Benutzers in USDT und wandelt ihn unter Verwendung eines vom Protokoll gepflegten TWAP-Preises (twapPrice) in i6 um.

Schwachstellenanalyse

Die Hauptursache im Protokollvertrag (0x1cb36b...2a18a) ist, dass invest() den Spotpreis des USDT/i6-Pools als Nebenwirkung des Kaufs von i6 und der Hinzufügung von Liquidität verändert, während withdraw() aufgelaufene, in USDT denominierte Salden unter Verwendung eines vom Protokoll gepflegten TWAP (twapPrice) in i6 abwickelt, der erst nach Ablauf eines Zeitfensters aktualisiert wird. Nichts im Vertrag verhindert, dass diese beiden Funktionen in derselben Transaktion ausgeführt werden.

Da ein invest()-Aufruf den Spotpreis innerhalb derselben Transaktion aufblähen kann, in der eine nachfolgende withdraw() einen noch nicht aktualisierten TWAP liest, sehen die beiden effektiv zwei unterschiedliche Preise für denselben Poolzustand. Ein durch withdraw() abgewickelter, in USDT denominierter Saldo wird dann zum veralteten, viel niedrigeren Preis in i6 ausgezahlt, obwohl jeder i6 jetzt im Pool selbst für weit mehr USDT realisierbar ist. Diese Lücke verwandelt jeden aufgelaufenen USDT-Saldo im Protokoll in eine ausnutzbare Spanne zwischen interner Abrechnung und dem Live-Pool.

Angriffsanalyse

Die folgende Analyse basiert auf der Transaktion 0xc1b9...2f16.

  • Schritt 1: Der Angreifer beschaffte sich zunächst 270.000 WBNB über einen Flash-Loan, hinterlegte diese dann als Sicherheit bei Venus und lieh sich eine große Menge USDT. Der Angreifer setzte auch den Angriffskontrakt A unter der Adresse 0xda49 und den Hilfskontrakt B unter der Adresse 0x096a ein.

  • Schritt 2: Der Angriffskontrakt führte die erste invest()-Operation aus. Während dieses Prozesses verwendete das Protokoll zunächst 531.489e18 USDT, um 234.188e18 i6 zu kaufen, und fügte dann 354.326e18 USDT zusammen mit 72.607e18 i6 in den Pool ein. Infolgedessen stieg der Pool-Spotpreis schnell von etwa 1,05159 USDT/i6 auf etwa 4,89287 USDT/i6, während der vom Protokoll erfasste TWAP bei nur 1,05159 blieb.

  • Schritt 3: Der Angreifer übertrug dann 124.014.184e18 USDT an den Hilfskontrakt B, der wiederum invest() mit referrer = A aufrief. Dieser Schritt zwang das Protokoll erneut, einen massiven USDT -> i6-Kauf und eine addLiquidity()-Operation durchzuführen, was die Poolreserven in einen neuen Zustand trieb, der einem Spotpreis von etwa 15.528 USDT/i6 entsprach. Da jedoch kein neues Zeitfenster verstrichen war, aktualisierte das Protokoll den TWAP nicht entsprechend.

  • Schritt 4: Nach Abschluss der zweiten invest()-Operation erhielt der Angriffskontrakt A als Empfehlungsgeber sofort Anspruch auf eine Empfehlungsprämie in USDT. Der Angreifer rief dann withdraw() auf. Das Protokoll verwendete den veralteten TWAP, um die auszuzahlende Menge an i6 zu berechnen und übertrug die Token aus seinem eigenen Guthaben, was zu einer Gesamtauszahlung von 5.896.508e18 i6 führte.

  • Schritt 5: Nach Erhalt des i6 rief der Angreifer sofort swapExactTokensForTokensSupportingFeeOnTransferTokens() auf, um alle 5.896.508e18 i6 zurück in den Pool zu verkaufen und dafür 125.177.224e18 USDT zu erhalten. Da diese i6-Token mit dem veralteten TWAP von etwa 1,05159 USDT/i6 abgerechnet worden waren, während sie gegen einen Pool-Spotpreis verkauft wurden, der vom Angreifer auf etwa 15.528 USDT/i6 hochgetrieben worden war, konnte der Angreifer die enorme Spanne zwischen den beiden Preisen direkt realisieren.

  • Schritt 6: Nach Rückzahlung des Flash-Loans behielt der Angreifer 273.802e18 USDT, was der tatsächliche Gewinn aus dem Angriff war.

Schlussfolgerung

Die Hauptursache liegt darin, dass eine Spotpreis-beeinflussende Funktion (invest()) und eine TWAP-abgerechnete Funktion (withdraw()) innerhalb einer einzigen Transaktion kombiniert werden konnten, wodurch die beiden unterschiedliche Preise für denselben Poolzustand sehen konnten.

Um diese Art von Fehler zu vermeiden, sollten Protokolle, die AMM-Interaktionen mit verzögerter Preisgestaltung kombinieren, es vermeiden, Salden zu einem TWAP in derselben Transaktion abzurechnen, in der eine Begleitfunktion den Spotpreis des zugrunde liegenden Pools verschiebt, und stattdessen Auszahlungen an den realisierbaren Live-Wert des Pools anstatt an einen veralteten oder abgeleiteten Preis anbinden.


4. Drift Protocol Vorfall

Kurze Zusammenfassung

Am 1. April 2026 (UTC) wurde das Drift Protocol auf Solana für rund 285,3 Mio. $ kompromittiert. Die Hauptursache war kein Smart-Contract-Bug, sondern ein Zusammenbruch des Multisig-Autorisierungsverfahrens, verschärft durch einen 2-von-5-Sicherheitsrat ohne Timelock und den Durable-Nonce-Mechanismus von Solana, der es erlaubte, vorab gesammelte Multisig-Genehmigungen bis zur Ausführung durch den Angreifer gültig zu bleiben. Nach wochenlanger Vorbereitung veranlasste der Angreifer zwei von fünf Unterzeichnern, bösartige Governance-Transaktionen, die an Durable-Nonce-Konten gebunden waren, vorab zu signieren, reichte sie später ein, um die Admin-Kontrolle zu übernehmen, führte dann ein gefälschtes Sicherheiten-Asset (CVT) ein, blähte dessen Oracle-Preis auf, lockerte die Auszahlungslimits und zog echte Vermögenswerte über den Drift Vault (JCNCMF...XJfrw) ab.

Hintergrund

Drift Protocol ist ein DeFi-Protokoll auf Solana, das Margin-Trading, Lending, Spotmärkte und Derivate unterstützt. Seine Vorgänge mit hohen Berechtigungen, einschließlich Admin-Änderungen, Markterstellung, Oracle-Konfiguration, Risikoparameter-Updates und Auszahlungslimit-Anpassungen, werden eher durch das Squads Multisig-Framework als durch einen einzelnen privaten Schlüssel gesteuert. Zum Zeitpunkt des Angriffs operierte der Sicherheitsrat von Drift unter einer 2-von-5-Schwellenkonfiguration ohne Timelock, was bedeutet, dass zwei von fünf Unterzeichnern administrative Aktionen mit sofortiger Wirkung autorisieren konnten. Die Sicherheit dieses Systems hängt nicht nur von der Verwahrung der Schlüssel der Unterzeichner ab, sondern auch von der Integrität der gesamten Genehmigungspipeline: Welche Transaktion wurde erstellt, welche Transaktionen glaubten die Unterzeichner zu genehmigen, und stimmten die endgültigen ausgeführten Anweisungen mit diesem Überprüfungskontext überein.

Separates dazu ersetzen die Durable-Nonce-Konten von Solana den kurzlebigen Blockhash durch eine persistente Nonce, die in einem dedizierten Konto gespeichert ist. Dies ermöglicht, dass eine signierte Transaktion bis zur Advancierung der Nonce unbegrenzt gültig bleibt. Dieser Mechanismus ist für legitime Anwendungsfälle wie Offline-Signierung und verzögerte Einreichung konzipiert, führt aber zu einem kritischen Angriffsprimitiv, indem er den Zeitpunkt der Signierung von dem Zeitpunkt der Ausführung auf der Kette trennt. Sobald ein Unterzeichner eine Durable-Nonce-Transaktion genehmigt, kann die Genehmigung nicht widerrufen werden, es sei denn, der Nonce-Autorisiert hat das Nonce-Konto manuell weitergeschaltet.

Schwachstellenanalyse

Die Hauptursache ist kein Smart-Contract-Bug, sondern drei strukturelle Schwächen in der Governance-Konfiguration von Drift, die zusammen eine Social-Engineering-Möglichkeit in einen Abfluss von 285,3 Mio. $ verwandelten. Erstens entfernten die Durable Nonces das implizite Signatur-Ablauf-Sicherheitsnetz. Bei normalen Blockhash-basierten Transaktionen wird die Genehmigung eines getäuschten Unterzeichners entweder umgehend ausgeführt oder läuft innerhalb eines engen Fensters harmlos ab, was den Spielraum für koordinierte Ausbeutung begrenzt. Durable Nonces lösen diese Einschränkung auf: Sobald zwei Unterzeichner des Sicherheitsrats dazu gebracht wurden, bösartige Governance-Transaktionen durch irreführende Signierungsanfragen zu genehmigen, blieben ihre Signaturen unbegrenzt ausnutzbar, was dem Angreifer die vollständige Kontrolle über den Ausführungszeitpunkt gab.

Zweitens bedeutete der Null-Timelock bei administrativen Aktionen, dass, sobald die vorab signierten Transaktionen eingereicht waren, die Admin-Übertragung sofort wirksam wurde, ohne dass ein Zeitfenster für Erkennung oder Intervention verblieb. Drittens war der Umfang der Admin-Rolle breit genug, um neue Sicherheitenmärkte zu schaffen, Oracle-Quellen zu wechseln und Auszahlungslimits zu lockern, alles innerhalb eines einzigen privilegierten Pfades. Eine erfolgreiche Governance-Übernahme reichte daher aus, um jedes beliebige Asset in eine echte Geldbeschaffung umzuwandeln, ohne weitere Genehmigungsbarrieren.

Angriffsanalyse

Der Angriff entfaltete sich in drei separaten Phasen: Pre-Attack Staging, in der der Angreifer eine mehrwöchige Operation durchführte, um ein gefälschtes Sicherheiten-Asset herzustellen und durch irreführende Signierungsanfragen Governance-Zugang zu erhalten; Governance Takeover, in der zwei vorab signierte Durable-Nonce-Transaktionen in schneller Folge eingereicht wurden, um die administrative Kontrolle zu übernehmen; und Fund Extraction, in der der Angreifer Protokollparameter manipulierte und echte Vermögenswerte über die Kreditvergabe-Pfade des Protokolls abzweigte. Das Diagramm unten veranschaulicht den Ausführungsfluss über diese drei Phasen hinweg.

  • Phase 1 (Pre-Attack Staging): Ab dem 11. März zog der Angreifer 10 ETH aus Tornado Cash ab und setzte den CarbonVote Token (CVT) ein, prägte 750 Millionen Einheiten, bot dann Liquidität auf Raydium an und nutzte Wash-Trading, um eine künstliche Preisgeschichte nahe 1 $ aufzubauen. Parallel dazu wurden bis zum 23. März vier Durable-Nonce-Konten erstellt, zwei davon mit Drift Security Council-Mitgliedern verknüpft und zwei vom Angreifer kontrolliert, was darauf hindeutet, dass mindestens zwei von fünf Unterzeichnern bereits Transaktionen im Zusammenhang mit Durable-Nonce-Konten signiert hatten. Am 27. März führte Drift aufgrund eines Mitgliederwechsels eine geplante Migration des Sicherheitsrats durch, die die zuvor gesammelten Signaturen ungültig machte; bis zum 30. März hatte der Angreifer jedoch die erforderliche Schwelle unter der neuen Konfiguration wieder erreicht, was eine aktive Überwachung der On-Chain-Governance-Änderungen und eine Echtzeit-Anpassung zeigte.

  • Phase 2 (Governance Takeover): Am 1. April um ca. 16:05 UTC, etwa eine Minute nachdem Drift eine legitime Testauszahlung aus dem Versicherungsfonds durchgeführt hatte, reichte der Angreifer zwei vorab signierte Durable-Nonce-Transaktionen vier Slots voneinander entfernt ein. Die erste Transaktion (2HvMSg...2C4H) erstellte und genehmigte den bösartigen Admin-Übertragungsantrag. Die zweite Transaktion (4BKBmA...RsN1) genehmigte und führte sie aus, beginnend mit AdvanceNonceAccount, um die gespeicherte Nonce zu aktivieren, über proposalApprove und vaultTransactionExecute bis hin zur Aufrufung von UpdateAdmin, um die administrative Kontrolle auf eine vom Angreifer kontrollierte Adresse zu übertragen.

  • Phase 3 (Fund Extraction): Mit voller Admin-Befugnis erstellte der Angreifer einen Sicherheitenmarkt für CVT, wechselte zu einem vom Angreifer kontrollierten Oracle, um dessen Buchpreis aufzublähen, und hob die Auszahlungslimits für wichtige Asset-Märkte an oder entfernte sie. Der Angreifer zahlte dann eine große Menge überbewertetes CVT in das Protokoll ein und führte 31 schnelle Auszahlungen über etwa 12 Minuten durch, wobei er USDC, JLP, SOL, cbBTC, USDT, wETH, dSOL, WBTC, JTO und FARTCOIN für einen Gesamtverlust von rund 285,3 Mio. $ abzweigte, berechnet auf Basis des vom Angreifer genutzten Kontos (HkGz4K...pZES).

Schlussfolgerung

Die Hauptursache dieses Vorfalls ist keine Smart-Contract-Schwachstelle oder Kompromittierung von Schlüsseln, sondern ein Zusammenbruch des Multisig-Autorisierungsverfahrens in Kombination mit einer Durable-Nonce-basierten verzögerten Ausführung und einem administrativen Pfad ohne Timelock. Vorab gesammelte Genehmigungen, die normalerweise innerhalb von Minuten abgelaufen wären, blieben auf unbegrenzte Zeit ausnutzbar, und sobald sie eingereicht wurden, hinterließen die Admin-Übernahme und die anschließende Geldbeschaffung kein Zeitfenster für Interventionen.

Die Minderung dieser Risikoklasse erfordert die Sicherung der gesamten Autorisierungspipeline anstelle nur der Schlüsselverwahrung der Unterzeichner, die Durchsetzung von Timelocks für Vorgänge mit hohen Berechtigungen und die Behandlung von verzögerten Ausführungsmechanismen wie Durable Nonces als eigenständige Bedrohungsoberfläche, die höhere Signaturschwellen, zeitgebundene oder widerrufbare Genehmigungen und Einschränkungen für unbegrenzt gültige signierte Transaktionen erfordert.


5. LML Staking Protocol Vorfall

Kurze Zusammenfassung

Am 1. April 2026 wurde das LML-Staking-Protokoll auf der BNB-Kette für rund 950.000 $ ausgenutzt. Die Hauptursache war eine Inkonsistenz in der Belohnungsberechnungslogik: Die Belohnungskonvertierung las einen gespeicherten LML/USDT-Preis, der hinter einer Aktualisierungssperre von 3600 Sekunden gesperrt war, während das ausgezahlte LML zum Live-AMM-Preis einlösbar war, ohne Abweichungsprüfung zwischen den beiden. Der Angreifer nutzte Flash-Loans, um den Pool-Spotpreis aufzublähen, und EIP-7702-Code-Delegation, um Belohnungen für 11 vorab gestakte EOAs in einer einzigen Transaktion zu stapeln, eine überhöhte Menge an LML zum veralteten gespeicherten Preis zu erhalten und diese dann über den nun stark verzerrten Pool zu verkaufen, um Profit zu erzielen.

Hintergrund

LML ist ein Staking-Protokoll auf der BNB-Kette, bei dem Benutzer BNB über den APower-Vertrag staken, um LML-Token als Belohnungen zu erhalten. Belohnungen werden in USDT-Begriffen berechnet und dann basierend auf einem vom Protokoll gespeicherten LML/USDT-Preis in LML-Beträge umgewandelt, bevor sie verteilt werden. Der gespeicherte Preis wird durch updatePrice() aktualisiert, das den AMM-Spotpreis liest, aber eine 3600-Sekunden-Sperre zwischen den Updates erzwingt. Belohnungsansprüche werden über APower's receive() basierend auf msg.sender ausgelöst, sodass nur die ursprüngliche Staking-Adresse ihre eigenen Belohnungen beanspruchen kann.

Schwachstellenanalyse

Der Kernfehler im Staking-Vertrag (0xbe9713...adce19) besteht darin, dass die Belohnungsakkumulation und die Belohnungseinlösung an zwei unterschiedliche Preise desselben Pools gebunden sind, ohne dass eine Konsistenzprüfung zwischen ihnen erfolgt. Die Belohnungsformel reward += (10^18 * base_reward) / stored_price berechnet die LML-Auszahlung aus _prices[], einem vom Protokoll gespeicherten LML/USDT-Preis, der nur durch updatePrice() nach einer 3600-Sekunden-Sperre aktualisiert wird, obwohl das ausgezahlte LML sofort zum Live-AMM-Spotpreis einlösbar ist. Jede externe Aktivität, die den Spotpreis innerhalb dieses Sperrfensters verschiebt, öffnet eine Lücke zwischen einer eingefrorenen Akkumulationspreis und einem Live-Verkaufspreis, und nichts im Vertrag lehnt einen Anspruch ab, wenn diese Lücke unangemessen wird.

Ein zweiter struktureller Fehler liegt darin, wie die Belohnungsquelle aufgefüllt wird. Wenn das LML-Guthaben des PROOF-Vertrags nicht ausreicht, um einen Anspruch zu bezahlen, füllt swapBack() es auf, indem es super._transfer(swapPair, PROOF, deficit) aufruft, gefolgt von sync(). Dabei wird LML direkt aus den Reserven des LP-Paares entnommen und der gespeicherte Zustand des Paares neu ausgerichtet, anstatt einen normalen Swap zu durchlaufen. Da dieser Pfad die Preisfindung des Paares umgeht, reduziert jeder Anspruch, der ihn auslöst, die LML-Reserven des Paares und verschiebt den Spotpreis weiter, ohne dass ein gegenläufiger Token-Zufluss stattfindet. Wiederholte Ansprüche vergrößern mechanisch die Lücke zwischen dem eingefrorenen gespeicherten Preis und dem Live-Verkaufspreis.

Angriffsanalyse

Die folgende Analyse basiert auf den Transaktionen 0x805d...5b47, 0x70f7...3572.

  • Schritt 1: Der Angreifer aggregierte eine große Menge USDT und WBNB durch Flash-Loans von Moolah, lieh sich von Venus und Moolah Pool (unter Verwendung von WBNB als Sicherheit) und Flash-Loans von PancakeSwap V4, mehreren V3-Pools und V2-Pools. Dieses Kapital wurde benötigt, um den Preis des LML/USDT-Paares zu manipulieren.

  • Schritt 2: Der Angreifer rief swapAndTrans() im LML-Token-Vertrag auf, der die im Vertrag angesammelten LML-Gebühren in USDT tauschte. Dies entzog dem LML-Vertrag sein eigenes LML-Guthaben, was bedeutete, dass er nicht mehr als lokaler Token-Lieferant dienen konnte. Jede nachfolgende normale Belohnungsverteilung müsste LML aus dem LP-Paar über swapBack() beziehen.

  • Schritt 3: Der Angreifer tauschte USDT gegen LML über PancakeRouter swapExactTokensForTokensSupportingFeeOnTransferTokens, wobei die Zieladresse auf die Nulladresse gesetzt wurde. Die gekauften LML-Token wurden verbrannt, anstatt vom Angreifer empfangen zu werden. Der alleinige Zweck war es, LML aus dem Paar zu entziehen und den LML-Preis am AMM aufzublähen; der Angreifer benötigte die Token selbst nicht, nur die Preisverzerrung.
  • Schritt 4: Der Angreifer hatte zuvor mit 11 EOA-Adressen in das Staking-Protokoll eingezahlt. Da APower's receive() _claimReward(msg.sender) basierend auf msg.sender auslöst, können Belohnungen nur von der einzahlenden Adresse selbst beansprucht werden. Um Belohnungen für alle 11 EOAs innerhalb einer einzigen Transaktion zu beanspruchen, nutzte der Angreifer EIP-7702, um Code auf diesen EOAs zu setzen, wodurch sie als Verträge vom Hauptvertrag des Angreifers aufgerufen werden konnten. Jeder EOA führte eine transfer(rst, fte)-Funktion aus, die eine kleine Menge BNB an APower sendete, was receive() und _claimReward(EOA) auslöste. Innerhalb jedes Anspruchs: updatePrice() wurde übersprungen (3600s-Sperre nicht erfüllt, daher blieb stored_price beim historischen niedrigen Wert), updateUser() berechnete die Belohnung unter Verwendung des veralteten niedrigen Preises, sendMining() übertrug LML von PROOF an APower und löste dann swapBack() aus, das PROOF auffüllte, indem es LML aus dem LP-Paar zog und sync() aufrief, wodurch die Reserven des Paares weiter reduziert wurden. Schließlich verteilte claimReward() LML an die EOA, und jede EOA übertrug ihre erhaltene LML zurück an den Angriffskontrakt.
  • Schritt 5: Der Angreifer tauschte die angesammelte LML über den nun stark ausgedünnten Pool zum extrem aufgeblähten Preis zurück in USDT.

  • Schritt 6: Rückzahlung aller Flash-Loans, Kredite und Gebühren. Überweisung des verbleibenden Gewinns.

Schlussfolgerung

Die Hauptursache ist eine Diskrepanz zwischen Belohnungsakkumulation und Einlösung im Staking-Vertrag: Auszahlungen werden aus einem gespeicherten LML/USDT-Preis berechnet, der hinter einer 3600-Sekunden-Sperre gesperrt ist, aber in LML abgerechnet wird, dessen realer Wert dem Live-AMM-Preis folgt, ohne Abweichungsprüfung zwischen den beiden. Der swapBack()-Nachfüllpfad verschärft diesen Fehler, indem er LML bei jedem Anspruch direkt aus dem LP-Paar entzieht und die Lücke zwischen dem eingefrorenen gespeicherten Preis und dem Live-Verkaufspreis mechanisch vergrößert, je mehr Ansprüche verarbeitet werden.

Staking-Protokolle, die Belohnungen aus AMM-abgeleiteten Preisen berechnen, sollten bei der Einlösung eine Abweichungsprüfung zwischen dem gespeicherten Preis und dem aktuellen Spotpreis erzwingen und rückgängig machen, wenn die Lücke einen sicheren Schwellenwert überschreitet. Sie sollten auch Nachfüllmechanismen vermeiden, die LP-Reserven außerhalb normaler Swap-Pfade verändern, da solche Mechanismen die Preisfindung umgehen, die andernfalls den Schaden durch veraltete Preisgestaltung begrenzen würde.


6. Tactile Vorfall

Kurze Zusammenfassung

Am 1. April 2026 erlitt Tactile, ein gestaffeltes Einlagenprotokoll auf Polygon, einen Verlust von rund 12.000 $. Die Hauptursache war eine Inkonsistenz in seiner Einzahlungs- und Auszahlungsabrechnungslogik: Sowohl der Ein- als auch der Ausstieg wurden zum aktuellen Spotpreis von CES abgerechnet, und der interne Anteil trug keine Aufzeichnung über den Wert des Vermögenswerts, zu dem er ursprünglich geprägt wurde. Der Angreifer nutzte dies aus, indem er den Spotpreis vor der Einzahlung aufblähte, um übermäßige Anteile zu erhalten, dann den Preis vor der Auszahlung senkte, um mehr CES pro Anteil einzulösen, und den Zyklus über Hilfskontrakte wiederholte, um Profit zu erzielen.

Hintergrund

Tactile ist ein gestaffeltes Einlagenprotokoll auf Polygon, bei dem Benutzer CES gemäß einer ausgewählten Stufe in einen Zahlungsvertrag einzahlen. Der erforderliche Einzahlungsbetrag wird aus dem aktuellen Spotpreis von CES und der Stufenkonfiguration berechnet, und der Benutzer erhält einen internen Buchhaltungsanteil, der seine Position darstellt. Bei der Auszahlung wird der aufgezeichnete Anteil anstelle der ursprünglichen Einzahlung in CES umgerechnet, sodass die Guthaben der Benutzer effektiv als preisabhängige Buchungseinheiten verfolgt werden und nicht als feste Vermögensbeträge.

Schwachstellenanalyse

Der Kernfehler im Zahlungsvertrag (0x9153e1...09b654) besteht darin, dass Ein- und Auszahlungen zu zwei verschiedenen Zeitpunkten gegen dasselbe Spotpreis-Oracle abgerechnet werden, ohne dass eine unveränderliche Verankerung sie verbindet. Zum Zeitpunkt der Einzahlung liest der Vertrag getActualPrice() und rechnet die eingezahlten CES basierend auf dem aktuellen Preis in einen internen Anteil um; zum Zeitpunkt der Auszahlung wird derselbe Anteil unter Verwendung des Spotpreises zum Zeitpunkt der Einlösung wieder in CES umgerechnet.

Da der Anteil selbst keine Aufzeichnung über den Preis oder den Betrag des Vermögenswerts enthält, zu dem er geprägt wurde, führt jede Verschiebung des Spotpreises zwischen diesen beiden Zeitpunkten direkt zu einer Diskrepanz zwischen eingezahltem CES und ausgezahltem CES, wodurch die Buchhaltung des Protokolls vollständig dem Preispfad und nicht dem Wert des zugrunde liegenden Vermögenswerts ausgesetzt ist.

Angriffsanalyse

Die folgende Analyse basiert auf der Transaktion 0xc321...da74.

  • Schritt 1: Der Angreifer lieh sich zunächst 55.365e18 CES aus einem Uniswap V3-Flash-Pool und verteilte die Gelder auf 5 Hilfskontrakte. Jeder Helfer erhielt zunächst 6.426e18 CES und rief dann deposit(12) auf. Während dieses Prozesses fragte jeder Helfer zuerst getPriceForLevel(12) ab und bereitete dann die für diese Einzahlung erforderliche Menge an CES basierend auf dem aktuellen Preis vor.
  • Schritt 2: Nachdem alle 5 Helfer die erste Runde von deposit abgeschlossen hatten, verkaufte der Angreifer 300.000 CES am DEX, was den vom bank verwendeten Preis von 1.067585 auf 0.688542 senkte. Die 5 Helfer führten dann nacheinander withdraw aus und lösten die zuvor zum hohen Preis erstellten Anteile gegen CES zum nun niedrigeren Preis ein. Jeder Helfer erhielt 9.427e18 CES.
  • Schritt 3: Nach Abschluss der ersten Runde von withdraw tauschte der Angreifer den erworbenen Gegenpartei-Vermögenswert zurück in CES und trieb damit den Preis wieder nach oben. Der Angreifer wiederholte dann die Schritte 2-3.

  • Schritt 4: Schließlich, nach mehreren Angriffszyklen und nach Rückzahlung des Flash-Loans zuzüglich der Flash-Gebühr von 166.097975017841805126 CES, verblieben dem Angreifer 567.736e18 CES als Gewinn.

Schlussfolgerung

Die Hauptursache dieses Vorfalls liegt darin, dass Tactile sowohl die Einzahlung als auch die Auszahlung gegen einen manipulierbaren Spotpreis abwickelte, ohne den Buchhaltungsanteil an den Betrag oder Preis des Vermögenswerts zum Zeitpunkt der Einzahlung zu binden. Dadurch war die interne Buchhaltung vollständig Preisschwankungen zwischen Ein- und Ausstieg ausgesetzt.

Protokolle, die Anteile gegen volatile Vermögenswerte ausgeben, sollten jeden Anteil an den konkreten Betrag oder Preis des Vermögenswerts zum Zeitpunkt der Prägung binden, damit die Einlösung den ursprünglichen wirtschaftlichen Wert reproduziert, anstatt ihn gegen ein Live-Oracle neu zu bewerten. Wenn Abrechnungsfunktionen auf einen aktuellen Preis verweisen müssen, sollten sie zeitgewichtete oder anderweitig manipulationsresistente Quellen verwenden und vermeiden, denselben Spotpreis zu lesen, der durch Trades verschoben werden kann, die in derselben Transaktion wie der Abrechnungsaufruf ausgeführt werden.


7. SAS Token Vorfall

Kurze Zusammenfassung

Am 2. April 2026 wurde der SAS-Token auf der BNB-Kette für rund 12.000 $ ausgenutzt. Die Hauptursache war ein Fehler in der benutzerdefinierten Übertragungslogik des Tokens: Das Senden von SAS an den LP-Pool erhöhte nur einen globalen sellBurn-Zähler, und jede nachfolgende normale Übertragung konnte dann SAS direkt aus dem Pool verbrennen und sync() aufrufen, um seine Reserven neu zu schreiben, alles ohne den AMM's Swap-Logik zu durchlaufen. Der Angreifer nutzte dies aus, indem er sellBurn durch Verkäufe ansammelte, eine nicht verwandte normale Übertragung auslöste, um SAS aus dem Pool zu verbrennen und seine Reserve auf 1 Wei zu reduzieren, und dann den verbleibenden SAS für Profit umkehrte.

Hintergrund

SAS ist ein deflationärer Token auf der BNB-Kette mit benutzerdefinierter Übertragungslogik, die auf einem PancakeSwap V2-Pool aufbaut. Seine transfer()-Funktion unterscheidet zwischen zwei Pfaden: einem Verkaufspfad, der ausgelöst wird, wenn das Ziel einer Übertragung der LP-Pool ist und der einen globalen sellBurn-Akkumulator um den übertragenen Betrag erhöht; und einem normalen Übertragungspfad, der, wenn sellBurn nicht null ist, SAS direkt aus dem LP-Pool verbrennt und dann sync() aufruft, um seine Reserven an den neuen On-Chain-Saldo anzupassen. Die beiden Pfade sollen zusammen als deflationärer Mechanismus fungieren, der die SAS-Reserve des Pools als Reaktion auf kumulativen Verkaufsdruck reduziert.

Schwachstellenanalyse

Der Kernfehler im SAS-Token-Vertrag (0xbfa266...3d91c6) liegt darin, wie der deflationäre Mechanismus in transfer() integriert ist. Wenn SAS an den LP-Pool gesendet wird, erhöht der Vertrag einen globalen sellBurn-Akkumulator um den übertragenen Betrag. Dann, bei jeder späteren normalen Übertragung, wenn sellBurn nicht null ist, ruft der Vertrag _burnFromPair() auf, um SAS direkt aus dem LP-Pool zu verbrennen, und folgt ihm mit sync(), das die Poolreserven neu schreibt, um sie an den On-Chain-Saldo anzupassen.

Das Problem ist, dass dieser Burn-and-Sync-Pfad die Poolreserven neu schreibt, ohne die AMM-Swap-Logik zu durchlaufen. Sobald sellBurn durch Übertragungen in den Pool erhöht wurde, reicht eine nicht verwandte normale Übertragung aus, um den Burn und Sync auszulösen, wodurch die SAS-Reserve des Pools gegen null gedrängt und eine große Preisverzerrung erzeugt wird, die dann durch einen normalen Swap geerntet werden kann.

Angriffsanalyse

Die folgende Analyse basiert auf der Transaktion 0x878e...adc5.

  • Schritt 1: Der Angreifer lieh sich WBNB über einen Flash-Loan.

  • Schritt 2: Der Angreifer tauschte WBNB gegen SAS.

  • Schritt 3: Der Angreifer setzte einen Vertrag ein und führte die Angrifflogik im constructor() aus. Dies wurde verwendet, um die is_contract()-Prüfung des Protokolls zu umgehen, da der Token-Vertrag verlangte, dass transfer() von einer Whitelist-Adresse oder einer EOA stammt.

  • Schritt 4: Der Angreifer übertrug SAS in den Pool, was den Verkaufspfad auslöste und sellBurn akkumulierte.
  • Schritt 5: Der Angreifer setzte einen zweiten Vertrag ein und löste, wiederum innerhalb seines constructor(), eine normale Übertragung aus. Da sellBurn bereits ungleich null war (aus Schritt 4), löste diese Übertragung die Funktion _burnFromPair() aus, die SAS direkt aus dem LP-Pool verbrannte und dann die Funktion sync() aufrief, wodurch die SAS-Reserve auf 1 Wei reduziert wurde.
  • Schritt 6: Der Angreifer führte einen Umkehr-Swap durch und verkaufte den verbleibenden SAS für Profit.

Schlussfolgerung

Die Hauptursache dieses Vorfalls ist ein Fehler in der benutzerdefinierten Übertragungslogik des SAS-Tokens: Eine normale Übertragung konnte SAS direkt aus dem LP-Pool verbrennen und seine Reserven an den reduzierten Saldo anpassen, wodurch die kumulierte Verkaufstätigkeit in eine willkürliche Reduzierung der SAS-Reserve des Pools und von dort in eine große Preisverzerrung umgewandelt wurde, die dann durch einen normalen Swap geerntet werden konnte.

Token sollten nicht in einen externen AMM-Pool eingreifen und dessen Reserven außerhalb normaler Swap-Pfade verändern. Wenn ein deflationäres Design tatsächlich das Verbrennen aus einem Pool erfordert, müssen das Verbrennen und das dazugehörige sync() an einen eng kontrollierten internen Auslöser gebunden werden, wie z. B. einen vertrauenswürdigen Keeper oder einen ratenlimitierten Zeitplan, anstatt sich auf willkürliche Benutzertransfers zu stützen.


8. Unbekannter EIP-7702 Vorfall

Kurze Zusammenfassung

Am 3. April 2026 wurde ein Benutzerkonto auf der BNB-Kette, das die delegierte Code-Ausführung über EIP-7702 aktiviert hatte, für rund 17.200 $ geleert. Der delegierte Code legte eine pancakeV3SwapCallback()-Funktion ohne ordnungsgemäße Zugriffskontrolle offen. Der Angreifer rief diesen Callback direkt mit präparierten Calldata auf, wodurch das Konto des Opfers gezwungen wurde, seine Token an eine vom Angreifer kontrollierte Adresse zu übertragen.

Hintergrund

Das EOA des Opfers verwendete eine EIP-7702 Typ-4-Transaktion, um delegierten Code einzurichten, damit das Konto Swap-bezogene Logik ausführen konnte. Die delegierte Implementierung enthielt jedoch eine öffentliche pancakeV3SwapCallback()-Funktion, die nur während eines legitimen PancakeSwap V3-Pool-Callbacks aufgerufen werden sollte.

Schwachstellenanalyse

Die Hauptursache ist das Fehlen einer Zugriffskontrolle in der pancakeV3SwapCallback()-Funktion des delegierten Vertrags (0x02C809...aEDbAE).

Bei einem korrekten UniswapV3/PancakeV3-Callback-Design muss der Callback überprüfen, ob msg.sender der erwartete kanonische Pool ist (abgeleitet vom Factory-, Tokenpaar- und Gebühren-Trio oder verifiziert gegen eine vertrauenswürdige Poolliste). In diesem Fall fehlte diese Validierung, sodass jeder externe Aufrufer den Callback direkt aufrufen konnte.

Da der Callback Token-Übertragungen von dem Konto ausführt, das ihn hostet, bedeutet die fehlende msg.sender-Prüfung, dass jeder externe Aufruf mit positiven amount0Delta/amount1Delta in den Zahlungspfad innerhalb des Callbacks gelangt und Token aus dem Konto des Opfers verschiebt, ohne dass ein tatsächlicher Swap stattfindet.

Angriffsanalyse

Die folgende Analyse basiert auf der Transaktion 0x5b2c...4261.

  • Schritt 1: Der Angreifer rief pancakeV3SwapCallback() direkt mit präparierten Parametern auf, was die Callback-Übertragungslogik auslöste, um die Token des Opfers an vom Angreifer kontrollierte Adressen zu übertragen.

Schlussfolgerung

Dieser Vorfall wurde durch die Bereitstellung von Swap-Callback-Logik auf einem EIP-7702-Konto ohne strenge Callback-Authentifizierung verursacht. Da pancakeV3SwapCallback() keine Zugriffskontrolle hatte, konnte der Callback von jedem externen Aufrufer aufgerufen und verwendet werden, um Token aus dem Konto des Opfers zu verschieben, ohne dass jemals ein legitimer Swap stattfand.

Für jeden Vertrag oder delegierten EIP-7702-Code, der V3-ähnliche Callbacks implementiert, müssen Entwickler überprüfen, ob msg.sender der kanonische PancakeV3-Pool ist (abgeleitet vom vertrauenswürdigen Factory-, Tokenpaar- und Gebührentyp), bevor der Callback in eine Übertragungslogik eintritt.


9. Silo Finance Vorfall

Kurze Zusammenfassung

Am 3. April 2026 wurde das Silo Finance soUSDC-Vault auf Arbitrum für rund 359.000 $ ausgenutzt. Die Hauptursache war das Zusammentreffen von drei Mängeln: ein unveränderliches wstUSR-Oracle, das den Token immer noch mit ~1,133 bewertete, nachdem sein Marktpreis auf ~0,12 gefallen war, ein Kapazitätsmechanismus für die Angebotsgrenze bei soUSDC, der nur die eigenen Einlagen des Vaults, aber nicht externe, einschränkte, und ein totalAssets()-Rechnungsfehler, der extern gutgeschriebene bUSDC-Anteile zählte, ohne entsprechende soUSDC-Anteile zu prägen. Durch die direkte Einzahlung von USDC in den Null-Cap-wstUSR-Markt mit receiver=soUSDC blähte der Angreifer den Anteilspreis des Vaults auf, lieh sich dieselben USDC gegen überbewertete wstUSR-Sicherheiten zurück und löste zuvor erworbene soUSDC-Anteile zur aufgeblähten Bewertung ein, wobei der Fehlbetrag aus anderen gesunden Märkten in der Auszahlungswarteschlange gezogen wurde.

Hintergrund

Silo Finance ist ein risikoisolierter Kreditprotokoll auf Arbitrum. Jeder Silo-Markt ist ein zweiseitiges Kreditpaar (z. B. wstUSR/USDC): Kreditnehmer zahlen Sicherheiten (wstUSR) ein und leihen den Kreditbetrag (USDC), während Kreditgeber USDC einzahlen und Zinsen verdienen. Wenn ein Kreditgeber USDC in einen bestimmten Markt einzahlt, erhält er den Einlagenanteils-Token dieses Marktes. Wenn ein Kreditnehmer Sicherheiten einzahlt, erhält er einen Sicherheitenanteils-Token (z. B. bwstUSR-149).

soUSDC ist ein SiloVault, der auf mehreren Silo-Märkten aufsetzt, um USDC-Kredite zu aggregieren. Benutzer zahlen USDC in soUSDC ein und erhalten soUSDC-Anteile. Das Vault leitet dann das eingezahlte USDC basierend auf Angebotsgrenzen, die vom Allokator festgelegt wurden, an genehmigte Silo-Märkte weiter, und das Vault selbst hält die bUSDC-Anteile jedes Marktes, in den es eingezahlt hat. Wenn ein Benutzer soUSDC-Anteile einlöst, berechnet das Vault, wie viel USDC die Anteile wert sind, indem es totalAssets() verwendet, das jeden Markt in der Auszahlungswarteschlange durchläuft und den bUSDC-Anteilsaldo des Vaults in jedem davon summiert. Das Vault zieht dann USDC aus seinen zugrunde liegenden Märkten ab, um den Einlöser zu bezahlen.

wstUSR (Wrapped Staked USR) ist ein Staking-Derivat des USR-Stablecoins, der von Resolv ausgegeben wird. Nachdem Resolv ausgenutzt wurde, verlor USR seine Bindung, stUSR verlor ebenfalls seine Bindung, und der Marktpreis von wstUSR kollabierte auf ~0,12. Die Chainlink-Feed für wstUSR verfolgte jedoch nur die wstUSR/stUSR-Austauschrate (~1,133), und das Protokoll nahm implizit an, dass 1 stUSR = 1 USD ist. Daher bewertete das Oracle wstUSR weiterhin mit ~1,133, eine Lücke von ~10x gegenüber der Realität des Marktes.

Schwachstellenanalyse

Die Oracle-Adresse des wstUSR/USDC-Marktes ist in SiloConfig fest codiert und unveränderlich und kann nicht ersetzt werden. Der Oracle-Vertrag (0x836a1a...04425e) selbst ist ein ChainlinkV3Oracle, dessen zugrunde liegender Chainlink-Feed (Beschreibung: "wstUSR / stUSR Exchange Rate") nur das wstUSR zu stUSR-Wrapper-Verhältnis (~1,133) verfolgt und nicht den Sekundärmarktpreis. Das Protokoll nimmt implizit an, dass 1 stUSR = 1 USD ist, und bewertet wstUSR daher mit ~1,133. Nachdem USR seine Bindung verloren hatte, verlor auch stUSR seine Bindung, und wstUSR fiel im offenen Markt auf ~0,12, aber das Oracle meldete weiterhin ~1,133, eine ~10-fache Überbewertung.

Das Protokoll war sich des Risikos teilweise bewusst: Die Angebotsgrenze von soUSDC für den wstUSR-Markt war auf 0 gesetzt, was bedeutet, dass das Vault niemals freiwillig USDC dorthin leiten würde. Diese Grenze regelt jedoch nur die eigenen ausgehenden deposit()-Aufrufe des Vaults. Da wstUSR_Market.deposit() einen beliebigen receiver-Parameter akzeptiert, kann jeder USDC direkt in den wstUSR-Markt einzahlen und die resultierenden bUSDC-Anteile an die Adresse von soUSDC gutschreiben und so die Angebotsgrenze vollständig umgehen.

Dies schafft den Kern des Exploit-Pfads. Wenn bUSDC-Anteile über eine solche externe Einzahlung in soUSDCs Guthaben gelangen, zählt totalAssets() sie: Es durchläuft jeden Markt in der Auszahlungswarteschlange und liest das tatsächliche Anteilguthaben des Vaults, ohne zu prüfen, ob die Position freiwillig eingegangen wurde. Mittlerweile werden keine neuen soUSDC-Anteile für diese extern gutgeschriebenen Positionen geprägt, da die eigene Prägelogik des Vaults nie ausgelöst wurde – totalAssets steigt, totalShares bleibt gleich, und der soUSDC-Anteilspreis bläht sich auf. Gleichzeitig schafft dies USDC-Liquidität im zuvor leeren wstUSR-Markt, die für den nächsten Schritt benötigt wird.

Angriffsanalyse

Die folgende Analyse basiert auf der Transaktion 0xf77a...f3e1.

Der Angreifer kaufte zunächst wstUSR auf dem Sekundärmarkt für etwa 0,12 pro Token.

  • Schritt 1: Flash-Loan von ca. 4.236.352 USDC von Morpho. Die Fehlbewertung durch das Oracle allein reicht nicht aus – der wstUSR-Markt hatte keine USDC-Liquidität (cap=0, soUSDC zahlte dort nie ein), sodass es nichts gibt, was gegen die überbewerteten Sicherheiten geliehen werden kann. Der Flash-Loan stellt das für die anschließenden Einzahlungs- und Spenden-Schritte benötigte Kapital bereit.

  • Schritt 2: Einzahlung von wstUSR in den wstUSR-Markt als Sicherheit und Erhalt von bwstUSR-149. Dies ist die Vorbereitung für die Ausleihe in Schritt 5 – das Oracle bewertet 13.797 wstUSR mit ~15.633 (zu je 1,133), obwohl der Angreifer nur ~1.656 bezahlt hat.

  • Schritt 3: Einzahlung von ca. 4.222.007 USDC in das soUSDC-Vault, wobei soUSDC-Anteile empfangen werden (~91,5 % des Gesamtangebots). Das Vault leitet diese USDC an bestehende gesunde Märkte weiter (nicht den wstUSR-Markt, da cap=0). Diese soUSDC-Anteile sind das Instrument zur Gewinnentnahme in Schritt 6 – je mehr Anteile der Angreifer hält, desto mehr profitiert er, wenn der Anteilspreis aufgebläht wird.
  • Schritt 4: Einzahlung von ca. 14.344 USDC direkt in den wstUSR-Markt über wstUSR_Market.deposit(receiver=soUSDC) und Prägung von bUSDC-149 an soUSDC. Die resultierenden bUSDC-Anteile werden an die Adresse von soUSDC gutgeschrieben, nicht an die des Angreifers. Dies ist die Kernmanipulation: soUSDCs totalAssets() umfasst nun diese bUSDC-Anteile zum Nennwert (~14.344 USDC), aber es werden keine neuen soUSDC-Anteile geprägt, da die eigene Einzahlungslogik des Vaults nie ausgelöst wurde – totalAssets steigt, totalShares bleibt gleich und der soUSDC-Anteilspreis bläht sich auf. Gleichzeitig schafft dies USDC-Liquidität im zuvor leeren wstUSR-Markt, die für den nächsten Schritt benötigt wird.
  • Schritt 5: Ausleihen von ca. 14.344 USDC aus dem wstUSR-Markt unter Verwendung der in Schritt 2 hinterlegten Sicherheiten. Das Oracle bewertet die Sicherheiten mit ~15.633, sodass bei 92 % maxLTV der Angreifer ~14.344 leihen kann. Dies deckt die in Schritt 4 gespendeten USDC ab – die Ausleihe und die Spende sind Bargeld-neutral. Aber der wstUSR-Markt ist nun vollständig ausgedünnt: Alle USDC wurden ausgeliehen, wodurch nur eine ausstehende Darlehensposition gegen nahezu wertlose wstUSR-Sicherheiten übrig bleibt. soUSDC hält weiterhin die bUSDC-Anteile zum Nennwert in totalAssets().
  • Schritt 6: Einlösung aller in Schritt 3 erworbenen soUSDC-Anteile. Der Anteilspreis ist nun aufgrund der Spende in Schritt 4 aufgebläht, sodass der Angreifer ~4.235.143 USDC erhält, ~13.136 mehr als die in Schritt 3 eingezahlten 4.222.007. Das Vault versucht, aus dem wstUSR-Markt abzuheben, findet aber keine Liquidität (in Schritt 5 ausgeliehen), sodass es den Fehlbetrag aus anderen gesunden Märkten in der Auszahlungswarteschlange zieht. Hier materialisiert sich der Verlust: Echte USDC aus den Märkten anderer soUSDC-Einzahler werden übertragen, um die aufgeblähte Einlösung abzudecken.

Schlussfolgerung

Dieser Vorfall wurde durch das Zusammentreffen eines Oracles, das eine Staking-Austauschrate und nicht den Marktpreis eines abgestürzten Assets verfolgte, eines Vault-Buchhaltungssystems, das extern gutgeschriebene Positionen in totalAssets() zählte, ohne entsprechende Anteile zu prägen, und eines Angebotsdeckelungsmechanismus, der nur die eigenen Einzahlungen des Vaults, aber nicht externe einschränkte, verursacht. Die Oracle-Adresse, die in SiloConfig unveränderlich war, verhinderte eine Notfallkorrektur, nachdem das Problem offensichtlich wurde.

Vault-Protokolle, die über Kreditmärkte aggregieren, sollten sicherstellen, dass totalAssets() nur Positionen zählt, die das Vault durch eigene Einzahlungsoperationen eingegangen ist, nicht extern gutgeschriebene Anteilssalden. Oracle-Adressen sollten nicht dauerhaft unveränderlich sein; Notfall-Governance-Mechanismen sollten für die Aktualisierung von Preis-Feeds vorhanden sein, wenn zugrunde liegende Assets ihre Bindung verlieren.

Sign up for the latest updates
Tracing $1.6B in TRON USDT: Inside the VerilyHK Ponzi Infrastructure
Case Studies

Tracing $1.6B in TRON USDT: Inside the VerilyHK Ponzi Infrastructure

An on-chain investigation into VerilyHK, a fraudulent platform that moved $1.6B in TRON USDT through a multi-layered fund-routing infrastructure of rotating wallets, paired payout channels, and exchange exit funnels, with traced connections to the FinCEN-sanctioned Huione Group.

Weekly Web3 Security Incident Roundup | Mar 30 – Apr 5, 2026
Security Insights

Weekly Web3 Security Incident Roundup | Mar 30 – Apr 5, 2026

This BlockSec weekly security report covers nine DeFi attack incidents detected between March 30 and April 5, 2026, across Solana, BNB Chain, Arbitrum, and Polygon, with total estimated losses of approximately $287M. The week was dominated by the $285.3M Drift Protocol exploit on Solana, where attackers combined multisig signer social engineering with Solana's durable nonce mechanism to bypass a zero-timelock 2-of-5 Security Council, alongside notable incidents including a $950K flash loan TWAP manipulation against the LML staking protocol, a $359K Silo Finance vault inflation via an external `wstUSR` market donation exploiting a depegged-asset oracle and `totalAssets()` accounting flaw, and an EIP-7702 delegated-code access control failure. The report provides detailed vulnerability analysis and attack transaction breakdowns for each incident, covering flawed business logic, access control, price manipulation, phishing, and misconfiguration attack types.

Drift Protocol Incident: Multisig Governance Compromise via Durable Nonce Exploitation
Security Insights

Drift Protocol Incident: Multisig Governance Compromise via Durable Nonce Exploitation

On April 1, 2026 (UTC), Drift Protocol on Solana suffered a $285.3M loss after an attacker exploited Solana's durable nonce mechanism to delay the execution of phished multisig approvals, ultimately transferring administrative control of the protocol's 2-of-5 Squads governance with zero timelock. With full admin privileges, the attacker created a malicious collateral market (CVT), inflated its oracle price, relaxed withdrawal protections, and drained USDC, JLP, SOL, cbBTC, and other assets through 31 rapid withdrawals in approximately 12 minutes. This incident highlights how durable nonce-based delayed execution can decouple signer intent from on-chain execution, bypassing the temporal assumptions that multisig security implicitly relies on.