科普入门 | 不推迟就可能会死——“重入攻击”详解

不知道是不是之前老路奶了一口的原因,以太坊硬分叉在原定日期的前一天居然又双叒叕被推迟了,这狼来了的故事一再重演,矿工们的小心脏都要承受不住了呀。

据官方发布的消息称,这次分叉改期的原因是在已完成硬分叉的测试网络中,发现了会被黑客用来发动“重入攻击”的代码漏洞。

那么“重入攻击”到底是如何进行的?它会对区块链网络以及用户造成什么危害呢?当然矿友们最关注的是,现在的以太坊网络会不会受到“重入攻击”?

 

科普入门 | 不推迟就可能会死——“重入攻击”详解

//

The DAO 事件回顾

//

17 年那起导致以太坊分家的 The DAO 事件大家想必都不陌生吧,The DAO 的发生就是因为黑客对当时的以太坊网络发动了“重入攻击”(Re-entrancy)。

出于拓展性的考虑,以太坊的智能合约代码是可以和其他网络上的各类合约代码互相兼容以及调用的。

黑客们发现,虽然一时半会找不到以太坊自身代码的漏洞,但是当以太坊调用一些外部合约时,却有可能出现一些逻辑上的自相矛盾或者是以太坊代码开发者没想到过的情况,这些问题会导致以太坊智能合约做出令人意想不到的操作。

科普入门 | 不推迟就可能会死——“重入攻击”详解

//

“重入攻击”如何产生

//

以太坊智能合约中有两个功能函数,depositFunds() 和 withdrawFunds()depositFunds() 功能函数被用于增加发件人余额,而 withdrawFunds() 功能函数允许发件人指定要撤回的以太坊数字货币数量,这两个代码一般被运用于交易发起人撤回交易的情况。

当时被攻击的 "DAO" 合约就包含这两个函数,函数本身是没有问题的, 为了避免用户钻空子,"DAO" 智能合约还对这两个函数设置了撤回数量和撤回间隔的限制,类似“一周内只能有一次小于等于 1 ETH 的交易撤回”。

因为以太坊智能合约的执行需要消耗手续费 Gas(Gas 说明看这里),假设需要撤回交易的钱包在发起撤回请求时里面有 1 ETH,但发起撤回请求时,用户设置了较高额度的 Gas,那么撤回之后钱包里的 ETH 数量就不足 1 了,这使得 "DAO" 智能合约判定这次撤回失败,withdrawFunds() 函数还可以被执行。

黑客所编写的攻击合约就是利用这一点,在攻击合约上反复发起交易撤回请求,"DAO" 智能合约也会自动将自己钱包里的以太坊不限次数地“返还”给攻击合约钱包,直到 "DAO" 的钱包余额小于 1 ETH 为止。

 

科普入门 | 不推迟就可能会死——“重入攻击”详解

//

硬分叉带来的重入危机

//

The DAO 事件直接导致的“分家”,使得以太坊元气大伤,开发团队自然是不会想再来一次“The DAO”的。

针对重入攻击,The DAO 事件后以太坊网络在智能合约中加入了transfer()功能函数,该函数可以通过限制以太坊手续费 gas 来阻止智能合约。

此前,以太坊已经在测试网络 Rinkeby 成功实现了君士坦丁堡硬分叉,但随后智能合约审计公司 ChainSecurity就在测试网络的代码中发现了漏洞:“EIP-1283 协议为 SSTORE 操作引入了更便宜的 Gas 成本。

一些智能合约(已经在链上了)可能会利用这种代码模式,这会使它们在君士坦丁堡升级之后容易遭受一种重入攻击。"

 

科普入门 | 不推迟就可能会死——“重入攻击”详解

//

目前的情况

//

此次的漏洞和The DAO 事件相似,也是通过“反复执行交易撤回命令”来从目标账户中转出 ETH 来获利的。但它的发生有一个前提,就是“君士坦丁堡硬分叉”。在当前较高的 SSTORE 操作费用下,以太坊智能合约代码并没有被重入攻击的可能。

可能也是出于对 The DAO 事件重演的恐惧,这次 EIP 1283 协议所曝出来的漏洞,以太坊开发团队只花了 9 个小时就解决了(但出于风险考虑还是延后了硬分叉),运行节点的用户仅需第一时间更新官方发布的Geth以及 Parity软件补丁即可,此举可以说是把一次可能的“大事件”扼杀在了摇篮里。

科普入门 | 不推迟就可能会死——“重入攻击”详解

文字/魔路西

编辑/魔路西

图片/网络

无盘挖矿奇迹摩尔:https://wondermole.com/

官网:http://minerhub.com

********:https://t.me/MinerHub

QQ群:9107173

关注微博:@MinerHub