关于区块链:区块链合约安全系列二如何认识及预防公链合约中的重入攻击漏洞

45次阅读

共计 1394 个字符,预计需要花费 4 分钟才能阅读完成。

id:BSN_2021
公众号:BSN 研习社

背景:因为公链环境下所有的信息都是共享的,智能合约相当于是齐全透明化,任何人都能够调用,外加一些利益的驱动,导致引发了很多 hacker 的攻打。其中重入 (Re-Entrance) 攻打是以太坊中的攻击方式之一,例如 The DAO 事件被盗取了大量的以太币从而造成了以太坊的硬分叉。

指标:将指标合约里的所有资金 (ether) 进行盗取,从而意识以及预防重入攻打破绽。

对象:实用于用 Solidity 语言开发的智能合约,例如 BSN 中的武汉链(基于 ETH)和泰安链(基于 fisco bcos)上运行的智能合约。

前言

在进入明天的正题之前,咱们先来看一段典型的有重入破绽的代码:

上述办法的业务也很简略,提取调用者存入的钱,胜利后将其余额设为零。

不晓得大家脑海里有没有收回这样的疑难:这怎么就存在重入破绽了呢?

如果你存在这样的纳闷,那么请由我来解说一下其中的常识。在开始之前须要大家分明几个知识点:

1. 重入定义
什么是重入?官网的解释如下:

为不便记忆,暂且能够简略的了解为咱们开发者传统印象中的递归。

2. 非凡函数
这里的非凡函数是指在合约交互发送 ether 转账时,会隐式触发调用的函数,蕴含 receive 和 fallback。官网的解释如下:

艰深的来说就是当你的合约接管 ether 时,必须至多蕴含这俩函数中的一个。

3. 转账操作

什么是转账???对,没错,就是你脑子里想的那样。在这里是指在两个以太坊账户之间的发送和接管 ether 的操作。但须要晓得的一点是以太坊上的账户分为两种,即一般账户和合约账户。

在以太坊上转账操作常见的函数包含三种.transfer()、.send()和.call{value:xxx}(“”)

在各位理解了根本的常识后,上面咱们开始进入明天的正题:我将通过一个示例来进行演示,通过重入破绽,盗取一个“银行”里的全副资金。

示例波及到两个合约,一个为资金治理合约,一个为攻击者合约。其残缺代码如下:

合约部署

为其不便演示在此应用 remix 进行测试环境筹备。首先,部署资金治理合约,并初始化存入 100Wei(为显示不便,其金额任意)。后果如下:

而后,部署攻击者合约,后果如下:

重入攻打

首先,存入 ether。因为资金治理合约的提款逻辑为提取本人已存入的,所以咱们须要先存入。后果如下图:

而后,提取 ether,利用重入破绽将额定的资金进行盗取。交易执行胜利后,查问提取的资金信息,后果如下图:

该笔交易的事件日志信息如下:

另外,咱们查看一下资金治理合约的余额信息,查问后果如下图:

解决方案

通过下面的示例,仔细的敌人可能曾经大略明确,其实重入攻打破绽是因为触发了非凡函数(receive 或者 fallback)造成递归调用转账,目前罕用的解决方案有上面几种:

计划一、应用平安的转账函数
应用内置的 transfer 或 send 函数,因为 transfer 和 send 在转账时会传递 2300Gas,不足以执行重入调回合约操作,而.call 会传递所有可用的 Gas(当然也能够设置传递可用的 Gas)。

计划二、应用官网举荐的查看 - 失效 - 交互模式 (checks-effects-interactions)

计划三、应用专门针对重入攻打的平安合约

例如 OpenZeppelin 官网库中的平安合约 ReentrancyGuard.sol

明天的解说到此结束,感激大家的浏览,如果你有其余的计划,欢送一块交换。

正文完
 0