Mystery Box

First Flight #25
Beginner FriendlyFoundry
100 EXP
View results
Submission Details
Severity: medium
Valid

openBox() randomValue is not so random and can be predicted

Summary

In MysteryBox.sol, when a user wants to open a box using openBox() function, a randomValuewill define what prize a user will get. The problem is that randomValuedepends on block.timestampso it can be predicted by deploying a malicious contract that will do the same calculation and delegate the call to `MysteryBox` if `randomValue >= 99` .

Vulnerability Details

  1. Attacker buy a box on `MysteryBox`

  2. Attacker deploys Malicious smart contract that does the guessing of `randomValue`, and if the encode gives a Gold box, it forwards the attacker call to MysteryBox with a delegatecallto keep msg.sender

  3. Attacker calls malicious contract until a guaranteed Gold box is earned

  4. Attacker redeem the value of the box

This attack can be replayed indefinitely and deplete all funds from `MysteryBox`

Malicious contract that will open a box only if it's Gold

contract Attack {
MysteryBox public mysteryBox;
constructor(address _mysteryBox) {
mysteryBox = MysteryBox(_mysteryBox);
}
function attack() external {
uint256 randomValue = uint256(keccak256(abi.encodePacked(block.timestamp, msg.sender))) % 100;
if (randomValue >= 99) {
(bool success, bytes memory data) = mysteryBox.delegatecall(
abi.encodeWithSignature("openBox()")
);
}
}
}

Impact

An attacker can deplete all the funds without taking any risk by being granted a Gold reward every time he opens a box.

Tools Used

Manual

Recommendations

Do not use block.timestamp to generate a randomNumber
Instead, use chainlink VRF https://chain.link/vrf

Updates

Appeal created

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

Weak Randomness

Support

FAQs

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

Give us feedback!