Aurora销毁逻辑错误导致代币窃取漏洞
langu_xyz

跨链桥-RainBow Bridge

Rainbow Bridge 不要求用户信任任何东西,除了区块链本身,称之为无信任。任何在 NEAR 上加密可证明的信息都可用于以太坊合约,反之亦然。

例如以下信息:

•    将交易包含在区块中;
•    执行具有特定结果的交易;
•    合约的状态。

桥的设计

桥背后的核心思想是它实现了两个轻客户端: 
1. 作为 NEAR 合约在 Rust 中实现的以太坊轻客户端
2. 作为以太坊合约在 Solidity 中实现的 NEAR 轻客户端

处理流程

https://near.org/blog/eth-near-rainbow-bridge/

1.    假设 Alice 想在 NEAR 区块链上将 X DAI 转给 Bob,她从 RainbowCLI/RainbowLib 发起转账;
2.    RainbowLib 首先设置允许将 X DAI 从 Alice 转移到 TokenLocker;
3.    然后它调用 TokenLocker 获取那些令牌,导致 TokenLocker 发出事件“Alice locked X tokens in favor of Bob”;
4.    RainbowLib 然后等到 EthOnNearClient 收到包含此事件的以太坊标头,再加上 25 个区块进行确认;
5.    然后 RainbowLib 计算这个事件的证明并提交给 MintableFungibleToken 合约;
6.    MintableFungibleToken 合约然后通过调用 EthOnNearProver 来验证这个证明是否正确;
    6.1.    EthOnNearProver 反过来验证证明的标头是否在 EthOnNearClient 的规范链上,并且它具有所需的确认次数。它还验证证明本身;
    6.2.    MintableFungibleToken 然后解包以太坊事件并为 Bob 铸造 X nearDAI,完成转账。

漏洞代码分析

根据这个漏洞的基本信息,错误提交是漏洞的核心,先来看一下EthCustodian的withdraw函数是如何实现的。

提取编码在’ proofData ‘中的适当数量的ETH,利用_parseAndConsumeProof对proofData进行解码。

https://etherscan.io/address/0x6BFaD42cFC4EfC96f529D786D643Ff4A8B89FA52#code#F1#L116

https://etherscan.io/address/0x6BFaD42cFC4EfC96f529D786D643Ff4A8B89FA52#code#F5#L45

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
function _parseAndConsumeProof(
bytes memory proofData,
uint64 proofBlockHeight
)
internal
returns(ProofDecoder.ExecutionStatus memory result)
{
require(
proofBlockHeight >= minBlockAcceptanceHeight_,
'Proof is from the ancient block'
);
require(
prover_.proveOutcome(proofData,proofBlockHeight),
'Proof should be valid'
);

// Unpack the proof and extract the execution outcome.
Borsh.Data memory borshData = Borsh.from(proofData);

ProofDecoder.FullOutcomeProof memory fullOutcomeProof =
borshData.decodeFullOutcomeProof();

require(
borshData.finished(),
'Argument should be exact borsh serialization'
);

bytes32 receiptId =
fullOutcomeProof.outcome_proof.outcome_with_id.outcome.receipt_ids[0];

require(
!usedEvents_[receiptId],
'The burn event cannot be reused'
);
usedEvents_[receiptId] = true;

require(
keccak256(fullOutcomeProof.outcome_proof.outcome_with_id.outcome.executor_id) ==
keccak256(nearProofProducerAccount_),
'Can only withdraw coins from the linked proof producer on Near blockchain'
);

result = fullOutcomeProof.outcome_proof.outcome_with_id.outcome.status;
require(
!result.failed,
'Cannot use failed execution outcome for unlocking the tokens'
);
require(
!result.unknown,
'Cannot use unknown execution outcome for unlocking the tokens'
);
}

从这里keccak256(fullOutcomeProof.outcome_proof.outcome_with_id.outcome.executor_id) == keccak256(nearProofProducerAccount_)可以看到会校验executor_id和nearProofProducerAccount_是否相等,也就是eth和near对应的合约是否一致。

从Aurora的代码里找到对应的部分看下如何实现的。

let mut executor = executor_params.make_executor(self);是这个漏洞的关键,可以看到Aurora将自己设置为了executor。

这时候我们模拟流程看一下会发生什么。

经过EthCustodian.sol初始处理后,会生成如下的数据包:

包含了要发送的ETH数量、ETH的接收账户、执行此操作的地址。

1
2
3
4
require(
result.ethCustodian == address(this),
'Can only withdraw coins that were expected for the current contract'
);

在withdraw中验证result.ethCustodian是否等于BurnResult.ethCustodian,如果相等,则执行合约转账。

当ETH侧发起转账时,Aurora侧withdraw_eth_from_near的会进行处理。

同时重新定义了BurnResult数据结构如下:

在 withdraw函数中直接调用了withdraw_eth_from_near函数,如下

然后进一步跟踪withdraw_eth_from_near,最终在internal_withdraw_eth_from_near函数中实现了Near代币销毁。

以上就是Near向ETH跨链发送代币的流程。

那么如何利用漏洞来实现向ETH发送代币而不在Near链上销毁代币呢?

在上文中分析过,ETH侧会判断执行者id和Aurora 合约发起地址匹配,如果可以将Aurora 合约发起地址设置为Aurora合约本身,就可以不需要销毁代币从而窃取ETH了。

从Aurora的代码寻找会将自己设置为执行id的函数,在代码中我们找到三处,分别是deploy、call、view函数。

所以攻击链就有了:

0.    创建一个合约Evil进行跨链转币,进行数据封装
0.    用view函数去调用Evil合约(理论上查看合约就可以触发)
0.    这时候executor_id就是Aurora合约本身
0.    自动化批量调用实现

当前的修复方式是验证Evil中的EthCustodian是否等于Evil自身的EthCustodian。

修复代码:

https://medium.com/immunefi/aurora-withdrawal-logic-error-bugfix-review-c5b4e30a9160

https://github.com/aurora-is-near/aurora-engine/commit/7109e30926ea33f67c6f702aa2b796b025cca96a

https://etherscan.io/address/0x6BFaD42cFC4EfC96f529D786D643Ff4A8B89FA52#code

  • Post title:Aurora销毁逻辑错误导致代币窃取漏洞
  • Post author:langu_xyz
  • Create time:2022-11-23 21:00:00
  • Post link:https://blog.langu.xyz/Aurora销毁逻辑错误导致代币窃取漏洞/
  • Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.