首页 > 百科 > qtum|区块链安全 - DAO 攻击事件解析
链闻研究院  

qtum|区块链安全 - DAO 攻击事件解析

摘要:文章来源:疯猫网络前言最近关注了一下区块链方面的安全,因此翻出来之前的 DAO 攻击事件研究了一番,形成此文。基础知识1. 跨合约调用智能合约之间的调用本质上是

文章来源:疯猫网络

前言

最近关注了一下区块链方面的安全,因此翻出来之前的 DAO 攻击事件研究了一番,形成此文。

基础知识

1. 跨合约调用

智能合约之间的调用本质上是外部调用,可以使用 message call 或者创建智能合约对象的形式进行调用。

(1)使用 message call
比如合约 1 调用合约 2 的某个方法:

区块链安全 - DAO 攻击事件解析

(2)还原智能合约对象

如果已知合约的地址,可以通过如下方式获取到合约对象:

区块链安全 - DAO 攻击事件解析

2. 智能合约发送 ETH

我们可以在智能合约中用代码向某个地址(这个地址可以是人,也可以是智能合约)发送以太币,比较常见的两个方式是:

(1)调用 send 函数
比如:msg.sender.send(100)
(2)使用 message call
msg.sender.call.value(100)()

这两个方式不同的是发送的 gas 数量,gas 就是执行 opcode 需要花费的一种币,称作为 gas 也特别形象。

当调用 send 方法时,只会发送一部分 gas,准确地来讲,是 2300gas,一旦 gas 耗尽就可能抛出异常。

而使用 message call 的时候,则是发送全部的 gas,执行完之后剩余的 gas 会退还给发起调用的合约。

3.fallback 函数

智能合约中可以有唯一的一个未命名函数,称为 fallback 函数。该函数不能有实参,不能返回任何值。如果其他函数都不能匹配给定的函数标识符,则执行 fallback 函数。

当合约接收到以太币但是不调用任何函数的时候,就会执行 fallback 函数。如果一个合约接收了以太币但是内部没有 fallback 函数,那么就会抛出异常,然后将以太币退还给发送方。

下面就是一个 fallback 函数的代码示例:

区块链安全 - DAO 攻击事件解析

一般单纯使用 message call 或者 send 函数发送以太币给合约的时候,没有指明调用合约的某个方法,这种情况下就会调用合约的 fallback 函数。

攻击事件还原

我们先用简单的模拟代码来了解下整个攻击过程。
首先是存在漏洞的智能合约代码,Bank:

区块链安全 - DAO 攻击事件解析

用户可以通过 addToBalance 方法存入定量的以太币到这个智能合约,通过 withdrawBalance 方法可以提现以太币,通过 getUserBalance 方法可以获取到账户余额。

注意到这里是通过 message call 的方式来发送以太币,所以在调用 sender 的 fallback 函数的时候我们就会有充足的 gas 来进行循环调用。如果是 send 的方式,gas 只有 2300,稍微一操作就会耗尽 gas 抛出异常,是不够用来进行嵌套调用的。以下是不同操作所需要的 gas 数量:

区块链安全 - DAO 攻击事件解析

出问题的是 withdrawBalance 方法,特别是在修改保存在区块链的 balances 的代码是放在了发送以太币之后。

攻击代码如下:

区块链安全 - DAO 攻击事件解析

这里的 deposit 函数是往 Bank 合约中发送 10wei。withdraw 是通过调用 Bank 合约的 withdrawBalance 函数把以太币提取出来。注意看这里的 fallback 函数,这里循环调用了两次 Bank 合约的 withdrawBalance 方法。

攻击的过程如下:

(1)假设 Bank 合约中有 100wei,攻击者 Attack 合约中有 10wei
(2) Attack 合约先调用 deposit 方法向 Bank 合约发送 10wei
(3)之后 Attack 合约调用 withdraw 方法,从而调用了 Bank 的 withdrawBalance 方法。
(4) Bank 的 withdrawBalance 方法发送给了 Attack 合约 10wei
(5) Attack 收到 10wei 之后,又会触发调用 fallback 函数
(6)这时,fallback 函数又调用了两次 Bank 合约的 withdrawBalance,从而转走了 20wei
(7)之后 Bank 合约才修改 Attack 合约的 balance,将其置为 0

通过上面的步骤,攻击者实际上从 Bank 合约转走了 30wei,Bank 则损失了 20wei,如果攻击者多嵌套调用几次 withdrawBalance,完全可以将 Bank 合约中的以太币全部转走。

复现过程

给 Bank 合约 100wei,给 Attack 合约 10wei。
(1)部署 Bank,分配 100wei

区块链安全 - DAO 攻击事件解析

区块链安全 - DAO 攻击事件解析

分配给 Attack 10wei。
(3)调用 Attack 合约的 deposit 方法
(4)调用 Attack 合约的 withdraw 方法
(5)查看 Attack 合约的余额,变成了 30wei,即窃取了 20wei

DAO 攻击事件代码分析

在 DAO 源码中,有 withdrawRewardFor 函数:

区块链安全 - DAO 攻击事件解析

这里调用了 payOut 函数进行付款。

区块链安全 - DAO 攻击事件解析

而 payOut 中直接使用的是 message call 的方式发送以太币,从而导致了嵌套漏洞。

总结

在写智能合约进行以太币发送的时候,要使用 send 或者 transfer,不要使用 message call 的方式。DAO 事件直接导致了以太币硬分叉,分为 ETH 和 ETC。可见,区块链领域的安全不容忽视,因为其修复难度和所造成的影响都很高,毕竟是和钱打交道。

Tags:
免责声明
世链财经作为开放的信息发布平台,所有资讯仅代表作者个人观点,与世链财经无关。如文章、图片、音频或视频出现侵权、违规及其他不当言论,请提供相关材料,发送到:2785592653@qq.com。
风险提示:本站所提供的资讯不代表任何投资暗示。投资有风险,入市须谨慎。
世链粉丝群:提供最新热点新闻,空投糖果、红包等福利,微信:juu3644。