TheDAO攻击中RACEToEmpty

  • A+
所属分类:区块链技术

TheDAO 攻击中使用了 RACE To Empty的攻击方法。下面介绍一下RACE TO Empty的方法
下面代码看起来是安全,其实并不安全

function withdrawBalance() {  
  amountToWithdraw = userBalances[msg.sender];
  if (!(msg.sender.call.value(amountToWithdraw)())) { throw; }
  userBalances[msg.sender] = 0;
}

1、获取记录的余额 balances[ msg.sender ]
2、发送余额,发送不成功时抛出异常,本次调用不成功。
3、修改余额为0
这是一个看起来美好,实际在智能合约上执行时有问题的代码。关键在于钱包是有默认函数。比如像这样的代码

function () {  
  // To be called by a vulnerable contract with a withdraw function.
  // This will double withdraw.
  vulnerableContract v;
  uint times;
  if (times == 0 && attackModeIsOn) {
 times = 1;
 v.withdrawBalance();
   } else { times = 0; }
}

当你调用msg.sener.call.value时,就会调用到默认函数,而默认函数又调用了withdraw造成了递归调用。从堆栈上可以看到

vulnerableContract.withdraw run 1
   attacker default function run 1
  vulnerableContract.withdraw run 2
   attacker default function run 2

第一次调用 userBalances[msg.sender] 有当前余额值
第二次调用 由于 userBalances[msg.sender] = 0 还没有调用到,因此 userBalances[msg.sender]
还是原来的值,因此会造成重复支付。
避免的方式很简单,改为这样就可以避免

function withdrawBalance() {  
  amountToWithdraw = userBalances[msg.sender];
 userBalances[msg.sender] = 0;
 if( amountToWithdraw > 0 ) {
  if (!(msg.sender.call.value(amountToWithdraw)())) { throw; }
 }
}

非原创,具体可参考 http://vessenes.com/more-ethereum-attacks-race-to-empty-is-the-real-deal/

weinxin
共识社
用手机扫一扫,加入组织,时刻关注组织动态。
daodaoliang

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: