samczsun Profile picture
Oct 6 21 tweets 9 min read
Five hours ago, an attacker stole 2 million BNB (~$566M USD) from the Binance Bridge. During that time, I've been working closely with multiple parties to triage and resolve this issue. Here's how it all went down.
It all started when @zachxbt sent me the attacker's address out of the blue. When I clicked into it, I saw an account worth hundreds of millions of dollars. Either someone had pulled off a huge rug, or there was a massive hack underway
@zachxbt At first, I thought that @VenusProtocol had been hacked yet again. However, it only took a couple seconds to determine that the attacker *really did* deposit over $200M USD into Venus

Instead, I needed to figure out where those funds came from
The answer was that the attacker had somehow convinced the Binance Bridge to simply send them 1,000,000 BNB. Twice.
Either Binance was finally running the biggest giveaway that Web3 had ever seen, or the attacker had found a critical bug
I started by comparing the attacker's transactions with legitimate withdrawals. The first thing I noticed was that the height used by the attacker was always the same - 110217401. The heights used by legitimate withdrawals were much bigger, such as 270822321
I also noticed that the attacker's proof was significantly shorter than the legitimate withdrawal's proof. These two facts led me to believe that the attacker had found a way to forge a proof for that specific block - 110217401. Now I had to figure out how these proofs worked
On Binance, there's a special precompile contract used to verify IAVL trees. If you don't know anything about IAVL trees, don't worry. I still don't understand about 95% of it. Fortunately, all you and I need to reproduce the hack is the remaining 5%
Ok, so basically, when you verify an IAVL tree, you specify a list of "operations". The Binance Bridge typically expects two of them: an "iavl:v" operation, and a "multistore" operation. Here are their implementations

github.com/cosmos/iavl/bl…
github.com/bnb-chain/bsc/…
In order to forge a proof, we need both operations to succeed, and we need to last operation (the multistore) to return a fixed value (the hash of the specified block: 110217401)
Looking at the implementation, we can convince ourselves with some effort that it's impossible, or at least very difficult, to manipulate the root hash. Or you can just take my word for it. This means that we need our input value to be equal to one of the commit IDs
The input value of the "multistore" operation is the output value of the "iavl:v" operation. This means that we want to somehow control the root variable here, while still passing the value verification
So how is the root hash computed? Well, it happens in this monster of a function called COMPUTEHASH. At a very very high level, it recursively goes over each path and leaf and does a bunch of hashing and really the implementation details don't matter

github.com/cosmos/iavl/bl…
What does matter is that due to the way that hash functions are intended to work, we can basically say with certainty that any (path, nleaf) pair will produce a unique hash. If we want to forge a proof, those will need to stay the same
Looking at the way that the proof is laid out in a legitimate transaction, we see it has a very long path, no inner nodes, and only one leaf node. This leaf node contains the hash of our malicious payload! If we can't modify this leaf node, then we'll need to add a new one
Of course, if we add a new leaf node, we'll also need to add a new inner node to match
Now we just have one last obstacle to face. How do we actually get COMPUTEHASH to return the root hash we want? Well, notice that eventually we'll need a path to contain a non-zero right hash. When we find one that does, we assert it matches the intermediate root hash
Let's just instrument the code a bit so we can figure out what hash we need and....
All that's left is to put it all together. We'll take a legitimate proof and modify it so that:
1) we add a new leaf for our forged payload
2) we add a blank inner node to satisfy the prover
3) we tweak our leaf to exit early with the correct root hash

gist.github.com/samczsun/8635f…
(It's worth noting that this wasn't the exact method the attacker used. Their proof path is much shorter, and I'm not sure how exactly they generated that. However, the rest of the exploit is identical, and I believe showing how to build it from the ground up is valuable)
In summary, there was a bug in the way that the Binance Bridge verified proofs which could have allowed attackers to forge arbitrary messages. Fortunately, the attacker here only forged two messages, but the damage could have been far worse

• • •

Missing some Tweet in this thread? You can try to force a refresh
 

Keep Current with samczsun

samczsun Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!

PDF

Twitter may remove this content at anytime! Save it as PDF for later use!

Try unrolling a thread yourself!

how to unroll video
  1. Follow @ThreadReaderApp to mention us!

  2. From a Twitter thread mention us with a keyword "unroll"
@threadreaderapp unroll

Practice here first or read more on our help page!

More from @samczsun

Aug 1
1/ Nomad just got drained for over $150M in one of the most chaotic hacks that Web3 has ever seen. How exactly did this happen, and what was the root cause? Allow me to take you behind the scenes 👇 Image
2/ It all started when @officer_cia shared @spreekaway's tweet in the ETHSecurity Telegram channel. Although I had no idea what was going on at the time, just the sheer volume of assets leaving the bridge was clearly a bad sign Image
3/ My first thought was that there was some misconfiguration for the token's decimals. After all, it seemed as though the bridge was running a "send 0.01 WBTC, get 100 WBTC back" promotion Image
Read 12 tweets
Jul 5
1/ Today, someone tried to hack me with a crypto stealer, so I guess I've finally made it

Fortunately, they weren't successful, but all it would've taken was three clicks. Read on to learn about how the attack works, how to protect yourself, and some basic malware analysis🕵️
2/ The first step is to create an urgent and compelling hook. When placed under pressure, even trained security professionals might act instinctively instead of rationally. This DM does both.

If you clicked the link, then you're only two clicks away from being pwned
3/ Clicking the link automatically downloads this file to your computer. Once again, this is compelling - who is cryptogeng.eth, and what exactly does the statement claim?

If you open the download, then you're one click away from being pwned
Read 17 tweets
Mar 24
I need to make a correction! Thanks to @madergaser and @siintemal for pointing out that I completely missed the other half of the exploit.

So as I mentioned earlier, the two token accounts must hold the same token. The attacker forged accounts to bypass the validation on common.crate_collateral_tokens, but what about depositor_source?

Well, the depositor_source has to use the same token as common.collateral. Image
Read 7 tweets
Mar 23
Another day, another Solana fake account exploit. This time, @CashioApp lost around $50M (based on a quick skim). How did this happen? Image
In order to mint new CASH, you need to deposit some collateral. This cross-program invocation (CPI) will transfer tokens from your account to the protocol's account, but only if the two accounts hold the same type of token. Otherwise, the token program will reject the transfer. Image
Here, the protocol validates that the crate_collateral_tokens account hold the right type of token by comparing it with the collateral account. It also verifies the collateral account shares the same token type as the saber_swap.arrow account. Image
Read 7 tweets
Feb 3
How did the @wormholecrypto exploit work? I joined forces with @gf_256 and @ret2jazzy to reverse engineer the exploit, and now that it's been patched we can finally share it with you👇 Image
First, we had to determine where the exploit occurred. Ethereum, or Solana? A quick check of the encoded VM that the attacker submitted showed that it contained valid signatures from the guardians. This meant that either they got the private keys, or they exploited the bridge. Image
Given that the attackers had left over $600MM in tokens in the bridge, I figured that the latter was more likely. Sure enough, there was a corresponding transaction on Solana where the attacker bridged out the ETH.

solscan.io/tx/5UaqPus91wv… Image
Read 15 tweets

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just two indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3/month or $30/year) and get exclusive features!

Become Premium

Don't want to be a Premium member but still want to support us?

Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal

Or Donate anonymously using crypto!

Ethereum

0xfe58350B80634f60Fa6Dc149a72b4DFbc17D341E copy

Bitcoin

3ATGMxNzCUFzxpMCHL5sWSt4DVtS8UqXpi copy

Thank you for your support!

Follow Us on Twitter!

:(