目标
- 本文的目标是整理50个左右的随机数安全问题。
- 总结出随机数安全问题的一些规律。
- 为设定诸如
Predictability
等评价标准寻找灵感。
手段
- 不思考业务逻辑,单纯从代码出发,理解生成随机数的过程。
- 思考操控这个随机数的难度如何。
如何阅读本文
- https://etherscan.io/address/替换成下面的合约代码#code
2. 0xb8797a4ba7402d8a9ab62c4a12ef8846f1ea9a80
- 智能合约名:GoldenKingdom
- 智能合约类型:彩票。
- 随机数生成方式:LuckyDraw.sol23行,使用链上变量block.difficulty, now(0.7之后强制用block.timestamp)以及players的地址。
- 问题:使用链上变量和地址,容易被预测。
- 分类:使用“简单不安全”的链上变量作为随机数熵源;使用“私有”变量(可以被观测到内部信息)。
- 识别思路:
- 定位产生随机数的函数。
- 通过abi.encodePacked进行定位。
- 通过keccak256进行定位。
- 通过函数名random进行定位。
- 定位随机数种子:
- block.difficulty为链上变量。
- now为链上变量。
- players为私有变量。
- 定位函数传递:
- 调用时进行取模操作。
- 综上:
- 这是一个产生随机数行为的合约,风险极大。
- 定位产生随机数的函数。
3. 0x9c008a22d71b6182029b694b0311486e4c0e53db
- 智能合约名:Apymon
- 智能合约类型:NFT。
- 随机数产生方式:Apymon.sol113行,使用链上变量blockhash(block.number)。
- 问题:运行时blockhash(block.number)还未产生,结果为0。[1]
- 分类:误使用blockhash(block.number)作为随机数熵源。
- 识别思路:
- 定位产生随机数的函数。
- 通过abi.encodePacked进行定位。
- 通过keccak256进行定位。
- 定位随机数种子:
- blockhash(block.number)
- 定位后续操作:
- 进行取模。
- 结论:
- 这是对于blockhash的误使用,风险极大。
- 定位产生随机数的函数。
4. 0xc1ebbce86a24b6e045fc9f46af342d8dabe14272
- 智能合约:League
- 智能合约类型:彩票。
- 随机数产生方式:League.sol 221行,直接使用链上变量。
- 问题:使用链上变量和地址,容易被预测。
- 分类:使用“简单不安全”的链上变量;依赖于调用该合约的sender。
- 识别思路:和2的基本相同。
5. 0x8dc74D28B9821f7f9d0e95AB2D3C66f5276AC474
- 智能合约名:EthexJackpot
- 智能合约类型:竞猜下次的blockhash。
- 参考网址:https://bitcointalk.org/index.php?topic=5120151.msg50562585#msg50562585
- 随机数产生方式:??
- 问题:有可能被操控。
- 分类:可能被操控。
- 识别思路:??
6. 0xd5A3A5f35e8Db7740fF644752bce389fC958d5c1
7. 0xA11E4ed59dC94e69612f3111942626Ed513cB172
- 合约名:EtherLotto
- 智能合约类型:彩票
- 随机数产生方式:第39行 var random = uint(sha3(block.timestamp)) % 2;直接使用链上变量。
- 问题:非常容易被预测。
- 分类:使用“简单不安全”的链上变量作为随机数熵源。
- 识别思路:
- 定位变量名:
- 找到random。
- 定位变量来源:
- 完全依赖于timestamp。
- 结论:
- 风险非常大的随机数生成过程。
- 定位变量名:
8. 0xcC88937F325d1C6B97da0AFDbb4cA542EFA70870
- 合约名:Ethraffle_v4b
- 智能合约类型:彩票
- 随机数产生方式:第99行 uint winningNumber = uint(randHash) % totalTickets;而randHash变量的产生依赖于coinbase, msg.sender和block.difficulty。
- 问题:非常容易被预测。
- 分类:使用“简单不安全”的链上变量作为随机数熵源。
- 识别思路:和2基本相同。
9. 0xA65D59708838581520511d98fB8b5d1F76A96cad
- 合约名:BlackJack
- 智能合约类型:彩票。
- 随机数产生方式:15行 return uint8(uint256(keccak256(block.blockhash(b), player, cardNumber, timestamp)) % 52)
- 问题:b为当前区块block,结果恒为0。
- 分类:误使用blockhash(block.number)作为随机数熵源。
- 识别思路:基本和3相同。
10. 0xF767fCA8e65d03fE16D4e38810f5E5376c3372A8
- 合约名:LuckyDoubler
- 智能合约类型:彩票
- 随机数产生方式:122行,使用blockhash(block.number-1)
- 问题:容易被镜像攻击,产生相同结果的随机数。
- 分类:使用“简单不安全”的链上变量作为随机数熵源。
- 识别思路:基本和3相同。
11. 0x5acE17f87c7391E5792a7683069A8025B83bbd85
- 合约名:SmartBillions
- 智能合约类型:彩票
- 随机数产生方式:第561行 hash = getHash(player.blockNum); 获取超过256个区块长度的开奖信息;但需要admin来调用putHash往数据库打入hash,举办hackathon的时候admin开小差导致问题。
- 问题:blockhash只保存256个block,需要依赖admin。
- 分类:blockhash的误用。
- 识别思路:??
12. 0x2983eedfbd560b6d65ffa47de6a0f6d6fee6e136
- 合约名:Slotthereum
- 智能合约类型:彩票
- 随机数产生方式:使用私有变量(已自毁,未公开源码)。
- 问题:使用私有变量的时候,可以被他人看见。
- 分类:使用“私有”变量(可以被观测到内部信息)。
- 识别思路:?
14. 0x99b9791d1580bf504a1709d310923a46237c8f2c
- 合约名:MillionDollarRat
- 智能合约类型:彩票?
- 随机产生方式:commit & reveal方式?产生goldenRat并奖励赢家。
- 问题:?
15. 0xd1ceeeeee83f8bcf3bedad437202b6154e9f5405
- 合约名:Dice2Win
- 智能合约类型:彩票
- 随机产生方式:Commit & Reveal方式。
- 问题:有串谋风险。
- 分类:Commit&Reveal。
16. 0xEdB61f74B0d09B2558F1eeb79B247c1F363Ae452
- 合约名: GutterCats
- 智能合约类型:虚拟资产
- 随机产生方式:76行 156行,使用coinbase,timestamp, gaslimit, msg.sender和timestamp和block.number作为随机数种子
- 问题:使用链上变量和地址,容易被预测。
- 分类:使用“简单不安全”的链上变量作为随机数熵源;
- 识别方式:和2类似
17. 0x1681bcb589b3cfcf0c0616b0ce9b19b240643dc1
- 合约名:IslandToken
- 智能合约类型:代币
- 随机产生方式:1086行 使用timestamp和sender以及seed=69作为随机数种子.
- 问题:使用链上变量和地址,容易被预测。
- 分类:使用“简单不安全”的链上变量作为随机数熵源;
- 识别方式:和2类似。
18. 0x4a013d18330880167a2507bc7b2a90bd2c912ec7
- 合约名:MansionCashToken
- 智能合约类型:代币
- 随机产生方式:1097行 使用timestamp和sender以及seed作为随机数种子
- 问题:使用链上变量和地址,容易被预测。
- 分类:使用“简单不安全”的链上变量作为随机数熵源;
- 识别方式:和2类似。
19. 0x9b811024635626bc37e5d294b384077ab25dcf62
- 合约名:AsteroidScans
- 智能合约类型:?
- 随机产生方式:140行 使用blockhash作为随机数种子,并在144行获得seed。
- 问题:观察发现不是使用未来哈希作为变量,所以它同样会有使用blockhash的一系列问题。
- 分类:blockhash的不安全使用。
- 识别方式:和3类似。
20. 0x5283fc3a1aac4dac6b9581d3ab65f4ee2f3de7dc
- 合约名:AsciiPunks。
- 智能合约类型:NFT。
- 随机产生方式: AsciiPunks.sol
115行使用_seed, timestamp, sender和numToken作为随机数种子。 - 问题:使用链上变量和地址,容易被预测。
- 分类:使用“简单不安全”的链上变量作为随机数熵源;
- 识别方式:和2类似。
21. 0x1a22188b5f6faf7253a3defcc576884c0ff50a91
- 合约名:LotteryLikePool
- 智能合约类型:彩票
- 随机产生方式:LotteryLikePool.sol 536行
uint256 random = uint256(keccak256(abi.encodePacked(round_.calculation.seed, passedIterationsCount)));
- 问题:感觉是使用链上变量直接做的随机数种子,尽管做了很多封装,容易被预测。
- 分类:使用不安全的链上变量作为随机数熵源。
- 识别方式:和2类似。
22. 0x9af15d7b8776fa296019979e70a5be53c714a7ec
- 合约名:EvnToken
- 智能合约类型:代币。
- 随机产生方式:RewardDistributor.sol 59行
uint256 rand = block.timestamp * (block.difficulty == 0 ? 1 : block.difficulty) * (uint256(addressForRandom) >> 128) * 31 % 100;
。 - 问题:使用链上变量和地址,容易被预测。
- 分类:使用“简单不安全”的链上变量作为随机数熵源;
- 识别方式:和2类似。
23. 0x988b3A538b618C7A603e1c11Ab82Cd16dbE28069
- 合约名:KlerosLiquid
- 智能合约类型:流动代币
- 随机产生方式:239行有一个RNG类 里面获取随机数的方式很奇怪,类似使用链上变量,但是又讲不清楚。
- 问题:使用链上变量。
- 分类:使用“简单不安全”的链上变量作为随机数熵源;
- 识别方式:和2类似。
24. 0x3aE323c0589d32067c07B4A351b10bc900d8B50D
- 合约名:PackFive
- 智能合约类型:彩票。
- 随机产生方式:189行,尽管有很多操作,但还是依赖于链上变量。
- 问题:使用链上变量和地址,容易被预测。
- 分类:使用“简单不安全”的链上变量作为随机数熵源;
- 识别方式:和2类似。
25. 0x7bd29408f11d2bfc23c34f18275bbf23bb716bc7
- 合约名: Meebits
- 智能合约类型:NFT?
- 随机产生方式:326行,完全用链上变量生成的随机数
uint index = uint(keccak256(abi.encodePacked(nonce, msg.sender, block.difficulty, block.timestamp))) % totalSize;
- 问题:使用链上变量和地址,容易被预测。
- 分类:使用“简单不安全”的链上变量作为随机数熵源;
- 识别方式:和2类似。
26. 0x06bca1e513603a5544e0a70256607087aba73659
- 合约名:HUSTLERS
- 智能合约类型:?
- 随机产生方式:1875行,直接用block.number + block.timestamp作随机数源
- 问题:使用链上变量和地址,容易被预测。
- 分类:使用“简单不安全”的链上变量作为随机数熵源;
- 识别方式:和2类似。
27. 0x678e8128138eec59801a80e1d57d0a982b8db5bb
- 合约名:Jackpot
- 智能合约类型:彩票。
- 随机产生方式:1421行,几乎把所有的链上变量全部拿出来做随机数种子,而且blockhash还使用的是当前block的。
- 问题:结合了2和3的。
-
- 分类:使用“简单不安全”的链上变量作为随机数熵源;
- 识别方式:和2,3类似。
28. 0xbc13cdbf9cc107a04be2070f068690b7e7412868
- 合约名:Mogiets。
- 智能合约类型:NFT?
- 随机产生方式:80行,91行,使用blockhash获得随机。
- 问题:主要是3的问题。
- 分类:误使用blockhash(block.number)作为随机数熵源,或使用未来hash作为随机。
- 识别方式:?。
29. 0xee4650cbe7a2b23701d416f58b41d8b76b617797
- 合约名:AragonCourt
- 智能合约类型:?
- 随机产生方式:506行,使用未来hash作为熵源。
- 问题:存在着只记录256个blockhash的问题。
- 分类:属于blockhash很容易出现的误使用问题。
- 识别方式:和3类似。
30. 0xc0fcdb4d882c28238cbcfbb023f87a7a7a1bdaa1
- 合约名:MultipleWinners
- 智能合约类型:彩票?
- 随机产生方式:64行 直接使用外部调用的变量作为随机数,非常不安全。
- 问题:
31. 0x3c22e37a198835d8a6413e3999ac7a404157c5b9
- 合约名:ChonkFarm
- 智能合约类型:?
- 随机产生方式:做了专门处理的timestamp作为随机数熵源,不确定是否安全。https://swcregistry.io/docs/SWC-116
32. 0x02b5841550f699e68b32336d3f88fcf689ebfa20
- 合约名:ERC20Token
- 智能合约类型:Token
- 随机产生方式:448行,
uint screen = uint(keccak256(abi.encodePacked(now, msg.sender, nicetacos))) % 100;
其中niceacos不断自增。
33. 0x5fd335e64400eabecc9ebe80e3d2fcfb6c001adb
- 合约名:Niftysistas
- 智能合约类型:?
- 随机产生方式:209行,使用skillBase, nonce, id作为随机数种子,其中skillBase来自于blockhash。
34. 0xe9a2bbc6f08f200afba25474083d8b42a89abab8
- 合约名:Mars
- 智能合约类型:NFT?
- 随机数产生方式:245行 blockhash(block.number)作为随机数种子。
35. 0x082903f4e94c5e10a2b116a4284940a36afaed63
- 合约名:Pixls
- 智能合约类型:NFT?https://www.getpixls.com/
- 随机数产生方式:Pixls.sol 115行和上面的合约一模一样。
36. 0x27d22a7648e955e510a40bdb058333e9190d12d4
- 合约名:Ticket
- 智能合约类型:?
- 随机数产生方式:48行 引入了随机数,并且没有看到预言机或者VRF的字样,但是搞不清楚哪里调用了这个随机数函数
37. 0xe5e7DdADD563018b0E692C1524b60b754FBD7f02
- 合约名:Vyper_contract
- 智能合约类型:?
- 随机数产生方式:69行 randomLevel 使用block.timestamp, msg.sender, block.number, traitNonce作为随机数种子
38. 0xac9bb427953ac7fddc562adca86cf42d988047fd
- 合约名:SCATTER
- 智能合约类型:代币
- 随机数产生方式:131行 使用block.timestamp, _addr, _totolsuppluy作为随机数种子
39. 0xa05d1fea5688688db808c17d2f3d8faa9026a41f
- 合约名:Buccaneers
- 智能合约类型:?
- 随机数产生方式:80行~100行,使用链上变量作为随机种子,131行进行了调用。
40. 0x1a79dd60bedd1ef00bd7d6e3ec0d98b979e5fcdc
- 合约名:ERC20Token(?)
- 智能合约类型:代币
- 随机数产生方式:40行,使用now, msg.sender, nicetacos(一个自增的变量)作为熵源。
41. 0x9816c3f639f5dfdc8832ffca75499b312d1f0c54
- 合约名:AWMain
- 智能合约类型:彩票。
- 随机数产生方式:147行,使用block.difficulty, now - num作为熵源。
42. 0x06a6a7af298129e3a2ab396c9c06f91d3c54aba8
- 合约名:UniverseGalaxy
- 智能合约类型:?
- 随机数产生方式:251行 使用上一个block.number作为熵源
43. 0xe10a2d74e7233e4e66f361a116b2ab1f61dbffcb
- 合约名:ELG
- 智能合约类型:代币
- 随机数产生方式:530行 使用block.number和now作为熵源。
44. 0xa7437c148c782d260b929140262a8e873e7f7ff4
- 合约名:Bussiness
- 智能合约类型:交易返利
- 随机数产生方式:50行,52行,以msg.sender和block.timestamp作为熵源。
45. 0xde201daec04ba73166d9917fdf08e1728e270f06
- 合约名:MEXPToken
- 智能合约类型:代币。
- 随机数产生方式:496行,使用blockHashValue和_userSeed作为随机数熵源
46. 0x3e370a6c8255b065bd42bc0ac9255b269cfcc172
- 合约名:jackpot
- 智能合约类型:彩票。
- 随机数产生方式:134行 直接使用now, msg.sender和block.number作为随机数种子。
47. 0x028ff933bd86bd4d699b1643477f858626482d35
- 合约名:LUCKER
- 智能合约类型:彩票。
- 随机数产生方式:75行 直接使用block.difficulty和_usertime和_time作为随机数种子。
48. 0x7f6f3012373b4fc7c33812402a880407eeac317c
- 合约名:FairWin
- 智能合约:彩票。
- 随机数产生方式:典型的commit-reveal合约,有串谋风险。
49. 0x3a9fff453d50d4ac52a6890647b823379ba36b9e
- 合约名:ShuffleToken
- 智能合约:代币
- 随机数产生方式:699行和687行 使用_from, nonce, magnitude(of the tx), 和heap.size()作为随机数种子,但仍可以被预测。
50. 0xf317a365cfef0aa4357abd057048808a1d430402
- 合约名:Plague
- 智能合约:彩票(一个号称解决了Fomo3D的合约)。
- 随机数产生方式:最后一位进入游戏的玩家拿走奖池一半的资金,每次有玩家进入,就增加30秒,如果一直有人买,那么则奖池一直积累,越早入场赚得越多,超过30000基本就回本。
- 攻击方式:
- 传统矿主,在自己购买完之后,就拒绝打包后面的购买。
- 购买完key后用天价GAS堵塞以太坊,使得其他人的交易都无法正常打包。
- 参见:https://zhuanlan.zhihu.com/p/42762070
51. 0xa94753f10dae24e39f0dd88bf73718455da387f2
- 合约名:LUCK
- 智能合约:彩票。
- 随机数产生方式:75行 和47基本问题一样。
52. 0x63a389435f370f8aec9ddb179483bdf16d189d1c
- 合约名:Fusion
- 智能合约:NFT
- 随机数产生方式:1298行,获取随机的罕见性,data1, data2和data3由getdata3这个函数来,而getData3就直接是由链上的data数组获得; 1434行使用blockhash作为随机数种子(理得不清楚)
结论
- 链上随机数的主要生成方式有:
- 直接通过非blockhash的链上变量生成。
- 通过blockhash(block.number-1)或blockhash(block.number)调用。(镜像攻击/对blockhash的错误理解)。
- 间接地通过各种非blockhash链上变量进行调用。(增加理解难度)
- 通过调用合约的调用者的信息生成。
- 通过未来的blockhash(block.number)进行调用。(哈希保存问题)
- Commit&Reveal——有串谋风险。
- 预言机。
- 从可预测性的角度,直觉的判断
- blockhash错误使用>非blockhash链上变量>间接非blockhash链上变量>(调用者信息)>通过未来的blockhash(block.number)进行调用。>Commit&Reveal>预言机。
- 从实现的角度来讲:
- 如果面对较为复杂的情况,的确判断难度较大,需要更多的讨论和思考。
Reference
- [1] https://www.freebuf.com/vuls/179173.html