Mystery Box

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

H2 State-Reverting Vulnerability

Summary

In this attack, an attacker deploys a contract with two primary functions: one to purchase a mystery box and another called AlwaysWinning.

This strategy allows the attacker to exploit the contract's logic, ensuring they always receive valuable rewards, as the box remains unopened whenever the balance condition fails, enabling repeated attempts until they obtain the desired treasures.

Vulnerability Details

In this attack, the attacker deploys a contract with two main functions:

  1. Buying the Box: The attacker first calls a function to purchase a mystery box, ensuring that the contract owns the box. This step is straightforward and sets the stage for the exploitation.

  2. AlwaysWinning Function: The core of the attack lies in this function. When invoked, it opens the mystery box and checks the balance before and after the operation. The function verifies whether the Ether balance has increased by a specific threshold (e.g., at least 0.5 ether). If the condition is not met, the transaction reverts, preventing the box from being opened.

By employing this strategy, the attacker effectively ensures that they always receive the rarest treasures, as the box remains unopened whenever the balance increase condition fails, thus allowing them to continuously attempt to open the box until they obtain the desired rewards.

Impact

High Level Impact, it will drain the contract balance.

Tools Used

Manual Review,

Recommendations

Use the modifer named as CallerIsNotContract on the BuyBox and OpenBox function.

modifer CallerIsNotContract{
require(tx.orgin == msg.sender,"Contract call is detected.");
_;
}

Attacker Contract Functions POC

Complete contract can be provided on request.

Intialize the target in the constrcutor.
Call the function buyMysteryBox() with the value of 0.1 ether.
Call the AlwaysWinning until it the transcation is successful.
Main two functions are:

//Function to buy a mystery box
function buyMysteryBox() public payable {
require(msg.value == 0.1 ether, "Incorrect ETH sent"); // Adjust based on the box price in MysteryBox
TargetMysteryBox.buyBox{value: msg.value}();
}
// Function to keep winning rewards
function AlwaysWinning() public {
uint256 balanceBefore = address(this).balance;
TargetMysteryBox.openBox();
TargetMysteryBox.claimAllRewards();
uint256 balanceAfter = address(this).balance;
require(balanceAfter >= balanceBefore + 0.5 ether, "The treasures is not rare treasures");
}
Updates

Lead Judging Commences

inallhonesty Lead Judge
about 1 year ago

Appeal created

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

Weak Randomness

xmrsaifx Submitter
about 1 year ago
inallhonesty Lead Judge
about 1 year ago
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!