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
明天的解说到此结束,感激大家的浏览,如果你有其余的计划,欢送一块交换。