Group of Software Security In Progress

EVMPatch Timely and Automated Patching of Ethereum Smart Contracts

作者:Michael Rodler1, Wenting Li2, Ghassan O. Karame2, Lucas Davi1

单位:1University of Duisburg-Essen , 2NEC Laboratories Europe

出处:Usenix Sec 2021

原文:EVMPatch: Timely and Automated Patching of Ethereum Smart Contracts

1 Abstract

近段时间里,许多攻击利用以太坊智能合约(下称合约)的漏洞,带来了毁灭性的后果,这也因此让这项技术受到质疑。与此同时,修复漏洞并及时将安全合约部署在区块链上也具有很高的挑战性,并且对合约修复的及时性也十分重要,尤其是当合约关系着大量资产安全的时候。

本文提出了EVMPATCH框架,用于自动化修复合约。其利用了以太坊字节码重写引擎,透明地/自动地将合约修复。

本文最后也对14000个真实合约做了测试,EVMPATCH成功地组止了相应攻击交易的发生,同时保证了合约原本的功能不变。同时与其他相关工具比较之后发现,本文的工具实用性很强,能够减少了97.6%的修复漏洞的时间。

2 Introduction

以太坊智能合约非常重要,关系着大量的资金安全。然而其受区块链特性所限制,一旦部署就难以修复漏洞。

目前针对以太坊合约安全的研究,主要都是面向检测是否存在某些特定漏洞,但是这些成果不能用于保护已经部署在区块链上的合约。

与此同时,虽然目前存在一些集成在合约中一同部署的合约更新机制,但是这些更新机制缺少自动化的特性,往往都需要人为修复合约,可更新机制只用作辅助合约迁移的工具。虽然人为修改看起来可行,但是这非常容易引入不兼容性,使得更新后的合约不可用。

目前两个更新方向:

  • 人工数据迁移
  • proxy-pattern

本文的工具在proxy-pattern的基础上,设计了一个全面的自动化修复框架,解决了proxy-pattern方案下的不足。而为了实现本文修复合约的目的,有如图所示两种方案:

  • 1)源码层面的修复:

    源码层面的修复看起来是可行的,因为作为合约的开发者是可以有查看合约源码的权限的(即使合约不是开源的),所以开发者完全可以利用工具从源码层面进行修改。

    但是如果想要从源码的层面进行修复,开发者就必须要保留有有相应的存储数据及其映射,否则一旦源码修改了,其合约本身的数据将可能会被覆盖,或者更糟糕的是可能会引入新的漏洞。并且即使这样的修改没有改变合约的逻辑,但却依然有可能引入不兼容性。

    之所以从源码层面修改容易造成数据覆盖问题是因为,合约本身数据的存储在storage中有一定的映射关系,一旦合约源码的修改涉及到了变量,很可能会使得变量在storage中的映射发生改变,导致数据读取出现错误。

  • 2)字节码层面的修复:

    字节码层面的修复不会对变量之间的映射造成影响,因为大部分漏洞都只会涉及到相应的EVM指令层面,而不会影响到内存存储层面的改变。

    除此之外,目前为止大量的以太坊攻击检测工具都是基于字节码层面的,给出的报告也都是基于字节码,因此字节码层面的修复与检测工具有更好的匹配性和兼容性。

    与此同时,交易层面的测试分析也更偏向于字节码层面,因此字节码层面的修复也将更易于后续的测试。

因此本文设计了EVMPATCH框架考虑基于字节码层面的修复,其提供了自动化快速修复已部署合约的工具,并且能够保留合约本身的功能性不变,增加的gas开销小于$0.01。当出现新的攻击或者漏洞检测工具升级了,此工具也可以自动重新检查合约,然后将修复完成的合约在短时间内重新部署。

3 Design

EVMPATCH工具的框架如下图所示:

主要分为四个部分:

  • 漏洞检测引擎:由漏洞检测工具和已知漏洞组成。
  • 字节码重写:从字节码层面对合约进行修补。考虑到数据之间的依赖关系,以及源代码中相应的跳转地址依赖关系,本文考虑使用“蹦床方法”来进行修改。
  • 修补后合约测试:通过重放历史合约验证修补后合约的有效性,同时可以检索出在原始合约和修补合约上表现不一致的交易列表,可以用作取证分析。
  • 合约部署:如果上一步检测出的交易列表为空,则将修补后的合约版本部署到区块链上。否则,需要开发者对交易列表中的交易进行调查确认,然后再调用此功能重新部署合约。

虽然此工具设计为全自动重写重部署工具,但是出现以下的情况时仍然需要人为介入调整。

  • 漏洞检测报告给出的漏洞种类不在工具所支持修复的范围内。
  • 修补后合约测试阶段给出的不一致合约交易列表中的记录大于等于1。包括交易中出现攻击、交易因为合约的修改出现了不一致现象(不存在已知攻击)以及检测工具出现误报。

4 Implementation of Deployment of Patched Contracts

本文利用基于delegatecall-proxy的更新模式来重新部署修补后的合约。

EVMPATCH 工具将一个合约分成两个部分:proxy 合约和 logic 合约。

proxy 合约是主要的入口合约,并负责存储所有的数据。proxy合约将有一个固定的地址,而在proxy合约中将会提供一个更新 logic 合约地址的方法,以此来将proxy合约和最新的 logic 合约相关连。与此同时,为了防止恶意的更新,proxy合约将会存储owner地址,并指定只有owner才可以调用地址更新方法。

用户将与proxy合约交互,由proxy合约执行delegatecall来调用 logic 合约中的方法,以此达到在proxy合约的状态环境下,执行 logic 方法的效果。

5 Evaluation

5.1 Patching Access Control Bugs(Parity Wallet Hack)

经过本文工具的修补之后,能够成功修复Parity Wallet中出现的此漏洞,与此同时,本文还将重写后的合约与源码层面重写的结果做了比较,如下图所示:

EVMPATCH修补后的合约相比原来只增长了25B的大小,Gas开销增加了235gas,相当于0.00006$/trans 基本上可以忽略不计,同时相比基于源码的修补差距非常小。

5.2 Patching Integer Bugs

本文利用Osiris工具对以太坊前5000000个区块中的50535个合约进行检测,共找到14107个合约存在至少1个整数溢出漏洞。运用EVMPATCH工具进行修补后,能够修复几乎所有的整数溢出漏洞,其中有33个合约(均为多余1个整数溢出漏洞的合约)没有修复成功,因为出现问题的代码所在的基本代码块的大小不够存放修补后多出的代码。

在这14107个合约中,有8000个左右的合约在交易中被执行过。因此本文提取了7755100个区块中所以涉及到这些合约的共26385532个交易。然后利用此工具对其进行重放,95.5%的漏洞合约在修补后与之前的行为一致。在剩下的4.5%的合约中,有以下的三种情况 1) 发现了存在攻击行为的交易 2) 出现了误报(由合约检测工具Osiris造成),修复了本不该被修复的合约 3) 对合约的修改改变了其原有的功能。

本文为了进一步测试,选取了ERC-20 token相关的合约及与其相关的真实的506607个交易进行测试,同时也人为从源码层面对合约进行修复,将两者的结果进行比较,得到了下图所示的结果:

  • Gas开销:由于本文工具在修补漏洞的时候,会增加一定的gas开销,虽然其成本可以忽略不计,但是由于在交易中合约执行的时候,每一步调用所传递的gas量非常的少,仅够刚好执行相应功能,这就使得一旦gas消耗有所增加,可能会直接导致交易失败,使得实验结果没有可比性了。因此本文在这里关闭了其执行环境的gas计费功能。

  • 代码长度增加:在合约中只有单个整数溢出漏洞的情况下,本文的合约修补方案增长的代码量与人为使用SafeMath进行修补的开销增长有一定的可比性,结果几乎相当甚至优于人工修补。由于本文的修补方案需要拓展原始的区块大小,其代码的增长量将于漏洞所在位置和数量有关。

  • 重新部署开销:EVMPATCH 工具消耗了43.167gas(大约$ 0.01)来重部署相关的合约。而如果考虑利用状态转移(除了本文方案外最可取的方案)来重部署合约的话,根据其他研究之处,在只有5000个ERC-20代币持有者的情况下,在最好的情况下都需要增加超过100$的开销。因此本文所造成的开销可以忽略不计。

  • 检测攻击:EVMPATCH工具在其第三部分对修补合约进行测试的时候,其结果还可以用于对先前在交易中出现的攻击进行分析,下图给出了其分析的结果:

6 Conclusion

本文提出的EVMPATCH工具能够自动化,高效的对漏洞合约进行修复并进行重新部署,对于大部分的合约已经不需要人为进行操作。本文工具所对应的修复模板同样可以有使用者自定义,提高了其使用的灵活性。不过本文所提供的工具对开发的合约有一定的要求,即需要满足delegatecall-proxy的格式,将合约分为proxy合约和logic合约。其格式要求在github上有给出。