Binance Chain Bridge Exploitation Writeup - Part 2
This is the second part of our analysis on Binance Chain's bridge hack, focus on hacker transactions and exploitation payloads.
by Verichains Team
This is the second part of our analysis on Binance Chain’s bridge hack, focus on hacker transactions and exploitation payloads. This analysis also answers @samczsun's questions in his early tweets, in which he wondered how the attacker's payload was much shorter than his me.
Transaction details
The hacker transaction is at https://bscscan.com/tx/0xebf83628ba893d35b496121fb8201666b8e09f3cbadf0e269162baa72efe3b8b. Decoding the transaction data, we got the following arguments that will be passed to the function handlePackage of CrossChain.sol smart contract (link):
0 payload bytes 0x000000000000000000000000000000000000000000000000000000000000000000f870a0424e4200000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000008ad3c21bcecceda100000094489a8756c18c0b8b24ec2a2b9ff3d4d447f79bec94489a8756c18c0b8b24ec2a2b9ff3d4d447f79bec846553f100
1 proof bytes 0x0a8d020a066961766c3a76120e00000100380200000000010dd85c1af201f0010aed010a2b0802100318b091c73422200c10f902d266c238a4ca9e26fa9bc36483cd3ebee4e263012f5e7f40c22ee4d20a4d0801100218b091c7342220e4fd47bffd1c06e67edad92b2bf9ca63631978676288a2aa99f95c459436ef632a20da657c1ffb86c684eb3e265361ef0fa4f9dfa670b45f9f91c5eb6ad84b21a4d112001a370a0e0000010038020000000000000002122011056c6919f02d966991c10721684a8d1542e44003f9ffb47032c18995d4ac7f18b091c7341a340a0e00000100380200000000010dd85c12202c3a561458f8527b002b5ec3cab2d308662798d6245d4588a4e6a80ebdfe30ac18010ad4050a0a6d756c746973746f726512036962631ac005be050abb050a110a066f7261636c6512070a0508b891c7340a0f0a046d61696e12070a0508b891c7340a350a08736c617368696e6712290a2708b891c7341220c8ccf341e6e695e7e1cb0ce4bf347eea0cc16947d8b4e934ec400b57c59d6f860a380a0b61746f6d69635f7377617012290a2708b891c734122042d4ecc9468f71a70288a95d46564bfcaf2c9f811051dcc5593dbef152976b010a110a0662726964676512070a0508b891c7340a300a0364657812290a2708b891c73412201773be443c27f61075cecdc050ce22eb4990c54679089e90afdc4e0e88182a230a2f0a02736312290a2708b891c7341220df7a0484b7244f76861b1642cfb7a61d923794bd2e076c8dbd05fc4ee29f3a670a330a06746f6b656e7312290a2708b891c734122064958c2f76fec1fa5d1828296e51264c259fa264f499724795a740f48fc4731b0a320a057374616b6512290a2708b891c734122015d2c302143bdf029d58fe381cc3b54cedf77ecb8834dfc5dc3e1555d68f19ab0a330a06706172616d7312290a2708b891c734122050abddcb7c115123a5a4247613ab39e6ba935a3d4f4b9123c4fedfa0895c040a0a300a0361636312290a2708b891c734122079fb5aecc4a9b87e56231103affa5e515a1bdf3d0366490a73e087980b7f1f260a0e0a0376616c12070a0508b891c7340a300a0369626312290a2708b891c7341220e09159530585455058cf1785f411ea44230f39334e6e0f6a3c54dbf069df2b620a300a03676f7612290a2708b891c7341220db85ddd37470983b14186e975a175dfb0bf301b43de685ced0aef18d28b4e0420a320a05706169727312290a2708b891c7341220a78b556bc9e73d86b4c63ceaf146db71b12ac80e4c10dd0ce6eb09c99b0c7cfe0a360a0974696d655f6c6f636b12290a2708b891c73412204775dbe01d41cab018c21ba5c2af94720e4d7119baf693670e70a40ba2a52143
2 height uint64 110217401
3 packageSequence uint64 17684572
4 channelId uint8 2Where:
payloadcontains information about the cross-chain transfer (of course it did not actually happen) including BSC recipient address and token amount which the attacker has set to his/her own address and 1 million BNB respectively.proofis an IAVL/Merkle proof that asserts the integrity ofpayload.heightis (at least) the BC (not BSC) block height at which the transfer occurred. TheappHashof BC corresponding toheightwill be retrieved for verifyingproof.packageSequenceacts like a TCP sequence number to assure that packages relayed to BSC can not be replayed and arrive in order.channelIdis routing information that is used to select the next appropriate contract to handle the package payload after its verification succeeds. Here,channelId == 2indicates a cross-transfer (BC to BSC) package which should be handled by theTokenHub.solcontract (link).
The way BC to BSC cross-chain communication works is that every-time a package needs to be sent to BSC, a key will be constructed from packageSequence and channelId, and its associated value, which is essentially the package payload, will be stored in the verifiable key-value store of BC and thus, updating BC appHash. Later on, the package is relayed to BSC together with proof that proves the correctness of the corresponding key-value pair in BC store. This is basically the light-client technique for cross-chain communication.
Next, we will analyze proof.
Proof details
proof essentially contains 2 parts.
The first part regards to the multistore architecture of BC. Basically, BC appHash is the hash of all its sub-store root hashes, including the one named ibc (short for Inter-Blockchain Communication) in which the key-value pair mentioned earlier is actually stored. proof carries all the sub-store hashes so ibc root hash could be verified against appHash. Compared with a valid proof, the attacker did not change this part.
The second part is about proving that a leaf containing key-value does actually exist in ibc IAVL tree given its root hash. The technique used to forge this part has been described earlier. Please notice that both Left and Right fields of Proof.LeftPath[1] are filled:
Based on LeftPath, we deduce that the ibc tree snapshot at BC block height 110217401 looks like this:
And the malicious second part is as follows:
So, the BC block height 110217401 chosen by the attacker is likely for minimizing the proof size as the ibc tree at that time had only a few nodes. Maybe it helped reduce some gas cost when submitting the malicious transaction, or the attacker just prefers a concise proof over longer ones.
This analysis also answers @samczsun's questions in his early tweets, in which he wondered how the attacker's payload was much shorter. As long as the IAVL tree contains at least 2 leafs, the attack is already feasible. Therefore, the proof could be made short, and the attacker chose to do so.






