北京时间 2021 年 8 月 27 日 20 点 50 分左右(区块高度 13107518),以太坊突然出现分叉。我们通过分析 Geth 的代码版本修改和这笔造成分叉的交易(0x1cb6fb36633d270edefc04d048145b4298e67b8aa82a9e5ec4aa1435dd770ce4)厘清了以太坊分叉的根本原因:Geth 旧版本在处理预编译合约调用时,并未考虑特殊情况(corner case)下参数值的处理,从而引发重叠拷贝(overlapping copy),导致返回值异常。该漏洞(CVE-2021-39137)已提交 Geth 官方,目前尚未披露细节,但攻击者已经利用漏洞实施了攻击。我们认为及时的分析和披露是必要的,也希望我们的分析能够为社区提供必要的理解和帮助。 攻击分析运用我们的 在线分析工具,可以看出: 图一 这笔交易执行了一个精心构造的 STATICCALL, 攻击者将 addr 设为 0x04 (是预编译合约 dataCopy), inOffset 为 0, inSize 为 32, retOffset 为 7, retSize 为 32。 图二 由于 STATICCALL 的目标地址是预编译合约,所以会执行图二中的 RunPrecompiledContract。 图三 图四 根据图三和图四的代码,可以看到预编译合约 0x04 真正执行的逻辑只是简单地把 in (指针)返回。 图五 图六 图五是 STATICCALL 的执行过程,753 行是执行预编译合约的入口,751 行的 args 指向 EVM 的 Memory 中 inOffset ~ inOffset + inSize 这篇区域的指针,也就是说 args 指向 Mem[0:32]。 根据图六以及前文对预编译合约 0x04 (dataCopy)的分析,我们可以知道 753 行的返回值 ret 是与 args 完全相同的指针,也指向 Mem[0:32]。
|