主页 > imtoken钱包官网下载 > 智能合约游戏之死——Dice2win安全分析

智能合约游戏之死——Dice2win安全分析

imtoken钱包官网下载 2023-03-11 07:58:38

Dice2win 是目前以太坊上非常流行的区块链游戏。 其最大的特点是理论上的公平性保证。 每天有超过 1,000 ETH 投入到这个游戏中。

Dice2win官网:

Dice2win合约代码:#code

dice2win 的游戏很简单,就是一个赌概率的问题。

相当于猜硬币的正反面。 只要猜对了,就能以相应的概率赢得收获。

这是最简单的依赖公平的游戏合约。 只要“庄家”能够保证绝对的公平,那么这个游戏就成立了。

2018 年 9 月 21 日,我在

《Ethereum Contract Audit CheckList之《以太坊智能合约编码设计问题》影响分析报告》

提到以太坊智能合约存在弱随机数问题,提到在dice2win的合约中实现了很好的随机数生成方案hash-commit-reveal。

2018年10月12日,奇虎360核心安全彭志娘发表了《不公平的游戏,Dice2win公平性分析》,其中提到了关于Dice2win的三个安全问题。

在阅读文章的过程中,我重新审视了Dice2win的合约代码,发现在上次阅读时我对Dice2win的执行过程有误解,并且Dice2win还在以下代码中迭代更新了Merkle证明函数。 下面我们就着重谈谈这些问题。

Dice2win安全分析

选择中止攻击

让我们回顾一下dice2win的代码

function placeBet(uint betMask, uint modulo, uint commitLastBlock, uint commit, bytes32 r, bytes32 s) external payable {// 检查赌注是否处于“干净”状态。赌注存储 bet = bets[commit];require (bet. gambler == address(0), "Bet should be in a 'clean' state.");// 验证输入数据范围.uint amount = msg.value;require (modulo > 1 && modulo = MIN_BET && amount 0 && betMask 0 && betMask placeBlockNumber, "settleBet 在与 placeBet 相同的块中,或之前。"); 要求(块。编号

主要函数有placeBet和settleBet,placeBet函数主要是建立赌注,settleBet是抽奖。 最重要的一点是这里完全遵守了hash-commit-reveal方案的实现。 随机数生成过程在服务器端。 整个过程如下。

用户选择自己的投注方式,确认后点击投注按钮。

服务器生成一个随机数reveal,生成本次赌博的随机数哈希信息,以及有效的最大区块数,对这些数据进行签名,并将commit和信息签名发送给用户。

用户将获得的随机数hash、lastBlockNumber等信息与投注信息打包,通过Metamask执行placebet函数交易。

一段时间后,服务器将进行随机数开奖,服务器

原文中提到,庄家(服务器)收到用户猜中的号码,可以选择是否中奖比特币合约分析软件,选择一些对自己不利的暂停,让庄家获得更大的收益。

这确实是这类合约最容易出现的问题,庄家就是靠这种方式来放大庄家中奖的概率。

上述过程如下

上面说的中止攻击的选项就是上图右边可能出现的问题

整个过程中最大的问题是placebet和settlebet有一个强制执行顺序,否则其中一个block.number得不到正确的数字,这正是应该的。 当用户下注时,执行下注功能,服务器可以获取到用户的下注信息。 此时服务器有随机数,打包的投注的block.number,投注信息。 服务器可以提前计算用户是否中奖,并可以选择是否中止本次交易。

选择彩票攻击

原文中提到了一个很有意思的攻击方式。 在了解这种攻击方式之前,我们首先需要了解一下区块链的共识算法。

比特币区块链采用工作量证明(PoW)机制,这是一种称为工作量证明的机制。 提议者需要经过大量的计算才能找到满足条件的哈希。 当找到满足条件的哈希时,也证明了提议者的工作量。 但是在这种情况下,可能会有多个提议者,所以可能会出现链的分叉。 这个结果的区块链方法是选择最长的链作为最终结果。

当你计算出的区块被丢弃时,就意味着你付出的成本白费了。 因此,矿工会选择更容易保存的链继续计算。 这也意味着,如果有人破坏,需要付出大量的经济成本。

借用原文的一张图

链上计算的b2、c5、b5、b6的打包交易都会回滚,交易失败,不识别区块。

回到 Dice2win 合约,Dice2win 是一个预计不可逆的交易过程。 对于赌博来说,单向不可逆是一个非常重要的原则。 所以Dice2win新增加了MerikleProof方法来解决这个问题。

MerikleProofi方法的核心是Dice2win无论分叉与否,以及该块是否会被丢弃,都认可这笔交易。 当服务器收到投注交易(placebet)时,区块会立即被抽取。

MerikleProofi 的承诺:

上述方法的原理与以太坊的区块结构有关。 具体可以参考《不是公平的游戏,Dice2win的公平性分析》一文中的分析,但是这种方法确实在一定程度上解决了开奖速度的问题,甚至降低了上面提到的选择中止攻击的难度.

然而,新的问题又出现了。 当 placebet 交易被打包成多个分叉区块时,服务器可以接受收益更多的区块,从而获得最大收益。 但是这种攻击方式有效,主要有以下几个原因:

Dice2win 需要一个具有一定算力的矿池来主动影响链上的区块打包,但大部分算力还是掌握在公共矿池手中。 所以这种攻击方式不适合主动攻击。

被动遇到分叉也不过分,尤其是遇到placebet打包的区块,这个区块的hash只是多了选择,还是不可控。 多种情况的结果大概率是一样的。

从这点来看,这种攻击方式的效率有限,对大部分玩家影响不大。

任意彩票攻击(Merkle证明验证绕过)

在上面的分析中,我们详细分析了我们Merkle证明的好处和问题。 但如果从根本上绕过 Merkle 证明机制,那么问题就更大了。

Dice2win 以前见过这种类型的攻击

攻击者成功构造攻击合约,通过合约调用placeBet下注,并伪造Merkle证明调用settleBetUncleMerkleProof抽奖,控制下注成功概率为100%。

分析攻击合约可以揭示合约中的多个安全问题:

1. Dice2win是一个不断更新的合约,有多个版本。 但是存在一个问题,确定银行家身份的secretSigner值的多个版本是相同的,导致在多个合约中使用相同的签名。

2. placebet中最后一个commitlaskblock的校验有问题

用作签名的commitlastblock定义是uint256,但只有uint40用作签名。 也就是说,我们在执行placeBet的时候,可以修改高位数字,让某个签名信息一直有效。

3.Merkle proof边界检查不严格。

在最近的一次提交中,dice2win 修复了一个与 Merkle proofcheck 范围相关的漏洞。

此检查使 Merkle 证明更加严格

4. SettleBet权限问题

经过我的研究,其实在Dice2win的游戏逻辑中,settleBet应该只是服务端调用的(只有庄家才能抽奖),但是在之前的版本中,并没有这样的设置。

在新版本中,settleBet 增加了这个限制。

绕过Merkle证明的方法这里不再赘述。 有兴趣的可以阅读原文。

退款下注

感谢奇虎360核心安全的@Zhiniang Peng 在这里提出我的问题。 一开始,一些认识上的偏差导致了错误的结论。

原文最后提到了一个refundBet函数的underflow,我们来看看这个函数的代码

跟进getDiceWinAmount函数,发现jackpotFee不可控

其中,JACKPOT_FEE = 0.001 ether,金额必须大于0.1 ether,金额来自投注变量

bet 变量只能在 placebet 中设置。

但不幸的是,在 placebet 中进行了相同的调用

所以我们无法构建一个完整的攻击过程。

但是当我们回到refundBet函数时,我们无法控制jackpotFee,那么我们可以控制jackpotSize吗?

首先,我们需要了解 jackpotSize 的作用。 在Dice2win的规则中,除了自己的规则外,还有一个额外的奖品,是从上次奖品公布后的交易佣金中累积的。

如果有人中了大奖,该值将重置为零。

但是这里涉及到竞争,完整的使用过程如下:

攻击者下注并获得承诺

一名幸运用户在下注前中了大奖

攻击者调用 refundBet 进行退款

jackpotSize 成功溢出

总结

回溯分析整个Dice2win合约后不难发现,由于智能合约与传统服务器的逻辑不同,我们平时的很多安全思路遇到了更多的问题。 区块链的不可信任原则直接导致随机数生成方法的难度加深。 目前最成熟的hash-commit-reveal方式是通过服务端与智能合约的交互来实现的。 它在随机数保密性方面具有很高的完成度。 不幸的是,无法避免从服务器获取过多信息的问题。

在hash-commit-reveal方法的基础上,只要服务器不能立即响应抽奖,abort攻击就会一直存在。 有趣的是,Dice2win合约中Merkle证明功能的初衷是为了实现更快的抽奖,但在一定程度上降低了选择中止攻击的可能性。

任意抽奖攻击是一种针对 Merkle 证明的攻击方法,满足了所谓函数越多比特币合约分析软件,漏洞越多的问题。 这种攻击是微妙的,也是一种有趣的利用方式。

到目前为止,无论是底层机制还是随机数的产生方式,智能合约的安全性还有很长的路要走。

▼ 智能合约审计服务▼

针对目前主流的以太坊应用,智创宇提供专业、权威的智能合约审计服务,避免因合约安全问题造成的财产损失,为各类以太坊应用的安全保驾护航。

知乎创宇404智能合约安全审计团队: