Full Report
Panaoptic is a company that maintains trading and perpetual (longs/shorts) contracts. When you take out a short, you are stating that I think this token will drop. This contract is called a position that a user takes. The vulnerability was a spoofing issue around the position data. This was received as a bug bounty report. The user received a $250,000K payout - the maximum on the program. The position is all stored within a uint256 with different sections to the value for gas efficiency reasons. These include four legs, each consisting of an asset ID, an option ratio, a boolean indicating whether it's a long, a strike price, and many other fields. Additionally, there's a one-time section for Uniswap pool information. So, what's the big deal? A user can have up to 25 open positions. Instead of storing each position ID on-chain, they combine the hashes to create a single fingerprint. When the user wants to interact with the contract, the positions are passed in, hashed, and verified against the user's current fingerprint. The fingerprint generation is as follows: Hash the provided number associated with the position. Take the lower 248 bits of the hash output. XOR the lower 248 bits with the accumulated hash, which defaults to 0x00. Add the amount of legs associated with the position and add them to the upper bits of the fingerprint. This is to know how many legs are associated with the user. Repeat steps 1-4 until you're left with a value. The usage of XOR is a significant problem here. XOR is associative, commutative, and self-canceling. This appears like the hashing function XHASH, which is known to be broken. By treating this as a set of linear combinations, it's possible to use Gaussian elimination to find overlaps with large sets of provided tokens. This allows you to create fake positions because the fingerprint will match. This requires brute-forcing the correct keccak256 hashes for the input values, but the problem isn't particularly computationally intensive. Another issue that made this MUCH easier to do was that the usage of the fingerprint was not limited to 25 positions. Additionally, there was very little input validation placed on this either, since it was assumed the fingerprint couldn't be spoofed. This made it possible to use giant token lists, making the solving easier. To exploit this, an attacker would do the following: Borrow assets via a flash loan. Use the funds to deposit a lot of collateral. Open two very deep in the money positions with both a call and a put with leverage. Call the withdrawal methods on the contract with a list of zero collateral requirement positions. This allows you to credit your account without triggering the collateral subtraction. They were unable to upgrade the contracts while this major vulnerability was present. So, they commenced a migration process. Over the course of two days they messaged all Panoptic users to remove funds from the protocol. Additionally, two wallets had 70% of 1.6M in them. They were able to find the users who owned these wallets, and they withdrew. They led to $550K in the protocol. Time for the crazy part: the whitehat hack. Their plan was the same as described above on the attack: take a flash loan, borrow a lot of tokens to open positions and withdraw the tokens with the spoofed IDs that were provided. They took the reporter's PoC and made it work within a single Tx. They didn't post to GitHub or other tools out of fear of leaking. So, the PoC was done on a single devs machine. They tried using the Flashbots RPC to recover the funds. This is a requirement because, otherwise, a bot could frontrun the whitehat hack and steal the funds. Unfortunately, Flashbots rejected the transaction because it required more state reads than they allowed. After contacting Flashbots, they updated the rate limit for them, and the recovery succeeded. It was first done on the Ethereum L1 and done immediately after on the L2s. They claim that 98% of customer funds were safe. To claim their funds, the team created a Merkle root verification system for users. Awesome post! They have some good lessons learned: Several issues were discovered relating to these issues on the C4 contest platform but they didn't put the whole spoofing issue together. This quote is perfect: "If we had spent time ourselves trying to come up with a position-list-spoofing method, we may have been able to foresee this vulnerability." Recovery methods, outside of whitehat hacks, are massively important. A large amount of the funds was recovered through reaching out to users. I find this risky because one of the users could have looked for the vulnerability and exploited it. The more people who know, the more likely it is to get exploited. A rule as old as time: Use available tools and methods at all times. This is specifically true with cryptography. If you need to do a whitehat hack, prepare to be perfect. RPC listening, mempool watching, compromised dev machines, GitHub snooping... all of these would have allowed an attacker to carry out this attack themselves. This is a case where perfection is required.
Analysis Summary
# Vulnerability: Position Spoofing via XOR Hashing Collision
## CVE Details
- **CVE ID:** Not Assigned (Custom protocol bug bounty/Incident response)
- **CVSS Score:** 10.0 (Critical)
- **CWE:** CWE-310 (Cryptographic Issues), CWE-327 (Use of a Broken or Risky Cryptographic Algorithm)
## Affected Systems
- **Products:** Panoptic Protocol
- **Versions:** V1 Core Contracts (PanopticPool)
- **Configurations:** Multi-leg trading positions utilizing bitpacked position IDs and XOR-based fingerprinting.
## Vulnerability Description
The Panoptic protocol manages user positions by bitpacking multiple data "legs" into a single `uint256`. To track a user's set of positions efficiently, the protocol generates a unique "fingerprint" using an incremental hashing method.
The flaw lies in the fingerprint generation logic:
1. Individual position IDs are hashed using Keccak256.
2. The lower 248 bits of these hashes are combined using the **XOR** operator.
3. The upper bits track the total number of legs.
Because XOR is associative, commutative, and self-canceling, the construction acts similarly to a broken incremental hash (specifically "XHASH"). By treating the position IDs as a set of linear combinations, an attacker can use **Gaussian elimination** to find a large set of arbitrary position IDs that, when XORed together, produce a fingerprint identical to the user's valid one. This allows a "spoofing" attack where the contract is tricked into believing a user has valid, high-collateral positions that do not actually exist.
## Exploitation
- **Status:** PoC available (developed by researcher and protocol team); Whitehat rescue executed.
- **Complexity:** Medium (Requires brute-forcing Keccak256 hashes for input values and solving linear equations).
- **Attack Vector:** Network (Direct smart contract interaction).
## Impact
- **Confidentiality:** None
- **Integrity:** High (Attacker can spoof position data and collateral balance).
- **Availability:** High (Funds can be drained, requiring protocol shutdown/migration).
## Remediation
### Patches
- **Panoptic V2:** The team has deprecated the vulnerable V1 architecture. V2 includes overhauled position tracking and has undergone multiple security audits (Obsidian, Nethermind).
### Workarounds
- **Social Recovery/Migration:** The V1 contracts were not upgradeable. The team initiated an emergency migration, coordinating with users to withdraw funds manually.
- **Whitehat Rescue:** The protocol team executed a whitehat "attack" using Flashbots to secure the remaining 2% of at-risk funds before malicious actors could exploit the flaw.
## Detection
- **Indicators of Compromise:** Large lists of position IDs being submitted in a single transaction that result in unconventional collateral requirement calculations.
- **Detection Methods:** Monitoring for transactions interacting with the `PanopticPool` that utilize an unusually high number of position legs to satisfy collateral checks.
## References
- Panoptic Post-Mortem: [https://panoptic[.]xyz/blog/position-spoofing-post-mortem]
- Whitehat Rescue Transaction (Mainnet): [https://etherscan[.]io/address/0x82BF455e9ebd6a541EF10b683dE1edCaf05cE7A1]
- Incremental Hashing Research (Bellare & Micciancio): [https://cseweb[.]ucsd[.]edu/~mihir/papers/inchash[.]pdf]