To be a winner of Ethereum gambling game, All For One, by breaking PRNG (CVE-2018–12056)
I found a vulnerability in smart contract of ‘All For One’ which is a Ethereum gambling game. This game generates random numbers using
keccak256() function with 4 parameters, such as a private variable
block.difficulty. They are all publicly readable to anyone, so attackers can get rewards by predicting the random number.
‘All For One’ is a Ethereum gambling game. If you want to participate this game, you first bet 0.1 Ether on this contract through
play() function(See Figure 1). Players who bet on the smart contract are pushed in the array. After an amount of time, a winner is decided by
draw() function, a winner is decided by a random number. A red box in Figure 2
produceRandom() function generates a random number and return it. The random number is a index of a players array.
produceRandom() function calls
random() function at line 80, so finally
maxRandom() function is called(See Figure 3). In
maxRandom() function, it generates random numbers using
keccak256() function with 4 parameters. However, all the 4 parameters are publicly readable to anyone. Therefore, attackers can predict the random numbers and can be a winner.
I already explained several times how to exploit these vulnerability in my previous articles. If you want to know the way to exploit it, I recommend reading my articles, especially “Attack on Pseudo-random number generator (PRNG) used in 1000 Guess, an Ethereum lottery game (CVE-2018–12454)”.
Figure 4 shows the exploit contract. Attackers bet 0.1 Ether on All For One site and then can be a winner by using the exploit contract.
I reported it to admin and they patched it. They changed
draw() function as
private and generate random numbers by using Oraclize library.
When you generate random numbers in the smart contract, you must not use private variables and variables of past and current blocks.