作者DarkerDuck (达克鸭)
看板DigiCurrency
标题[分析] DAO攻击简单解释
时间Sun Jun 19 04:20:14 2016
这两篇写得还不错,可以让局外人稍微了解一下
https://www.bikeji.com/t/4027#reply3
DAO 提现bug
简述
恶意用户通过一个合约地址而不是普通的用户地址(不含智能合约)参与DAO,之後通过
Split(DAO概念里的退出、提现),利用这个合约地址反复调用DAO的提现方法,在余额
减少N的情况下提现k*N的提现。
攻击表现
[DAO项目]的合约地址0xbb9bc244d798123fde783fcc1c72d3bb8c189413上可以看到大量到
地址[0x304a554a310c7e546dfe434669c62820b7d83490]的内部交易[
https://etherscan.io/txsInternal?a=0xbb9bc244d798123fde783fcc1c72d3bb8c189413&p=3
]
(内部交易:Internal transaction是指合约执行过程中产生的交易,比如在合约内给用
户转账)
目前DAO还有余额7,930,715.340858306 Ether ($137,915,139.78),黑客地址
3,641,694.241898506 Ether ($63,583,981.46)
原理
DAO合约记录着用户的余额,提现时候的伪代码如下:
// msg.sender为交易发送方的地址,这里就是提现的用户
if (balance[msg.sender]>=withdrawRequest) { //检查是否有足够的钱
msg.sender.send(withdrawRequest); //给用户转账
balance[msg.sender] -= withdrawRequest; //在记录中扣除相应的数额
}
合约在执行这里的msg.sender.send(withdrawRequest)时会产生一个内部交易,这个交易
很简单,就是从这个合约转账withdrawRequest给提现用户地址。但是以太坊所有交易在
转账的同时会执行交易接收方地址的合约。通常提现的地址是个普通用户,所在的地址没
有智能合约,而这里,黑客从一个自己写的合约发送提现申请,当这个地址收到钱时就会
执行黑客合约里定义的默认操作。
//黑客合约的默认操作
function defaultAction() {
//设定DAO合约的地址
address DAO = 0xbb9bc244d798123fde783fcc1c72d3bb8c189413;
if (attackMode) { //是否开启了攻击模式
DAO.withdraw(200); //递归调用DAO的提现操作
}
}
这样当黑客发起提现时,以太坊的执行过程如下: 执行到msg.sender.send这行,触发黑
客合约执行,继续调用DAO的提现,再次执行到msg.sender.send,注意这里的代码是在
msg.sender.send执行後完才扣除用户在DAO里记录的余额,因此再次执行时用户的余额还
是不变的...... 只要DAO合约还有钱,黑客给定的手续费足够,黑客不终止,这个过程可
以一直进行下去。
这个问题可以在写合约的时候解决。
-先扣除用户余额,再转账
-在转账给用户时只给足够小的手续费(Gas),即使递归调用也因为Gas耗尽而结束
-一旦开始提现,锁定合约的状态,不允许其他提现操作进行
DAO的开发人员已经考虑了这个问题,但是没有修复所有有这个漏洞的地方,被黑客所利
用。
目前的解决方案
DAO不能暂停,因此黑客的攻击还可以继续下去。黑客地址已经偷取了近三分之一DAO合约
里的以太币。目前开发人员号召DAO的用户否决黑客所用的Split申请,以及广播大量垃圾
交易阻塞以太坊的网络,不让黑客的交易被打包。终极的解决方案是以太坊回滚,会严重
影响以太坊的声望。
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 36.237.84.197
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/DigiCurrency/M.1466281216.A.E21.html
1F:推 koucc: 这漏洞尚未补上,虽然理论上任何人现在都能发起这个代码攻击 06/19 11:10
2F:→ koucc: 盗走DAO的eth,但过程需要split出一个子DAO则需要获得投票 06/19 11:11
3F:→ koucc: 同意,在DAO刚运作这几天我进去看投票项目,充斥着一堆和DAO 06/19 11:12
4F:→ koucc: 无关的表决项目,大家都在乱玩投票,才造成骇客能趁乱通过 06/19 11:13
6F:推 koucc: 最下方那个musical performance的split proposal就是骇客 06/19 11:49
7F:→ koucc: 使用的标的,投赞成票的人只有24个,提案并未通过 06/19 11:50
8F:→ koucc: 所以我不懂的地方是为何一个没通过的提案也能分出子DAO 06/19 11:51
9F:→ koucc: 骇客是投赞成票的其中一人,他在2天前上传了#225号合约 06/19 11:54
10F:→ koucc: 虽然上面把原理解释得很容易,合约代码却有1155行 06/19 11:56
12F:→ koucc: 因为骇客提的FUN-SPLT-42 Congo Split都获得同意通过 06/19 12:20
13F:推 Rasin: 如果那骇客提出控告 ETH会归谁还不好说 真是越演越精彩... 06/19 15:16