The analysis of Nomad cross-chain bridge exploitation
According to Go+ researcher Ben, at least 90M was hacked in Nomad cross-chain bridge exploitation.
The exploitation is relatively simple: any operation can be interpreted as valid because of the wrong usage of Merkle root. This means anyone can copy&paste the hacker’s transaction to steal funds from the bridge.
In this tx, the hacker just called process() in Replica.sol. Once you passed these three requires, the specified operations will be processed by NomadBridge.handle(). https://tools.blocksec.com/tx/eth/0xc4938e6f6368061194d076d44f73a8cae3a318b1ee7cf8b026abe10b7c206c2a
All the requires passed. The first and third ones are obvious, so check the second one: acceptableRoot(messages[_messageHash]). messages[_messageHash] = 0x0, because the message was forged by the hacker(non-existent in this contract’s history).
In a mapping, it will be 0 by default. LEGACY_XXXX = 1 or 2, irrelevant here. Next is confirmAt[_root], as long as it != 0 and < current block time then the check will pass. So what’s the value of confirmAt[0x0] ?
Wrong initialisation param: confirmAt[_committedRoot] = 1. They passed _committedRoot = 0x0 while initialising the contract. So confirmAt[0x0]=1. Check passed.
That is to say, anyone can forge any message to steal funds from the bridge. You can even copy&paste data from the hacker and modify the receiver.