🏡 Back Home
🔎 Search
Alright. I Figured Out T...

- Author: @kelvinfichter on Twitter
- Full Title: Alright. I Figured Out T...
- Category: #tweets
- Read on: 2022-05-31
- URL: https://twitter.com/kelvinfichter/status/1489041221947375616
Highlights
- Alright. I figured out the Solana x Wormhole Bridge hack. ~300 million dollars worth of ETH drained out of the Wormhole Bridge on Ethereum. Here's how it happened. (View Tweet)
- Here's the transaction which finalized a majority of the exploit. 80k ETH pulled out of the Wormhole contract on Ethereum in a single transaction: https://t.co/8IcrrnzeWj (View Tweet)
- Although it's dramatic, this transaction is just the very end of an interesting series of events. I had to start working my way backwards to figure out how this was even possible. (View Tweet)
- Wormhole is a "bridge" -- basically a way to move crypto assets between different blockchains. Specifically, Wormhole has a set of "guardians" that sign off on transfers between chains. It's a little more complicated than that in practice, but that's the general idea. (View Tweet)
- The transaction that pulled out 80k ETH was actually the attacker transferring 80k ETH from Solana to Ethereum. I originally thought that the contract might've incorrectly validated the signatures on the transfer, but the signatures completely checked out. (View Tweet)
- The Wormhole "guardians" had somehow signed off on this 80k ETH transfer as if it were 100% legit. How was that possible? (View Tweet)
- The first breakthrough came from this transaction on Solana which somehow minted 120k "Wormhole ETH" out of nowhere: https://t.co/8eaWLTXeIt (View Tweet)
- That explains part of it! The attacker was able to mint Wormhole ETH on Solana, so they were able to correctly withdraw it back to Ethereum. Now we just need to figure out how the attacker was able to mint this Wormhole ETH on Solana... (View Tweet)
- The next interesting piece of information is this Solana transaction that came right before the 120k ETH one, where 0.1 Wormhole ETH was minted on Solana: https://t.co/F6Sk8mdDn0 (View Tweet)
- If we take a look at the attacker's transaction history on Ethereum, we end up seeing that the attacker did make a deposit of 0.1 ETH into Solana from Ethereum: https://t.co/2GddVuidL3 (View Tweet)
- Of course, the attacker definitely did not make a 120k ETH deposit into Wormhole on Ethereum. But there's something interesting about this deposit. It definitely has something to do with the attack, but what? (View Tweet)
- Alright, here's where we start getting into the weeds of Solana. This is the first time I've ever looked at Solana contracts so it took me a while to get my bearings, but I think I finally get what's going on. (View Tweet)
- The transactions that minted Wormhole ETH on Solana were triggering this Wormhole function "complete_wrapped": https://t.co/v0y1TyVMDQ (View Tweet)
- One of the parameters that this function takes is a "transfer message", basically a message signed by the guardians that says which token to mint and how much: https://t.co/82NbEvXY8f (View Tweet)
- Solana is kinda weird, so these parameters are actually smart contracts themselves. But the important thing is how these "transfer message" contracts get created. Here's the transaction that made the 0.1 ETH transfer message: https://t.co/FXHBGbEXwA (View Tweet)
- This "transfer message" contract is created by triggering a function called "post_vaa": https://t.co/Y3wiQ9L8yB (View Tweet)
- It doesn't really matter if you understand the fancy code, the most important thing here is that post_vaa checks if the message is valid by checking the signatures from the guardians. That part seems reasonable enough. But it's this signature checking step that broke everything. (View Tweet)
- One sec loading up my next tweets... hold your horses (View Tweet)
- Alright let's keep going. "post_vaa" doesn't actually check the signatures. Instead, in typical Solana fashion, there's another smart contract which gets created by calling the "verify_signatures" function. https://t.co/iZ5eJoAjO3 (View Tweet)
- One of the inputs to the "verify_signatures" function is a Solana built-in "system" program which contains various utilities the contract can use: https://t.co/kJR1bhOYTK (View Tweet)
- Within "verify_signatures", the Wormhole program attempts to check that the thing that happened right before this function was triggered was that the Secp256k1 signature verification function was executed: https://t.co/2jW6TEokoT (View Tweet)
- This verification function is a built-in tool that's supposed to verify that the given signatures are correct. So the signature verification has been outsourced to this program. But here's where the bug comes in. (View Tweet)
- The Wormhole contracts used the function load_instruction_at to check that the Secp256k1 function was called first: https://t.co/psWNTfibVc (View Tweet)
- The load_instruction_at function was deprecated relatively recently because it does not check that it's executing against the actual system address! https://t.co/WYAwtgA8mL (View Tweet)
- You're supposed to provide the system address as the program you're executing here (it's the third-to-last program input): https://t.co/kBQTWz5QRV (View Tweet)
- Here's that system address being used as the input for the "verify_signatures" for the legit deposit of 0.1 ETH
(View Tweet)
- But here's the "verify_signatures" transaction for the fake deposit of 120k ETH
(View Tweet)
- That's not the system address! (View Tweet)
- Using this "fake" system program, the attacker could effectively lie about the fact that the signature check program was executed. The signatures weren't being checked at all! (View Tweet)
- After that point, it was game over. The attacker made it look like the guardians had signed off on a 120k deposit into Wormhole on Solana, even though they hadn't. All the attacker needed to do now was to make their "play" money real by withdrawing it back to Ethereum. (View Tweet)
- And one withdrawal of 80k ETH + 10k ETH later (everything in the bridge on Ethereum), everything was gone. (View Tweet)
- Wormhole reports that the exploit has been patched https://t.co/iDTova1URq (View Tweet)
- A commit was made ~9 hours ago replacing usage of load_instruction_at with load_instruction_at_checked, which actually confirms that the program being executed is the system program: https://t.co/rQQ108Zc5Y (View Tweet)
- It's interesting that this commit was made ~9 hours ago and the exploit happened a few hours after that. Possible that an attacker was keeping an eye on the repository and looking out for suspicious commits. (View Tweet)