Mystery Box

First Flight #25
Beginner FriendlyFoundry
100 EXP
View results
Submission Details
Severity: low
Invalid

Private Visibility Vulnerability on `rewardPool` Data

Summary

The rewardPool array in the MysteryBox contract was initially set as a public variable, allowing anyone to access the complete list of rewards directly. This posed a risk as sensitive data regarding the potential rewards could be exposed to unauthorized users, potentially revealing important contract details. This report outlines the vulnerability, the mitigation applied by making rewardPool private, and how the implementation of role-based access control (RBAC) via OpenZeppelin's AccessControl further protected this data from being accessed by unauthorized parties.

Vulnerability Details

The rewardPool array was declared as a public variable, allowing any user or external contract to view all the potential rewards directly. While this may not seem critical at first glance, it could have been used by malicious actors to gain insights into the contract’s reward system, potentially enabling them to exploit or game the system.

Key Issues:

  • Public Visibility: The rewardPool array being public made it accessible to anyone, revealing all the rewards and their values.

  • Potential Data Leakage: Attackers could gain insights into the reward structure, which might allow them to strategize attacks or exploits against the contract.

Original Declaration of rewardPool:

Reward[] public rewardPool;

Impact:

  • Unauthorized users could view all rewards, leading to potential exploits or gaming of the reward distribution mechanism.

Mitigation Details

The mitigation involved two main steps:

  1. Changing rewardPool Visibility: The visibility of rewardPool was changed from public to private, restricting direct access.

    Reward[] private rewardPool;
  2. Implementing Role-Based Access Control: Introduced OpenZeppelin's AccessControl to manage access to the rewardPool data. A new VIEWER_ROLE was created, allowing only authorized users to access reward details via a controlled function getReward.

    Mitigated Implementation:

    bytes32 public constant VIEWER_ROLE = keccak256("VIEWER_ROLE");
    constructor() {
    _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
    _setupRole(VIEWER_ROLE, msg.sender); // Assign VIEWER_ROLE to the contract owner
    }
    function getReward(uint256 index) public view onlyRole(VIEWER_ROLE) returns (string memory name, uint256 value) {
    require(index < rewardPool.length, "Index out of bounds");
    Reward memory reward = rewardPool[index];
    return (reward.name, reward.value);
    }
    function addViewer(address viewer) public onlyRole(DEFAULT_ADMIN_ROLE) {
    grantRole(VIEWER_ROLE, viewer);
    }

Proof of Concept (PoC)

  1. Before Mitigation: A test demonstrated that any user, including unauthorized ones, could access all rewards in the rewardPool by simply calling the public array directly.

function testRewardPoolVisibility() public {
vm.startPrank(attacker);
// Attempt to access the rewardPool directly
MysteryBox.Reward[] memory rewards = mysteryBox.getRewardPool();
// Emit logs to show the retrieved rewards
for (uint256 i = 0; i < rewards.length; i++) {
emit log_named_string("Reward Name", rewards[i].name);
emit log_named_uint("Reward Value", rewards[i].value);
}
vm.stopPrank();
}

Results:

  • Before Mitigation: The test confirmed that the attacker could access all the reward data without any restrictions.

  1. After Mitigation: After changing the visibility of rewardPool to private and implementing role-based access control, any unauthorized attempt to access getReward resulted in a reverted transaction, effectively preventing access.

Logs:
[FAIL: AccessControlUnauthorizedAccount] testRewardPoolVisibility() (gas: 12889)

Results:

  • The test demonstrated that unauthorized access was prevented, confirming the effectiveness of the mitigation.

Impact

  • Data Privacy: By changing rewardPool to private and implementing role-based access control, unauthorized access to sensitive reward data was prevented.

  • Security Enhancement: This significantly reduced the risk of potential exploits that could arise from attackers gaining insights into the reward distribution.

Tools Used

  • Manual code analysis

  • Foundry for testing the visibility vulnerability

Recommendations

  1. Limit Public Access: Ensure that sensitive data structures are kept private unless there is a clear need for public visibility.

  2. Use Access Control Mechanisms: Implement role-based access control for functions that interact with sensitive data to ensure only authorized users can access or modify them.

  3. Regularly Audit Access Controls: Periodically review and audit access control configurations to prevent unauthorized data exposure.

Conclusion

The rewardPool array in the MysteryBox contract was initially vulnerable due to public visibility, allowing unauthorized users to access sensitive reward data. By changing the array to private and implementing role-based access control, this vulnerability was successfully mitigated, ensuring that only authorized users can access the data. This serves as a crucial reminder to always implement appropriate access controls for sensitive data in Ethereum smart contracts to prevent unauthorized access and potential exploits.

Updates

Appeal created

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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

Give us feedback!