Group of Software Security In Progress

GoSSIP @ LoCCS.Shanghai Jiao Tong University

TEETHER: Gnawing at Ethereum to Automatically Exploit Smart Contracts

作者:Johannes Krupp, Christian Rossow

单位:CISPA, Saarland University

会议:usenix security’18

论文:https://www.usenix.org/system/files/conference/usenixsecurity18/sec18-krupp.pdf

摘要

加密货币被广泛认为是过去几年来最具有颠覆性的技术之一。比特币等加密货币在提供了一个去中心化货币的基础上,往往还提供了程序化处理交易的方式。以太坊作为仅次于比特币的全球第二大加密货币,第一个提出了一门用于描述交易处理的图灵完备语言,实现了智能合约的概念。

本文的研究重点在于针对智能合约的自动化漏洞识别技术以及漏洞利用代码生成技术。文章提出了TEETHER工具,并使用该工具对于现有的以太坊智能合约进行了大规模自动化的漏洞分析工作。

1 介绍

以太坊极大地扩展了通过共识机制处理交易的方式:比特币只允许在处理交易的时候进行一些简单的检查,而以太坊则允许使用一门图灵完备的语言描述这些交易处理规则。

然而,设计复杂性的提升往往会带来风险的提升,以太坊实现的图灵完备语言Solidity相比于比特币实现的简单检查更容易出错。更糟糕的是,由于区块链不可篡改的特性,智能合约一旦被部署便无法被更新或打补丁。

本文的核心贡献如下:

  • 基于底层的EVM指令,提出了存在漏洞的智能合约的一种广义定义;
  • 提出了TEETHER工具,该工具能够对于智能合约的字节码进行自动化的漏洞识别并生成相应的漏洞利用代码;
  • 对于以太坊区块链中部署的38,757个智能合约进行了大规模的漏洞分析。

2 背景

2.1 交易系统

每一笔交易都包含有一定数量的手续费,用于支付给处理该笔交易的矿工,以防止资源枯竭攻击(Resource Exhaustion Attacks)以及激励矿工去处理尽可能多的交易。

2.2 智能合约

智能合约是一类特殊的以太坊账户,这类账户包含有一段代码并具有私有的存储空间。

以太坊虚拟机(EVM)

  • 256比特字长的栈;
  • 永久存储空间;
  • 可按字节寻址的内存。

Solidity

20181004144013

交易

一笔交易中最重要的字段包括to、sender、value、data以及gas字段。用户通过发送一笔交易给智能合约,以调用执行合约中相应的函数。按照惯例,Solidity将交易data字段的前四字节作为函数标识符,其后的数据作为函数参数处理。

函数(functions)与修饰器(modifiers)的概念仅存在于Solidity代码的层面上。在EVM字节码层面上,一个智能合约仅仅是一个单独的字节码串,其执行永远从第一条指令开始。

2.3 记号

  • µ:EVM机器状态:
    • µm:内存状态;
    • µs:栈状态;
  • I:交易执行环境;
  • S:智能合约存储空间。

2.4 攻击模型

攻击者能够获取目标智能合约的字节码,且能够向以太坊网络提交交易。任何一个普通以太坊账户拥有者均可满足上述条件。

2.5 道德考虑

作者决定不公开存在漏洞的智能合约,并计划在论文发表180天之后再公开TEETHER工具,给智能合约拥有者足够的时间以完成合约修复工作。

3 智能合约漏洞

智能合约通常会对与其进行交互的以太坊账户实施访问控制,其中一个特别重要的控制就是只允许经过授权的以太坊账户提取存储在智能合约中的以太币。在这个前提下,如果一个智能合约允许攻击者将智能合约中存储的以太币转账至攻击者控制的以太坊账户中,则此智能合约是存在漏洞的。

3.1 危险指令

文章将四条EVM指令视作危险指令(Critical Instruction)。如果攻击者想要从智能合约中提取以太币,则必须要执行其中的任意一条指令。这四条指令中的两条指令将会导致直接的以太币转账交易,另外两条指令将会导致在当前智能合约环境下的任意以太坊字节码执行。如果攻击者能够控制这四条指令的相应参数,则攻击者能够利用这四条指令将智能合约中存储的以太币转账至攻击者控制的以太坊账户中。

直接转账

  • CALL:执行常规转账交易;

  • SELFDESTRUCT:中止智能合约,并将合约中所有剩余的以太币转账至指定的以太坊账户中。

代码注入

  • CALLCODE:在当前智能合约环境下执行指定第三方智能合约的代码;

  • DELEGATECALL:与CALLCODE功能相同,但是保留原始的sender字段与value字段的值。

危险路径(Critical Path):能够导致攻击者控制危险指令的特定参数并执行该危险指令的智能合约执行路径;

存在漏洞的状态(Vulnerable State):如果一笔交易能够导致智能合约执行危险路径,则该智能合约处于存在漏洞的状态。

3.2 存储空间

20181004161403

智能合约的存储空间中保存着智能合约的状态。如果攻击者能够通过控制修改智能合约存储空间的指令,改变智能合约的状态至存在漏洞的状态,则攻击者依旧能够实现攻击。其中,能够修改智能合约存储空间的指令只有SSTORE指令。

状态改变路径(State Changing Path):包含有至少一条SSTORE指令的智能合约执行路径;

状态改变交易(State Changing Transaction):如果一笔交易能够导致智能合约执行状态改变路径,则该交易为状态改变交易;

存在漏洞的(Vulnerable):如果一系列的状态改变交易能够导致一个智能合约转换为存在漏洞的状态,则该智能合约是存在漏洞的。

4 自动化漏洞利用

4.1 概述

20181004163412

4.2 CFG恢复

EVM提供的控制流指令均为间接跳转指令。条件跳转指令JUMPI与无条件跳转指令JUMP均将EVM栈的栈顶元素作为跳转目标。TEETHER通过使用后向切片(Backward Slicing)的方式推测EVM栈中元素并确定跳转指令的跳转目标,并通过使用依赖边(Dependent Edge)的方式过滤剔除非法路径。

20181004165523

4.3 路径生成

TEETHER通过扫描恢复得到的CFG中的危险指令(CALL、CALLCODE、DELEGATECALL、SELFDESTRUCT),计算这些指令中危险参数的后向切片(Backward Slicing),并使用A*算法探索路径,以寻找所有的危险路径和状态改变路径。

4.4 约束生成

约束生成模块与路径生成模块同步执行。TEETHER使用符号执行引擎Z3收集路径生成模块寻找得到的所有危险路径与状态改变路径的路径约束。

不可行路径

并不是所有由路径生成模块生成的路径都是可行的执行路径。TEETHER通过定义最小不可行子路径(Minimal Infeasible Subpath)的方式指导路径生成模块过滤剔除非法路径。

20181004170453

Hash计算

EVM的SHA3指令无法直接被符号执行引擎Z3符号建模。TEETHER使用一个新的256比特的符号变量模拟SH3指令的输出,并记录SHA3指令的输入数据与该符号变量的映射关系。

符号长度的内存访问

一些EVM指令会对内存进行变长变量的读写操作,而在符号执行的过程中,这些变量的长度由符号变量表示。对于变长变量的内存写操作,TEETHER使用符号执行引擎Z3的If表达式实现变长变量内存写操作的符号模拟。而对于变长变量的内存读操作,TEETHER使用一个符号读取对象模拟变长变量的内存读操作的结果,并记录该内存读取变量与内存读操作的地址、长度与内存状态的映射关系。

约束结果

  • p:智能合约的执行路径;
  • µ:符号化的机器状态;
  • S:符号化的智能合约存储空间;
  • I:路径p符号化的执行环境;
  • C:执行路径p所必须满足的约束;
  • H:SHA3指令输出符号变量与输入数据的映射;
  • M:符号读取对象与内存读操作的地址、长度与内存状态的映射。

20181004172314

4.5 漏洞利用代码生成

TEETHER使用约束求解程序E3,通过迭代约束求解算法依次求解能够满足上一步骤中约束生成模块生成的路径约束的符号变量赋值。若路径约束求解成功,TEETHER则会输出满足所有路径约束条件的交易序列,以生成目标智能合约的漏洞利用代码。

20181004183931

4.6 实现

TEETHER由4300行Python代码实现,使用E3作为约束求解程序。TEETHER工具将在论文发表180天之后开源。

5 评估

文章截取并下载了2017年11月30日的以太坊区块链的快照,并从中扫描获得了784,344个智能合约。在去除了具有相同字节码的合约之后,文章得到了剩下的38,757个互不相同的智能合约作为分析对象。此外,为了防止TEETHER的分析卡住,文章还对于CFG生成步骤以及之后的漏洞利用代码生成步骤设置了30min的超时时间。

5.1 结果

20181004185248

依赖/独立漏洞利用代码(Dependent/Independent Exploit):目标智能合约的执行过程中是否会向其它第三方的智能合约发送进一步的交易,即生成的漏洞利用代码是否依赖于这些进一步交易的结果。

5.2 验证

文章通过创建一个全新的以太坊测试网络,并在该网络中部署所有的测试智能合约,以测试TEETHER自动化生成的漏洞利用代码的有效性。

20181004190412

经过作者的进一步分析,验证结果中出现的大部分失败情况均是由于以太坊测试网络与实际的以太坊区块链之间的差异所导致的,例如区块链块号的差异以及以太坊账户余额的差异。

5.3 案例研究

在所有发现存在漏洞的智能合约中,只有44个合约将Solidity源代码上传至etherscan.io网站中。作者人工审查了所有这些上传了Solidity源代码的智能合约,并将这些智能合约中的漏洞分为以下四类:

错误的可见性

除非被internal关键词所修饰,Solidity中的函数默认是能够被公开访问的。一旦疏忽大意,就有可能导致智能合约对外暴露关键函数的接口。

错误的构造函数

在Solidity中,与智能合约同名的函数就是构造函数。构造函数仅在合约创建的时候执行一次,且并不包括在合约的字节码中。然而,由于忽视了大小写、拼写错误以及重构操作时的疏忽,就有可能导致智能合约的构造函数变为普通的函数,并对外暴露该接口。

20181004192859

语义混乱

这类存在漏洞的智能合约源于开发者对于以太坊执行模型中关键概念的混淆与误解。

逻辑缺陷

智能合约代码存在逻辑错误或漏洞。

20181004192915