nomad漏洞分析

攻击信息
部分攻击交易 0x96a2cfadb19cac9ba2a21c1f32b6f21b6132afe1b4f4698dee563ca01ec20e01 转移 USDC
0x811a54270e38154c30e65bdb8ee484883f5a9659dd16f1a335f9ff8f7eee342f 转移 WETH
0x12efbc03ecc8d56ebbadd637dbfc30c0d709b463e2c831034233427dfaecf777 转移 FRAX
0xc78bc10c77ca92693513e5b97b4a0063167ca8488b019f6b740bc9f8cad103bf 转移 CQT
0x8c65b2b25be2c929d86f1fb556aa0b981bd54c2ad54d8de63d3876c4c833293e 转移 DAI
0x5304e01a4cb926523f681bc34a8b71a1dfae35b5a5159f78aecc7f685f42422c 转移 CARDS
被攻击合约
0xB92336759618F55bd0F8313bd843604592E27bd8 Replica
漏洞分析
漏洞关键点为process中的这一行
require(acceptableRoot(messages[_messageHash]), "!proven");
这里acceptableRoot的输入为0x0000000000000000000000000000000000000000000000000000000000000000
难道这个函数结果是否返回true?可以绕过require判断嘛?带着疑问跟进acceptableRoot函数

这里_root肯定是不满足这两个条件
bytes32 public constant LEGACY_STATUS_PROVEN = bytes32(uint256(1));
bytes32 public constant LEGACY_STATUS_PROCESSED = bytes32(uint256(2));关键是这个_time只要不等于0就行。那么要跟进confirmAt[_root]。
全局搜索confirmAt发现在initialize中有赋值操作。

那我们要看看这个_committedRoot是个啥? 时间回到41天之前,在这个交易中 Ethereum Transaction Hash (Txhash) Details | Etherscan

_committedRoot就是我们上面的000000。那么上面的_time满足条件。不为0。acceptableRoot也会返回true。从而绕过这个require
Last updated