主页 > imtoken钱包官网版最新 > 智能合约安全(一):以太坊机制与安全问题

智能合约安全(一):以太坊机制与安全问题

imtoken钱包官网版最新 2023-05-23 07:29:41

在本系列中,我们将回顾以太坊现存的安全问题以及挖掘各类漏洞的前沿方法。 本文是该系列的第一篇文章,主要介绍以太坊的机制和存在的安全问题的分类。

01 什么是以太坊智能合约?

以太坊智能合约基于区块链(Blockchain)技术。 作为一种旨在以信息化方式传播、验证或执行的计算机协议,它为各种分布式应用服务提供了基础。 简单来说:如果你把比特币看成是一个分布式记账本; 以太坊是一个可以运行程序的分布式计算平台,程序运行的基础是Solidity智能合约。

智能合约早在 1995 年由 Nick Szabo 提出,目的是以数字形式定义合约。 当参与者执行并满足合同要求的条件时,计算机自动执行合同内容。 但由于技术限制等限制,这一概念在当时并未实现。 近年来,随着区块链技术的逐渐成熟和加密货币的快速发展,进入了以智能合约技术为标志的区块链2.0时代。

智能合约不仅仅是一个可以在区块链上自动执行的程序,它本身就是一个系统参与者,可以接收和响应信息,也可以存储和发送和接收资产。 支持智能合约运行的区块链平台有很多,如EOS、BCOS、Fabric、CITA等,其中以太坊规模最大、历史最悠久、影响力最大。 以太坊通过构建一个图灵完备的平台而广受欢迎,该平台允许开发人员编写任意智能合约和去中心化应用程序 (Dapps)。

02 为什么要关注智能合约的安全性

随着智能合约应用场景的丰富,如金融、保险、游戏、能源等领域,其中控制的重要金融资产必然成为吸引攻击的目标。 此外,由于智能合约本身编程语言的不安全性和合约整个生命过程的复杂性,再加上以太坊中的每个用户都可以在没有可信第三方的情况下参与合约,因此智能合约的安全性。 性伴随着巨大的风险和隐患。

例如,2017 年 6 月 18 日,智能合约 The DAO 的一个可重入漏洞最终造成了数亿美元的损失,并影响了整个以太坊网络。 2020年1月16日,攻击者通过开源项目为RVN添加功能,通过一些条件判断绕过审核,从而具备发币功能,最终获利数千万人民币,造成平台遭受巨大损失。

以太坊智能合约安全漏洞的频繁爆发,造成了巨大的经济损失,需要对其进行安全检查研究。

03 智能合约有什么样的结构?

作为脚本,智能合约可以使用多种高级语言开发,如Solidity、Serpent、Vyper等。其中,以太坊的智能合约通常使用Solidity编写,其语法类似于JavaScript . 智能合约的编译、解释和执行是通过安装在每个以太坊节点上的以太坊虚拟机(Ethereum Virtual Machine,EVM)完成的。 根据以太坊白皮书,以太坊系统架构如图1所示。每个以太坊节点架构自下而上由操作系统、区块链节点客户端、以太坊虚拟机和智能合约脚本组成。

图片

以太坊智能合约安全性_比特币带来了以太坊智能合约时代_比特币以太坊莱特币都开始下跌

图 1 以太坊系统架构

以太坊通过运行在不同主机上的以太坊客户端节点之间的通信来完成各种操作。 书面合约首先通过EVM编译器编译生成ABI文件和bin文件,其中ABI文件是合约的接口描述,包括字段名、字段类型、参数名、参数返回值等信息。 ,而bin文件就是最终在虚拟机上运行的字节码(bytecode),是一组EVM指令。

合约的部署是将编译好的字节码上传到以太坊区块链平台。 该过程类似于发送交易。 源地址为发布者地址,目标地址为零,交易数据由合约对应的字节码代替。 交易打包时,会根据发布者地址和交易序号,通过加密算法重新计算出一个地址作为合约地址,调用者可以通过合约地址调用合约。 以太坊中有两种账户:外部账户和合约账户。 外部账户由私钥控制,有账户余额,可以触发交易但没有代码; 合约账户包含不可修改的智能合约代码,有账户余额,但不能主动发起交易,被触发后只​​能执行预先写好的逻辑。

因此,合约调用也分为两种,一种称为外部账户发起的交易调用,另一种是一个合约向另一个合约发起的调用,称为消息调用。 此外,智能合约还具有自毁操作,这是从区块链中删除合约代码的唯一途径。 它需要在写入合约时进行selfdestruct操作,然后销毁合约账户中剩余的以太坊(Ether)。 发送到指定的目标,其中存储的相关状态和代码也会被移除。 所谓以太坊就是以太坊中的通用货币,类似于比特币。

04 与传统程序相比,智能合约的特殊机制有哪些?

气体机制

合同需要矿工执行和证明。 因此,当一笔交易被打包,即加入一个区块时,为了避免交易中大量循环等操作造成的节点资源浪费,合约需要向矿工支付一笔提前总结。 费用(天然气)。 在以太坊中执行合约本身也需要根据内部规则消耗一定的gas。 如果交易执行后预付的gas仍有剩余,则按原路返还; 如果gas在执行完成前耗尽,会触发out-of-gas异常,回滚当前合约程序的所有执行状态,但是因为矿工已经支付了执行的算力相应计算,消耗的gas不会返还。

委托调用机制

合约可以通过消息调用机制调用其他合约,委托调用是一种特殊的消息调用。 它与普通call指令的区别在于,普通call指令的行为是跳转到被调用的合约并执行合约中相应的代码然后返回执行后续代码,对上下文没有影响呼叫发起人; 而委托调用则是相当 将被调用合约中的一段代码复制到调用发起者合约的上下文中并执行,调用发起者中的信息将被修改。

异常传递机制

智能合约的函数调用分为内部调用和外部调用。 内部函数调用是指直接调用当前合约或父合约的内部函数。 这些函数调用在EVM中会直接转化为简单的跳转指令; 而外部函数调用是指调用指定地址的外部合约函数,需要通过消息调用来完成。 其中call、callcode、delegatecall等外部调用中的一些低级调用,如果在执行过程中出错,就会抛出异常。 异常不会沿着函数调用栈传递,只能得到一个布尔值来表示成功或失败。 此外,一些传递函数如call.value、send等,在传递异常发生时,只返回一个布尔值,不会回滚操作。

比特币带来了以太坊智能合约时代_比特币以太坊莱特币都开始下跌_以太坊智能合约安全性

05 智能合约存在哪些安全问题?

智能合约源代码的公开透明虽然提高了用户对合约的信任度,但也使得每一个公开的合约都成为黑客的潜在目标。 智能合约的可信度来自于其不可篡改性,但正因如此,智能合约无法像传统程序那样通过打补丁等方式修复漏洞。

接下来,本文将对目前典型的智能合约漏洞类型进行总结。

根据 Atzei 等人的调查报告,智能合约的安全漏洞可以按照高级语言 Solidity、EVM 和区块链三个层次进行分类。 过程中引入的错误,EVM层面的安全威胁主要是以太坊智能合约的字节码规范和运行机制本身的一些缺陷导致的,而区块链层面的问题则是区块链的诸多特性引入的本身。 详情如表 1 所示。

表1 漏洞分类

机密安全漏洞

高级语言Solidity

整数类型错误

未经检查的返回值

权限控制问题

拒绝服务

以太坊智能合约安全性_比特币以太坊莱特币都开始下跌_比特币带来了以太坊智能合约时代

资产冻结

EVM

重入漏洞

短地址攻击

代码注入

区块链

交易顺序依赖漏洞

时间戳依赖漏洞

可预测的随机处理

可以采取一些措施来避免潜在的重入漏洞:首先确保在允许以太币被转移出合约之前发生改变状态变量的逻辑; 或者当向外部合约发送以太币时,使用内置的转账函数代替调用和发送函数安全的货币转账操作。

06 智能合约安全漏洞介绍

比特币带来了以太坊智能合约时代_以太坊智能合约安全性_比特币以太坊莱特币都开始下跌

1)整数类型错误

整数类型错误主要包括算术错误、截断错误和符号错误。 算术错误包括整数溢出、被零除和被零取模。 EVM 使用几个固定长度来表示整数,也就是说只能表示一定范围内的数字。 一旦整数运算的结果超过这个范围,就会发生整数溢出。 攻击者可以利用整数溢出漏洞跳过某些条件判断或篡改数据。 著名的BEC漏洞事件就是在转账过程中因整数溢出导致大量代币蒸发。 使用提供安全检查的SafeMath数学计算库可以有效避免溢出漏洞。 在老版本的EVM和Solidity中,除以零和以零取模只会导致运算结果为0,不会触发异常。 截断错误是指将整数类型数据转换为宽度较短的整数类型数据而导致的精度损失。 符号错误是指将有符号整数类型的数据转换为相同宽度的无符号整数类型数据,可能导致负数变成大整数。

2)未经检查的返回值

以太坊Solidity语言的函数调用一般和其他高级语言一样设置返回值,但是当send、call、delegatecall等低级函数调用失败时,不会引起交易回滚操作,而只是表示返回值是否发生异常。 攻击者可以通过故意发送失败的操作来导致程序执行与预期设置不同比特币带来了以太坊智能合约时代,从而造成智能合约状态的混乱。 在开发合约时,开发者可以通过检查底层函数调用的返回值来判断调用是否成功,从而保证合约能够按照预设的逻辑执行。

3)访问控制问题

在 Solidity 中,可以使用四种说明符来设置函数和状态变量的可见性,即 external、internal、public 和 private。 未声明可见性的函数默认为public,即该函数不仅允许内部调用,还可以作为合约的外部接口被外部合约调用。 如果一些涉及转账等敏感操作的函数没有声明可见性,就有可能给攻击者可乘之机。

4)拒绝服务

拒绝服务(DoS)一般是指不可恢复的恶意操作或可控的无限资源消耗。 针对以太坊合约的DoS攻击会导致大量消耗以太坊和Gas,更严重的会导致合约永久无法使用。 2016年以太坊游戏The King of the Ether Throne中,攻击者利用外部函数调用漏洞,通过(Unexpected)Revert发起DoS攻击,导致游戏运行出现重大问题。

5)资产冻结

由于合约不可篡改的特性,如果开发者在开发智能合约时只设置了接收以太币的功能,而没有设置任何允许以太币转出的操作,或者由于以下原因导致以太币无法转出某些原因,会导致合约中的资产被永久冻结。

6) 重入漏洞

以太坊智能合约安全性_比特币带来了以太坊智能合约时代_比特币以太坊莱特币都开始下跌

虽然以太坊智能合约的执行是一个原子的、顺序的事务操作,但是当用户调用智能合约时,如果被调用的合约没有找到被调用的函数或者合约只接收以太币而没有任何其他的回退函数(fallback)是收到消息时调用。 攻击者可以通过构造特殊的回退函数来攻击具有重入漏洞的智能合约。 例如,fallback函数中包含了在被攻击合约中重新调用之前的传递函数给攻击者的代码,从而实现递归调用,耗尽被攻击合约的资产。 导致以太坊硬分叉(ETH/ETC)的著名 The DAO 事件与重入漏洞有关。

7)短地址攻击

短地址攻击漏洞是未经验证的用户输入造成的漏洞。 攻击者利用虚拟机的自动补全机制构造一个末尾为零的地址来调用合约,并故意插入地址(address),如果末尾的零被省略,则虚拟机会补全该地址用发送的token数量(amount)高位0,同时低位amout填0,相当于amount向左翻一倍,得到转出的token数量超出原来的设定。 通过严格检查用户输入,拒绝接受格式错误的地址,可以有效避免短地址攻击。

8)代码注入

该代码注入漏洞是由以太坊的委托调用机制引入的。 委托调用机制中使用的 delegatecall 指令允许合约在自己的上下文中执行其他合约的代码片段。 攻击者可以利用该漏洞向合约中注入修改合约重要状态变量等恶意操作。

9) 交易顺序依赖漏洞

一笔交易被矿工传播和批准写入区块需要一定的时间。 攻击者可以监控网络上依赖于交易顺序的合约,并通过发布自己的交易来改变当前合约状态。 例如,攻击者可以提交奖励合约,让用户通过提交疑难问题的答案,从合约中获得丰厚的奖励。 攻击者可以在提交奖励合约后继续监控网络。 如果有人提交了答案,并且提交的答案交易还没有被确认,攻击者可以立即发起一笔交易,将bonus降低到无限接近于0,并提供更高的gas让他的交易先被矿工处理,并且提交答案的交易在后面进行处理,这样攻击者只需支付很少的奖金就可以得到问题的答案。

10) 时间戳依赖漏洞

一些智能合约可以通过参数block.timestamp获取当前区块的时间戳并以此作为判断依据,时间戳可以在一定范围内由矿工自行决定。 因此,一般认为,如果依赖时间戳的智能合约中的代码可以允许12分钟的错误,那么这种使用时间戳的方式是安全的。

11) 可预测的随机处理

合约开发者在编写随机数生成函数时,有时会使用时间戳(block.timestamp)、区块号(block.number)等一些区块相关的参数来生成随机数比特币带来了以太坊智能合约时代,但以上数据在区块链上都是公开的,这使得生成的随机数可预测,因此可能被攻击者利用。 智能合约开发者可以使用Oraclize等第三方服务获取随机数来避免这个问题。

以太坊智能合约安全性_比特币带来了以太坊智能合约时代_比特币以太坊莱特币都开始下跌