PANews 7月11日消息,慢雾安全团队对此前7月10日OMNI Protocol闪电贷攻击事件进行了分析:1. 攻击者首先通过supplyERC721函数抵押doodle, 抵押后合约会给攻击者相应的凭证NToken;2. 调用borrow函数借出WETH;3. 调用withdrawERC721尝试提取NFT, 跟进到内部函数executeWithdrawERC721发现,提款会先通过burn函数去燃烧凭证而 burn 函数中的 safeTransferFrom 函数会去外部调用接收地址的 OnERC721Received 函数,攻击者利用这点重入了合约的liquidationERC721函数;4. 在liquidationERC721函数中,攻击者先支付了WETH并接收doodle nft,接着通过判断后会调用_burnCollateralNTokens函数去燃烧掉对应的凭证,同样的利用了burn函数外部调用的性质攻击者再次进行了重入操作, 先是抵押了清算获得的nft,接着调用borrow函数去借出了81个WETH,但由于vars变量是在liquidationERC721函数中定义的,因此第二次借款不会影响到liquidationERC721函数中对用户负债的检查,这导致了攻击者可以通过userConfig.setBorrowing函数将用户的借款标识设置为false即将攻击者设置成未在市场中有借款行为;5. 在提款时会首先调用 userConfig.isBorrowingAny() 函数去判断用户的借款标识,假如借款标识为 false,则不会判断用户的负债,故此重入后的81 WETH的负债并不会在提款时被判断,使得攻击者可以无需还款则提取出所有的NFT获利
此次攻击的主要原因在于burn函数会外部调用回调函数来造成重入问题,并且在清算函数中使用的是旧的vars的值进行判断,导致了即使重入后再借款,但用户的状态标识被设置为未借款导致无需还款。慢雾安全团队建议在关键函数采用重入锁来防止重入问题。