欧易

以太坊遭到攻击而导致分叉事件的技术分析

欧易交易所推荐 2022-09-23 欧易官网okex官网

北京时间年8月27日20点50分左右(区块高度),以太坊突然出现分叉。我们通过分析Geth的代码版本修改和这笔造成分叉的交易(0x1cb6fbdedefc04dbe67b8aa82a9e5ec4aaddce4)厘清了以太坊分叉的根本原因:Geth旧版本在处理预编译合约调用时,并未考虑特殊情况(cornercase)下参数值的处理,从而引发重叠拷贝(overlappingcopy),导致返回值异常。

该漏洞(CVE--)已提交Geth官方,目前尚未披露细节,但攻击者已经利用漏洞实施了攻击。我们认为及时的分析和披露是必要的,也希望我们的分析能够为社区提供必要的理解和帮助。

攻击分析

运用我们的在线分析工具,可以看出

图一

这笔交易执行了一个精心构造的STATICCALL,攻击者将addr设为0x04(是预编译合约dataCopy),inOffset为0,inSize为32,retOffset为7,retSize为32。

图二

由于STATICCALL的目标地址是预编译合约,所以会执行图二中的RunPrecompiledContract。

图三

图四

根据图三和图四的代码,可以看到预编译合约0x04真正执行的逻辑只是简单地把in(指针)返回。

图五

图六

图五是STATICCALL的执行过程,行是执行预编译合约的入口,行的args指向EVM的Memory中inOffset~inOffset+inSize这篇区域的指针,也就是说args指向Mem[0:32]。

{dede:field.title/}

根据图六以及前文对预编译合约0x04(dataCopy)的分析,我们可以知道行的返回值ret是与args完全相同的指针,也指向Mem[0:32]。

在1.10.7版本的Geth中(有Bug):行将ret指向的值赋给EVM的Memory中retOffset~retOffset+retOffset这篇区域,也就是将Mem[0:32]的值赋给Mem[7:7+32],而由于ret是一个指向Mem[0:32]的指针,这次Memory.Set修改了Mem[7:32]的值,也就修改了ret所指的值。

所以在第行返回的ret已经不是预编译合约执行结束时的ret了。

在1.10.8版本的Geth中(无Bug):增加了行:ret=common.CopyBytes(ret),将Mem[0:32]中的值做了一次深拷贝赋给ret,那么在行执行的Memory.Set只会修改Memory而不会修改ret,在行返回的ret就是正确的ret。

总结

通过对整个攻击流程的梳理和Geth源代码的分析,我们认为根本原因在于Geth旧版本在处理预编译合约的调用时并未考虑异常值的处理,导致攻击者利用该漏洞实施了重叠拷贝,影响了返回值,最终导致分叉的出现。

由于Geth是BSC、HECO、Polygon等公链的基础,因此该漏洞影响范围甚广。目前各公链也先后推出了升级和补丁,我们也呼吁各相关节点尽早升级打上补丁,以确保基础设施的安全。

展开阅读全文
文章标签: 欧易网址多少
okex注册
微信复制成功