背景
2020年8月5日,opyn contract遭到黑客攻击。接到情报后,慢雾安保小组对袭击进行了全面分析。以下是对此攻击的详细技术分析。
攻击细节
逻辑分析
看看其中一个攻击交易:
https://ETHerscan.io/tx/0xa858463f30a08c6f3410ed456e59277fbe62f14225754d2bb0b4f6a75fdc8ad
通过查看内联事务,我们可以看到攻击者只使用了272ETH,**得到了467ETH
利用Oko合同浏览器分析具体的攻击细节
https://oko.palkeo.com/0xa858463f30a08c6f3410ed456e59277fbe62f14225754d2bb0b4f6a75fdc8ad/
关键在于行使合同的功能。从上图可以看出,通过在exERCise函数中调用transfer两次,将USDC发送给攻击者合同。接下来,我们将分析练习功能
函数练习(uint256 oTokensToExERCise,地址:payable[]memory vaultsToExERCiseFrom)公共支付{用于(uint256 i=0;ilt;从长度开始练习的拱顶;i++){地址payable vaultOwner=vaultsToExERCiseFrom[i];require(hasVault(vaultOwner),“无法从不存在的保险库中进行练习”);保险存储保险库=保险库[vaultOwner];if(oTokensToExERCise==0){return;}else if(vault.otokensis发布gt;=oTokensToExERCise){练习(oTokensToExERCise,vaultOwner);return;}否则{耳穴运动=耳洞运动.sub( vault.otokensis发布)运动(vault.otokensis发布,vaultOwner);}需要(oTokensToExERCise==0,“指定的保险库没有足够的抵押品”);}
如您所见,exERCise函数允许传入多个vaultstoexERCisefrom,然后通过for循环调用exERCisefrom。exERCise函数处理每个vaultstoexERCisefrom函数,现在让我们深入分析exERCise的函数
函数练习(uint256 oTokensToExERCise,地址:payable vaultToExERCiseFrom)内部//1。练习前窗口:revert require(isExERCiseWindow(),“不能在练习窗口外练习”);
require(hasVault(vaultToExERCiseFrom),“Vault不存在”);
Vault storage Vault=vaults[vaultToExERCiseFrom];require(oTokensToExERCisegt;0,“不能练习0”otokenstokens“);//检查传入的正确耳鸣数)require(oTokensToExERCiselt;=vault.otokensis发布,“不能使用比所有者多的耳洞“);//确保呼叫的人有足够的耳洞需要(balanceOf(消息发送者)gt;=耳洞练习,“耳洞不够”);
//1。检查足够的基础//1.1更新基础余额uint256 amtUnderingToPay=underyingRequiredtoexecise(oTokensToExERCise);保险库.基础= vault.baseding.add(amtUnderingToPay);
//2。计算要支付的抵押品//2.1支付足够的抵押品以获得(strikePrice*oTokens)抵押品金额uint256 amtcalleraltopay=calculateCollateralToPay(oTokensToExERCise,Number(1,0));
//2.2每次练习都收取少量费用uint256 amtFee=calculateCollateralToPay(oTokensToExERCise,transactionFee);totalFee=总费用.add(amtFee);
uint256总抵押付款=amtCollateralToPay.add(amtFee);要求(totalCollateralToPaylt;= 保险库抵押品,“水下跳马,不能锻炼”);
//3。更新抵押品+贷款余额保险库抵押品= 保险库.collateral.sub(全自动对位机);vault.otokensis发布= 保险库.oTokensIssued.sub(耳鸣练习);
//4。转入标的,烧掉耳光+支付抵押品//4.1转入标的如果(isETH(基础)){要求(消息值==amtUnderingToPay,“不正确消息值“);}其他{require(基础.转移自( 消息发送者, address(this),amtUnderingToPay),“无法传入tokens”);}//4.2 burn oTokensuburn(消息发送者,oTokensToExERCise);
//4.3支付抵押品转让抵押品(消息发送者,amtCollateralToPay);
发射练习(美国电信公司,消息发送者,vaultToExERCiseFrom);
}
1代码的第6行首先检查它是否在保险期内,这当然是正确的
2在代码的第11行,检查vaulttoexERCisefrom是否创建了错误。请注意,这只检查是否已创建故障
3检查第14、16和21行中传入的tokenstoexERCise值。在上面的Oko浏览器中,我们可以看到攻击者传入了0x1443fd000,显然可以检查
4接下来,在第28行计算要消费的ETH的数量
5计算代码第35行和第41行中要支付的数量和服务费
6接下来,判断底层是否为代码第59行中的ETH地址,并且在上述代码的第31行中为底层赋值。因为isETH是真的,它将进入if逻辑而不是else逻辑。在if逻辑中,amtunderingtopay和消息值都是用户控制的
7然后烧录耳洞练习,并调用transfERCollateral函数将USDC转移到练习函数的调用者
上面的关键点在步骤2和步骤6中,因此我们只需要确保传入的vaulttoexERCisefrom创建了一个保险库,并且amtunderingtopay与消息值我们可以控制这些参数,所以攻击的想法是显而易见的。
思路验证
让我们通过攻击者的操作来验证这个过程是否如我们所想的那样:
1首先,在保险期内是确定的
2攻击者从vaultToExERCise传入,如下所示:
0xe7870231992ab4b1a01814fa0a599115fe94203f0x076c95c6cd2eb823acc6347fdf5b3dd9b83511e4
经验证,这两个地址都创建了保险库
3攻击者调用exERCise并以0x1443fd000(5440000000)的形式传入otokenstoexERCise,消息值272号,要练习的保险库分别是上述两个地址
4此时,因为前一个攻击者创建的otoken是0xa21fe800(272000),并且vault.otokensis发布如果值为27200000且小于5440000000,则将遵循exERCise函数中的else逻辑。此时,otokenstoexERCise为0xa21fe800(27200000),然后将遵循上述代码的第60行消息值==AMT underingtopay是正确的
5因为vaultstoexERCisefrom在两个地址中传递,for循环执行两次Execute函数,因此transfer two会将USDC传输到攻击者协定
完整的攻击过程如下
1攻击者利用契约调用opyn contract的createERC2CollerOption函数来创建otoken
2攻击契约调用exERCise函数,传递错误产生的地址
3通过exERCise函数中的for循环逻辑执行两次调用
4exERCise函数调用transfERCollateral函数将USDC传输到函数调用方(因为for循环被调用了两次exERCise函数,transfERCollateral函数也将执行两次)
5攻击契约调用removeBounding函数来传输先前传递的ETH
6**,攻击者收回ETH和额外的USDC
攻击合同地址
0xe7870231992Ab4b1A01814FA0A599115FE94203f
Opyn合同地址
0x951D51bAeFb72319d9FBE941E1615938d89ABfe2
攻击**易(上)
0xa858463f30a08c6f3410ed456e59277fbe62ff14225754d2bb0b4f6a75fdc8ad
维修建议
此攻击主要使用exERCise函数中的一个缺陷来检查vaulttoexERCisefrom是否创建了错误。此检查不会检查vaulttoexERCisefrom是否是调用者本身,而只是检查是否已创建错误,从而导致攻击者通过任意传入已创建错误的地址来通过检查。
建议如下:
1在处理用户控制的参数时,需要判断权限并将vaultToExERCise限制为调用者本人。
2项目方可以在项目前期或几次严格的安全审计完成前,增加合同中止功能和升级模式,避免黑天鹅事件发生后,无法有效保证剩余资金的安全。
文章标题:opyn合同被黑客攻击的详细分析
文章链接:https://www.btchangqing.cn/79367.html
更新时间:2020年08月06日
本站大部分内容均收集于网络,若内容若侵犯到您的权益,请联系我们,我们将第一时间处理。