To be a winner of Ethereum gambling game, All For One, by breaking PRNG (CVE-2018–12056) [Blog post] Retrieved from: medium.com

Abstract

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 _seedblockhash(block.number-1)block.coinbase, and block.difficulty. They are all publicly readable to anyone, so attackers can get rewards by predicting the random number.

Details

Figure 1. play() function

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.

Figure 2. draw() function. A winner is decided by a random value.

In 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.

Figure 3. maxRandom() function generates a random value using keccak256() function with 4 parameters.

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.

Exploit

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. exploit contract

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.

Report

I reported it to admin and they patched it. They changed draw() function as private and generate random numbers by using Oraclize library.

Conclusion

When you generate random numbers in the smart contract, you must not use private variables and variables of past and current blocks.