此次攻击由 VETH 合约漏洞造成,合约代码的函数访问修饰符的错误使用导致任何人都能绕过授权转账额度的检查,以极低的成本发起攻击。

原文标题:《成都链安:VETH 智能合约被攻击事件分析》
撰文:成都链安

2020 年 6 月 30 日下午 5:46,Beosin-OSINT 威胁情报系统发现 VETH 智能合约

0x75572098dc462F976127f59F8c97dFa291f81d8b

遭受攻击,被盗 919299 个 VETH。成都链安-安全研究团队第一时间对本次事件进行跟踪分析。

根据链上交易显示:攻击者利用自建合约

0x47ed415006c6f8052fff05fe983f31d6d24b8fdb

通过 Uniswap 将 0.9 ETH 兑换为 138 VETH,之后对 VETH 智能合约

0x75572098dc462F976127f59F8c97dFa291f81d8b

发起攻击,在攻击完成后自建合约进行自我销毁。

本次攻击成本仅 0.9 ETH,约合 200 美元。交易 hash:

0xdd1120a90ed4112b634266d6a244b93ca86785317bc75f0e170ab0cd97c65224

详情如下:

成都链安:技术分析 VETH 智能合约被盗  90 万美元代币过程图 1

在盗币成功之后,攻击者将盗取的 VETH 通过 Uniswap 换成了 16 ETH。如下图所示:

成都链安:技术分析 VETH 智能合约被盗  90 万美元代币过程图 2

具体攻击流程如下:

  1. 攻击者创建攻击合约,通过 Uniswap 将 0.9 ETH 兑换成 138 VETH;
  2. 调用 VETH 合约 changeExcluded 函数,支付 128 VETH 手续费,使 mapAddress_Excluded[excluded] 的值为 true;
  3. 调用 transferFrom 函数,因 mapAddress_Excluded[excluded] 的值为 true,可以直接进行转账;
  4. 攻击完成后,攻击者通过 Uniswap 将盗取的 VETH 兑换成 16 ETH。

漏洞原理分析

此漏洞产生的主要原因是 changeExcluded 函数修饰符为 external,使得任何人都可以调用该函数来绕过 transferFrom 函数内部的授权转账额度检查,将合约的 VETH 代币盗走。

首先分析 transferFrom 函数,在函数内部先进行 !mapAddress_Excluded[msg.sender] 的判断,按照正常逻辑,该结果为 true 后,将进行授权转账额度的检查。但是转账函数 _transfer 的调用放在 if 语句体外,这就导致攻击者可以通过将 mapAddress_Excluded[msg.sender] 的值设置为 true 而绕过授权转账额度的检查,直接进行 VETH 代币转移。transferFrom 函数源码如下图所示:

成都链安:技术分析 VETH 智能合约被盗  90 万美元代币过程图 3

通过分析修改 mapAddress_Excluded[msg.sender] 值的代码发现,在 changeExcluded 函数内实现了对其值的修改,且该函数修饰符为 external,可供外部调用。changeExcluded 函数源码如下图所示:

成都链安:技术分析 VETH 智能合约被盗  90 万美元代币过程图 4

在未对该值进行设置时,mapAddress_Excluded[excluded] 的初始值为 false,最后 if 判断结果为 true,进入 if 语句体,调用 _transfer 进行转账,要求支付转账金额为:mapEra_Emission[1]/16 (跟进 mapEra_Emission[1] 的来源 emission,得知其值为 2048*1018)即 128 VETH,然后 mapAddress_Excluded[excluded] 的值被设置为 true。emission 的值如下如所示:

成都链安:技术分析 VETH 智能合约被盗  90 万美元代币过程图 5

至此,再配合上面的 transferFrom 函数,攻击者便可实现仅花费 128 VETH 而将被攻击合约的 VETH 代币全部转移出去。

总结

此次 VETH 被盗事件,漏洞出自 VETH 合约而非 Uniswap,VETH 合约代码的函数访问修饰符的错误使用导致任何人都能绕过授权转账额度的检查,以极低的成本发起攻击。成都链安-安全研究团队在此提醒各大智能合约运营商,在合约正式部署上线前应做好充分的代码审计工作,即使是一些简单的代码错误也会财产损失。