Am 25. August 2025 führte Panoptic mit Unterstützung von Cantina und Seal911 eine White-Hat-Rettungsaktion durch und sicherte etwa 400.000 US-Dollar an gefährdeten Geldern [1]. Die Grundursache war ein Fehler in der Konstruktion von s_positionsHash: Das Protokoll verwendete XOR, um Keccak256-Hashes von Positions-IDs zu einem einzigen Fingerabdruck zu aggregieren. Während einzelne Keccak256-Hashes kollisionsresistent bleiben, macht die mathematische Linearität von XOR den zusammengesetzten Fingerabdruck unsicher. Ein Angreifer kann eine Reihe gefälschter Positions-IDs generieren, deren XOR-aggregierter Hash mit jedem Ziel-Fingerabdruck übereinstimmt, wodurch die Positionsprüfung des Protokolls umgangen und Sicherheiten abgezogen werden, ohne Schulden zurückzuzahlen.
Hintergrund
Panoptic ist ein dezentralisiertes Protokoll für den Handel mit ewigen Optionen, das auf Ethereum aufgebaut ist und es Benutzern ermöglicht, Put- und Call-Optionen zu handeln.
Die Funktion withdraw() hat einen Eingabeparameter positionList, der aus einer Menge von tokenIds besteht. Jede tokenId repräsentiert eine Position. Die Funktion withdraw() prüft den Schuldenstatus jeder Position basierend auf s_positionsHash und ruft dann die Sicherheiten des Benutzers ab.
Um Gas zu sparen, speichert das Protokoll nicht jede Position (d. h. tokenId) des Benutzers. Stattdessen berechnet es einen Fingerabdruck basierend auf allen tokenIds des Benutzers und zeichnet ihn in s_positionsHash auf. Die 8 höchstwertigen Bits jedes s_positionsHash repräsentieren numLegs, während die unteren 248 Bits den user position hash repräsentieren.
Für jede übergebene tokenId berechnet das Protokoll deren Hash, nimmt die unteren 248 Bits und aktualisiert den user position hash, indem es einen bitweisen XOR mit den unteren 248 Bits des aktuellen s_positionsHash durchführt.
Gleichzeitig wird countLegs basierend auf dem numerischen Bereich der tokenId angepasst: Es bleibt unverändert, wenn tokenId kleiner als ist, und erhöht sich um 1, 2 oder 3, wenn es in den Bereichen , bzw. liegt. Dies wird schließlich in die obersten 8 Bits von s_positionsHash geschrieben, um numLegs zu aktualisieren.
Schwachstellenanalyse
Die Grundursache ist ein Fehler im Algorithmus des Vertrags zur Konstruktion von s_positionsHash, insbesondere die Verwendung der XOR-Operation zur Aggregation von Keccak256-Hash-Ergebnissen. Während eine einzelne Hash-Funktion sicher bleibt, macht die mathematische Linearität der XOR-Operation den gesamten Fingerabdruck-Algorithmus (d. h. die XOR-Summe von Hashes) unsicher [2].
Linearität impliziert, dass ein Angreifer die Hash-Funktion selbst nicht brechen muss (d. h. die tokenId aus dem Hash umkehren). Stattdessen können sie eine kombinatorische Strategie anwenden: Generieren einer großen Anzahl von zufälligen tokenIds, Berechnen ihres Keccak256(tokenId) und aus diesen Hash-Werten eine bestimmte Teilmenge auswählen, sodass die XOR-Summe dieser tokenId-Hashes exakt dem Ziel-Fingerabdruck des Opfers entspricht.
Dies ermöglicht es einem Angreifer, bei Aufruf von withdraw() eine Reihe gefälschter tokenIds zu übergeben, um den Gesundheitstest zu bestehen und alle Sicherheiten im Zusammenhang mit s_positionsHash abzurufen.
Theorie
Nehmen wir an, der Positionsfingerabdruck des Benutzers s_positionsHash hat einen user position hash von und numLegs von , mit Benutzer tokenIds . Somit gilt:
Hier kann jeder 248-Bit-Hash-Wert als 248-dimensionaler Vektor betrachtet werden.
Daher liegt in einem 248-dimensionalen Raum aus 0en und 1en (). In diesem Raum ist die XOR-Operation gleich der Vektoraddition (Anhang I).
Das Ziel des Angreifers ist es, 248-dimensionale Vektoren aus allen verfügbaren Vektoren zu finden, sodass die unteren 248 Bits ihrer XOR-Summe gleich sind. Somit können wir das Ziel des Angreifers als System linearer Gleichungen formulieren:
Insbesondere müssen wir nicht direkt konstruieren. Stattdessen wählen wir linear unabhängige Hash-Vektoren (wobei der Dimension 248 entspricht) und verwenden sie als Spaltenvektoren, um eine Matrix zu konstruieren:
Das Problem verwandelt sich dann in die Suche nach einem Koeffizientenvektor , so dass:
Wobei und .
Gemäß der linearen Algebra erstreckt sich die Matrix , solange sie vollen Rang hat, über den gesamten -dimensionalen Raum. Das bedeutet, dass für jedes Ziel das Gleichungssystem eine eindeutige Lösung hat. Nach der Lösung von behalten wir einfach diejenigen Vektoren bei, für die ; ihre XOR-Summe ist .
Beispiel
Zur besseren Verständlichkeit demonstrieren wir diesen Konstruktionsprozess anhand einer Fallstudie. Nehmen wir an, die Vektoren sind 3-dimensional, jede Dimension besteht nur aus 0 oder 1, und der Ziel-Hashwert ist 101, d. h. .
Als Nächstes generieren wir zufällig 3 Hash-Werte:
Wir konstruieren die Matrix mit diesen drei Vektoren als Spalten und stellen die Gleichung auf:
Durch Gaußsche Elimination erhalten wir . Das bedeutet, wir müssen und auswählen (entsprechend ), und ihre XOR-Summe entspricht exakt .
Auswahl von n linear unabhängigen Vektoren
Wie bereits erwähnt, müssen wir zur Lösung von eine Matrix mit vollem Rang konstruieren. Da wir es mit einem extrem großen Vektorraum () zu tun haben, stellt sich die Kernfrage: Wie wählen wir schnell linear unabhängige Vektoren aus diesem riesigen Raum aus?
Betrachten wir die einfachste Methode: zufälliges Generieren von tokenIds und Auswählen ihrer Hash-Ergebnisse als Vektoren.
Über ist die Wahrscheinlichkeit , dass zufällig ausgewählte -dimensionale Vektoren eine vollen Rangmatrix bilden:
Wenn groß ist (in diesem Beispiel ), konvergiert diese Wahrscheinlichkeit gegen eine Konstante (Anhang II):
Das bedeutet, jeder zufällige Versuch hat eine Erfolgswahrscheinlichkeit von etwa 28,9 %. Im Durchschnitt benötigt ein Angreifer nur etwa 3,5 Versuche, um eine Menge linear unabhängiger Vektoren zu finden. Daher sind die Rechenkosten extrem niedrig, und der Angreifer kann schnell eine Matrix konstruieren, die die Bedingungen erfüllt.
Um countLegs in den obersten 8 Bits zu steuern, müssen wir nur den Bereich der zufällig generierten tokenId-Werte basierend auf dem Ziel countLegs anpassen.
Wenn wir zum Beispiel möchten, dass die numLegs im gefälschten Fingerabdruck 0 sind, stellen wir einfach sicher, dass die zufällig generierten tokenIds alle kleiner als sind. Da die Bein-Inkremente für tokenIds in diesem Bereich 0 betragen, wird die endgültige akkumulierte numLegs unweigerlich 0 sein, unabhängig davon, welche Vektoren die Gaußsche Eliminationslösung auswählt.
Angriffsanalyse
Der White-Hat-Retter initiierte mehrere Rettungstransaktionen. Der Einfachheit halber basiert die folgende Diskussion auf nur einer dieser Transaktionen [3].
Die Kernlogik besteht aus den folgenden 5 Schritten:
- Leihen Sie 0,23e8 WBTC und 28e18 WETH über einen Flash-Loan von Aave.
- Zahlen Sie 0,23e8 WBTC und 28e18 WETH in den poWBTC-Vertrag und den 0x1f8d_poWETH-Vertrag ein.
- Rufen Sie
mintOptions()desPanopticPool-Vertrags mit einer normalenpositionIdListauf, um Gelder zu leihen und eine gehebelte Position zu eröffnen. - Rufen Sie
withdraw()mit den gefälschtentokenIds auf. Da diese gefälschten Positionen einepositionSizevon 0 haben, gibt die FunktiontokenRequiredals 0 zurück, was bedeutet, dass die erforderlichen Gesamtsicherheiten für alle Positionen fälschlicherweise als null berechnet werden. In der Zwischenzeit ist der von diesentokenIds generiertes_positionsHashexakt derselbe wie der in Schritt 3 generierte, was es dem Retter ermöglicht, alle Sicherheiten abzurufen, ohne Schulden zurückzuzahlen. - Zahlen Sie den Flash-Loan zurück und führen Sie die nächste Runde aus.
Zusammenfassung
Dieser Vorfall hebt zwei sich verstärkende Mängel hervor, die zusammen den unbefugten Abzug von Sicherheiten ermöglichten.
- XOR ist keine sichere Aggregationsfunktion für Hashes. Keccak256 ist kollisionsresistent, aber die Linearität von XOR bedeutet, dass die XOR-Summe mehrerer Hashes diese Eigenschaft nicht erbt. Die Konstruktion einer Menge von Eingaben, deren Hashes zu jedem Zielwert XORen, reduziert sich auf die Lösung eines Systems linearer Gleichungen über , was rechnerisch trivial ist. Hash-Zusammensetzung erfordert Operationen, die die Kollisionsresistenz beibehalten, wie z. B. Verkettung gefolgt von erneuter Hashing.
- Fehlende Validierung von Positions-IDs. Das Protokoll prüfte nicht, ob die übergebenen
positionIds gültigen Optionspositionen entsprachen. Werte unter haben eincountLegsvon 0 und einepositionSizevon 0, was bedeutet, dass die gefälschten Positionen keine Schulden verursachen. Dies ermöglichte es dem Angreifer, den Gesundheitstest mit null erforderlichen Sicherheiten zu bestehen und gleichzeitig den Ziel-Fingerabdruck abzugleichen.
Referenz
Anhang
Die folgenden beiden Anhänge liefern eine mathematische Erklärung und einen Beweis für die Aussagen im Haupttext, nämlich dass die XOR-Operation der Vektoraddition entspricht (Anhang I) und die Wahrscheinlichkeit, dass eine zufällige Matrix vollen Rang hat (Anhang II).
Anhang I
Im endlichen Körper ist die Addition als Addition modulo 2 definiert:
Die Beobachtung zeigt, dass dies identisch mit der logischen Operation Exclusive OR (XOR, Symbol ) ist.
Für den -dimensionalen Vektorraum (in diesem Fall ) ist die Addition zweier Vektoren und als komponentenweise Addition modulo 2 definiert:
Daher ist im Vektorraum die Vektoraddition äquivalent zur bitweisen XOR-Operation auf den Vektorkomponenten.
Anhang II
Damit die Matrix vollen Rang hat, müssen diese Vektoren linear unabhängig sein.
Der erste Vektor kann jeder Vektor in außer dem Nullvektor sein, was Optionen bietet; der zweite Vektor darf nicht im von aufgespannten Unterraum liegen, der Vektoren enthält, was Optionen übrig lässt; diesem Logik folgend darf der -te Vektor nicht im von den vorherigen Vektoren aufgespannten Unterraum liegen, was mögliche Optionen ergibt.
Die Gesamtzahl solcher Matrizen (d. h. die Ordnung von ) ist:
Und die Gesamtzahl aller möglichen Matrizen beträgt .
Daher ist die Wahrscheinlichkeit :
Wenn wir setzen, können wir diesen Ausdruck umschreiben als:
Wenn , konvergiert dieses Produkt gegen eine Konstante:
Das bedeutet, dass für große die Wahrscheinlichkeit, dass eine zufällige Matrix vollen Rang hat, etwa 28,9 % beträgt.
Ü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 zahlreiche Blockchain-Sicherheitsarbeiten 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 Wert von mehreren Milliarden Dollar gesichert.
-
Offizielle Website: https://blocksec.com/
-
Offizielles Twitter-Konto: https://twitter.com/BlockSecTeam



