2022 年10 月 6 日,最大的加密货币交易所币安旗下的 BSC Token Hub 桥(以下简称 BSC)遭到黑客攻击。这是有史以来最大的加密货币黑客攻击之一。BSC 确保币安用于去中心化管理(堆叠、投票)的币安信标链区块链与币安智能链(用于创建各种去中心化应用程序的与 EVM 兼容的区块链)之间的交互。黑客从桥接协议中提取了 200 万个 BNB(币安的加密货币),其中 1 个 BNB 当时价值 293 美元。总计 5.86 亿美元被盗。
区块链桥用于在异构区块链之间传输数据和资产。它们充当发送交易的中介,因此您是否信任从区块链 A 发送到区块链 B 的交易取决于 A 和 B 之间的桥梁。要信任区块链 A 提供的交易,桥梁需要对其进行验证。根据桥接逻辑的不同,验证交易的方法有多种,但它们都取决于数据在区块链中的记录和存储方式,即数据表示的树状结构。
二叉树的每个节点都是其两个子节点的哈希值的串联。与添加到区块链的交易相对应的树的末端节点称为叶子,顶部的根节点称为根。这种树状的数据表示结构称为二叉搜索树,它允许您轻松检查任何树节点中记录的数据的合法性(作者身份)和完整性。知道要检查的数据的哈希值以及计算根哈希值时使用的中间节点的值,您可以执行 Merkle 证明:从节点的底部开始,检查每个连续的哈希值是否正确,直到根。任何差异都表明节点中的数据已被篡改。
BSC 桥使用平衡 AVL 树(一种二叉搜索树)来验证交易。对于这棵树的每个节点,其两个分支的高度相差不超过1。验证算法在主CrossChain智能合约的handlePackage函数中调用,该函数处理区块链之间的代币传输。
handlePackageBSC主智能合约中的函数声明
该函数还包含修饰符onlyRelayer,这意味着只有中继器可以调用该函数。
网桥中的中继器处理来自区块链 A 的特殊格式的数据包,从中提取必要的参数,并将其转换到网络以传输到区块链 B。要注册为中继器,需要存入 100 个 BNB 代币并配置设备按照配置文件连接到区块链。注册后,中继器开始解析每个网络块的 endBlock 事件表中的数据,并从中选择所有 IBCPackage 事件。
交易验证请求的结构
value参数有四个属性,用“::”分隔:
第一个属性是目标链名称;在此示例中为“bsc”。
第二个属性是目的链的CrossChainID;在本例中为“2”。
第三个属性是频道id;在本例中为“8”。
第四个属性是顺序;在此示例中为“19”。
处理完该事件后,中继器会处理从区块链 A 发送到区块链 B 的包含交易的数据包。中继器从数据包中提取以下参数:
参数名称 | 尺寸 | 价值 |
---|---|---|
字首 | 1字节 | 0x00 |
源链CrossChainID | 2字节 | 交易源区块链ID |
目的链CrossChainID | 2字节 | 交易目的地区块链ID |
通道ID | 1字节 | IBCPackage 事件通道 ID |
顺序 | 8字节 | IBCPackage 事件序列号 |
handlePackage接下来,中继器将这些参数、交易数据、交易验证标志(证明)和区块高度发送到调用CrossChain 合约函数的特殊 RPC 请求:
RPC 请求handlePackage功能
handlePackage函数中调用了MerkleProof库validateMerkleProof的函数;使用0x65处的方法,调用预编译的合约。该合约是一个用 Go 编写的库,它具有许多实现 Merkle 证明功能的 Cosmos 跨链框架的依赖项(方法)。staticcalliavlMerkleProofValidate
MerkleProof 库
iavlMerkleProofValidate这些依赖项在字符串 8、9 和 16 中的合约Run 函数中调用:
iavlMerkleProofValidate预编译合约的run函数
调用的op.Proof.ComputeRootHash()方法计算包含正在检查的事务的树叶的 AVL 树根哈希。接下来,该op.Proof.Verify(root)方法将 AVL 树根的哈希值与上一步计算的哈希值进行比较。如果比较的哈希值不同,该op.Proof.Verify(root)方法将返回错误,并且从区块链 A 到区块链 B 的交易传输将被取消。如果哈希值相同,则op.Proof.VerifyItem(op.key, value)调用该方法,在该方法中检查 AVL 树中是否存在交易数据哈希值。如果找到哈希值,则交易被视为有效并被执行。
交易验证过程的漏洞与计算和检查交易的树根哈希的方式有关。该ComputeRootHash函数调用该pwl.Leaf.Hash()方法:
HashcomputeRootHash函数中的函数调用
Hash当正在检查的交易的 Merkle 证明链中的左叶等于 0(即未定义)时,该函数会正确计算根哈希。但如果定义了左叶,则计算树根哈希时不考虑右叶。换句话说,如果定义了所检查交易的 Merkle 证明链中的左叶,则树根哈希的值将不依赖于证明链中右叶的存在。
根哈希计算中的漏洞
该缺陷允许攻击者将有效负载写入右叶并成功通过树根哈希值检查,前提是有效负载哈希计算正确。
在开始攻击之前,犯罪分子将100 BNB存入Relayer Hub合约,以注册为 BSC 桥接中继器。
他们使用了两年前从 BSC 桥上转移 0.05 BNB 的合法交易。他们通过将攻击者地址指定为接收者来更改有效负载,并将金额更改为 100 万 BNB:
原始交易 | 攻击者交易 | |
---|---|---|
有效载荷 | 0x00000000000000000000000000000000000 00000000000000000038d7ea4c68000f86da0 424e420000000000000000000000000000000 000000000 0000000000000000009400000000 0000000000000000000000000000000087b1a2bc2ec50000944e656459ed25bf986eea1196bc1b00665401645d94a10123c15a63135fe945a54232bae7fac8177056845FD12999 | 0x00000000000000000000000000000000000 0000000000000000000000000000000f870a0 424e420000000000000000000000000000000 0000000 000000000000000000009400000000 000000000000000000000000000000008ad3c21bcecceda100000094489a8756c18c0b8b24ec2a2b9ff3d4d447f79bec94489a8756c18c0b8b24ec2a2b9ff3d4d447f79bec846553f100 |
有效负载内容是以RLP格式编码的结构:
RLP编码视图结构
接下来,攻击者通过将带有有效负载哈希的右叶添加到AVL树来修改证明变量内容,并添加一个空的内部主机来平衡AVL树:
原始交易证明结构 | 攻击者交易证明结构 |
---|---|
RangeProof{ LeftPath: PathToLeaf{ 0:proofInnerNode{ 高度:1 尺寸:3 版本:110217392 左: 0C10F902D266C238A4CA9E26FA9BC36483CD3 EBEE4E263012F5E7F40C22EE4D2 右: } 1:proofInnerNode{ 高度:-1 尺寸:2 版本:110217392左 : E4FD47BFFD1C06E67EDAD92B2BF9CA63631978676288A2AA99F95C459436EF63 右: } } 内部节点: 叶子: proofLeafNode{ 密钥: 0000010038020000000000000002 ValueHash: 11056C6919F02D966991C10721684A8D1542E44003F9FFB47032C18995D4AC7F 版本:110217392 }(rootVerified):true (rootHash): E09159530585455058CF1785F411EA4 4230F39334E6E0F6A3C54DBF069DF2B62(treeEnd):真 } | RangeProof{ LeftPath: PathToLeaf{ 0:proofInnerNode{ 高度:1 尺寸:3 版本:110217392 左: 0C10F902D266C238A4CA9E26FA9BC36483CD3 EBEE4E263012F5E7F40C22EE4D2 右: } 1:proofInnerNode{ 高度:-1 尺寸:2 版本:110217392左 : E4FD47BFFD1C06E67EDAD92B2BF9CA63631978676288A2AA99F95C459436EF63 右: DA657C1FFB86C684EB3E265361EF0FA4F9DFA670B45F9F91C5EB6AD84B21A4D1 内部 节点 : 空路径到叶子 叶子: proofLeafNode{ 密钥: 0000010038020000000000000002 ValueHash: 11056C6919F02D966991C10721684A8D1542E44003F9FFB47032C18995D4AC7F 版本:110217392 } proofLeafNode{密钥: 00000100380200000000010DD85CValueHash:2C3A561458F8527B002B5EC3CAB2D308662798D6245D4588A4E6A80EBDFE30AC版本:1} (rootVerified): true (rootHash): E09159530585455058CF1785F411EA44230F39334E6E0F6A3C54DBF069DF2B62 (treeEnd): true } |
由于该漏洞,添加的右叶内容不会影响根哈希,因此欺诈交易被成功验证。检查交易后,CrossChain 合约调用函数将 100 万 BNB 从 BSC 转移到攻击者地址。接下来,攻击者尝试重复交易,但接下来的 15 次尝试均因值不正确而失败packageSequence。然而,在第 16次尝试中,他们成功找到了正确的packageSequence值,并在他们的地址获得了另外 100 万个 BNB。
接下来,由于担心BSC中的资产被冻结和封锁,攻击者开始从桥上提款。为了洗钱,他们使用了Venus Finance DeFi:他们发行了包装好的vBNB代币来换取BNB,并使用vBNB作为抵押品借出了币安的稳定币BUSD。接下来,攻击者使用 Stargate 和 Anyswap 桥将 BUSD 转换为多个区块链中的 USDT 和 USDC 稳定币:Ethereum、Avalanche、Fantom、Polygon、Arbitrum 和 Optimism。
被盗资金洗钱链
在发现攻击后,币安暂停并分叉了 BSC 区块链,阻止攻击者提取超过 4 亿美元。随后,USDT稳定币的所有者Tether封锁了攻击者的USDT地址,阻止他们洗掉部分被盗资金。攻击者地址已被列入黑名单:
攻击者地址已添加到BSC黑名单中
最初,AVL树验证方法假设只能为要验证的交易定义树的右叶或左叶。然而,AVL树检查算法中最初缺少对左右叶子是否同时存在的检查,而攻击者利用了这一点。
黑客入侵后不久,Cosmos 跨链框架的 AVL 证明方法引入了修复:
Cosmos框架AVL证明方法漏洞修复后的变化
如果AVL树的左叶和右叶同时存在,则交易验证将被拒绝并出现相应的错误。
Binance Smart Chain Token Hub 桥接器黑客攻击是利用第三方组件中的漏洞的一个示例,桥接器使用该第三方组件来确定交易是否可以信任、执行或拒绝。尽管该漏洞存在于第三方组件中,但它给 BSC 桥带来了巨大的财务损失。显然,在修复之前,该漏洞也存在于其他使用 Cosmos 跨链框架的 AVL 证明方法的 DeFi 协议中。然而,根据从BSC窃取的资金数额,我们可以假设攻击者从一开始就是为了中大奖,知道漏洞修复后他们不会再有第二次机会。
承接以下业务:
欢迎添加微信业务咨询: