一、 事件简述
8 月 5 日凌晨四点,有用户在 opyn 论坛反馈自己的账户余额无故消失,并有用户发现可疑的交易信息,如下图所示:
Opyn 项目方再对情况初步分析后做出回应表示:已经转移了资金,并正在寻找问题原因。
截至发稿前,官方发文回应此次事件:遭到黑客攻击,并已对可能遭受攻击的资产进行转移,但此次漏洞只涉及 ETH 合约,并不影响其他合约。如下图所示:
成都链安 - 安全实验室第一时间对本次事件进行跟踪分析,以下是态势感知系统检测盗的攻击者合约地址:
0xe7870231992ab4b1a01814fa0a599115fe94203f
0xb837531bf4eb8ebfa3e20948bd14be067c18cbd3
0xb72e60ea1d0c04605f406c158dce9ac6ae6d224c
攻击者攻击方式还原:
1、 攻击者调用合约向合约发送 n 个 USDC 增加抵押,并得到合约币 oETH
2、 攻击者调用合约发送 ETH 进行抵押,并销毁 oETH 以赎回自己的 USDC
3、 攻击者赎回自己抵押的 ETH 。
如下图所示:
在步骤二中,攻击者调用 exercise 函数,并向其传递了两个地址 A (攻击者自己地址)、 B (他人未赎回 USDC 的地址)和两倍自己应得的 USDC ,程序正常执行,这导致地址 B 的资金受损。
二、 技术分析
以交易 0x56de6c4bd906ee0c067a332e64966db8b1e866c7965c044163a503de6ee6552a 为例,攻击者通过合约 0xe7870231992ab4b1a01814fa0a599115fe94203f 对合约 0x951D51bAeFb72319d9FBE941E1615938d89ABfe2 发动攻击,此笔交易中共获利 $9907 。如下图所示:
攻击者首先调用了 addERC20CollateralOption 函数,向合约中发送了 9900 个 USDC ,如下图所示:
此函数中的 addERC20Collateral(msg.sender, amtCollateral); 负责代理转账 USDC ;函数中的 issueOTokens(amtToCreate, receiver); 负责铸币 oETH ,此笔交易铸币 30 个 oETH 并发送给了攻击者,如下图所示:
在此完成后,攻击者的 vault 参数进行了变化。 vault.oTokensIssued 和 vault.collateral 分别更新 300000000 和 9900000000 为如下图所示:
然后攻击者开始将 oETH 兑换出来。
调用 exercise ,构造参数 oTokensToExercise 为 60 , vaultsToExerciseFrom 为两个地址,其中一个是也满足条件的他人地址。如下图所示:
Exercise 函数运行 _exercise(vault.oTokensIssued, vaultOwner); 分支,将 30oETH 相应比例的 USDC 发送给调用者,如下图所示:
我们可以注意到,在最终转账时, _exercise 是将 USDC 转给了 msg.sender, 也就是攻击者。
我们回头看 exercise 中存在者 for 循环,攻击者输入的 oTokensToExercise 为 60 ,所以合约再验证了第二个地址符合条件的情况下,依旧会将余额转给 msg.sender, 也就是攻击者。这就使得攻击者可以获得两次 USDC ,从而获得利润。
总结建议
此次事件攻击者利用了 exercise 函数的逻辑缺陷。此函数在进行最后转账前并未验证调用者是否有权限赎回此地址的 USDC ,只是简单的验证了地址是否可以赎回。属于代码层的逻辑漏洞,并且根据官方回复,此合约是经过安全审计的。成都链安在此提醒各项目方:
1、 项目上线前应当进行足够有效的安全审计,最好是多方审计
2、 对于合约的应当设置暂停合约交易等功能,在发生安全事件时,可以以保证资金安全
3、 安全是一个持续的过程,绝非一次审计就能保平安,与第三方安全公司建立长期的合作至关重要
