Resources

People often ask me "How did you learn how to hack?" The answer: by reading. This page is a collection of the blog posts and other articles that I have accumulated over the years of my journey. Enjoy!

Inside the GMX Hack: $42 Million Vanishes in an Instant- 1698

SlowMist Posted 7 Months Ago
  • GMX is a very large decentralized trading platform. Although it has a $5M bug bounty, it was exploited for $42M after over 2 years of being live and multiple audits. There are several reasons this likely wasn't found, such as requiring multiple vulnerabilities to be exploited.
  • There were two design flaws. The first one is around the financial manipulation vulnerability within the GLP token. This was done by opening a short position to increase the size of the Assets Under Management (AUM) instantly. This would then increase the price of GLP in a controllable fashion that could reasonably be undone. This is pretty straightforward.
  • The second issue is less simple. When creating short positions, it was possible to call increasePosition, which did NOT update the globalShortAveragePrices in the ShortsTracker contract. Later, when the execution decreases, the value is updated, though. Entries update, but exist to not update. This is not really a vulnerability by itself but a quirk of the protocol.
  • The real vulnerability is very subtle. GMX had a Postionmanager contract that controlled a lot of settings that was only callable via a GMX controlled key. One of these contracts called enableLeverage on the core code before performing any of the trades. There was a backend off-chain service that would trigger this functionality. While Keeper made this call, it was possible to redirect execution and call the GMX contract while leverage was still enabled. This is the vulnerability that makes this possible.
  • With all of that in mind, the attack can be broken down into the preparation and the triggering. First, the attacker creates a long position via a smart contract (used for reentrancy later) and a reduce-order that the Keeper would later execute. When the keeper received the reduce-order, it would call the PositionManager to enable leverage. The Orderbook would then execute executeDecreaseOrder(), update the attacks position and pass execution to the contract via the collataral token being in WETH.
  • In the attackers smart contract, enabled by the sending of ETH to the fallback function, would transfer 3000 USDC to the vault and open a 30x leverage short against WBTC using increasePosition. Because of the second design flaw, the globalShortAveragePrices were not updated. During a future call to the ShortsTracker contract, the globalShortAveragePrices would be updated. This dropped the price of WBTC to about 57x less than it should have been.
  • To exploit this price discrepancy, they used the GLP token. It would first create a large flash loan of USDC to call mintAndStakeGlp to mint a lot of GLP. Next, the attacker would call increasePosition to deposit a large amount of USDC on WBTC. This would update the globalShortSizes, resulting in AUM increasing dramatically. Finally, the attacker would call unstakeAndRedeemGlp to redeem way more tokens than they were entitled to. But why?
  • The AUM was updated but the globalShortSizes was not. When performing calculations on the trades, the manipulated value of the trade was far above the market price, making the trade appear deeply unprofitable. Naturally, this increases AUM by a lot. By doing this over and over, they got more funds from the trade of GLP than they actually should have.
  • This is a pretty crazy exploit in a popular protocol - it makes me wonder what other big protocols are hiding huge bugs. Exploiting vulnerabilities, such as the manipulation of financial instruments, it pretty complicated. I'm guessing that the attacker found the financial manipulation first and then needed to find a way to turn on leverage.
  • Eventually, all of the funds were returned to the protocol. So, why didn't they just claim the bug bounty? Since the keeper functionality was "privileged" and the offchain infra is blackbox, there's a major risk of getting rugged. SlowMist recommends better reentrancy locks be added. In reality, I feel like these were reentrancy issues across contracts (in the case of enableLeverage), making this not a great solution. In the case of the discrepancy in the price updates, I do agree, though. Great write-up explaining this super complex set of issues!