Hawk High

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

LevelTwo is missing UUPSUpgradeable resulting in unrestricted upgrade to a malicious implementation

Summary

The LevelTwo contract is missing the UUPSUpgradeable inheritance, which is a critical security vulnerability in the upgrade mechanism. This allows any address to upgrade the contract, bypassing the intended access controls.

Vulnerability Details

In the current implementation:

  1. LevelOne inherits from UUPSUpgradeable and has a proper _authorizeUpgrade function with onlyPrincipal modifier

  2. LevelTwo is missing the UUPSUpgradeable inheritance, which means:

    • It doesn't inherit the upgradeTo and upgradeToAndCall functions

    • It doesn't have the _authorizeUpgrade function

    • It doesn't have the proxiableUUID function

This creates a dangerous situation where:

  1. The proxy contract still has the upgradeTo and upgradeToAndCall functions from UUPSUpgradeable

  2. These functions can be called by any address

  3. The _authorizeUpgrade check is missing in LevelTwo

  4. This allows unauthorized upgrades to any implementation

Impact

The impact is severe:

  1. Access Control Bypass: Any address can upgrade the contract to any implementation

  2. Malicious Upgrades: An attacker could:

    • Upgrade to a malicious implementation

    • Steal funds from the contract

    • Manipulate student scores and teacher data

    • Drain the bursary

    • Change the USDC token address

  3. Permanent Damage: Once upgraded to a malicious implementation, the contract's state could be permanently corrupted

  4. Financial Loss: All funds in the contract could be stolen

  5. Reputation Damage: The school's data and funds could be compromised

Tools Used

  • Manual code review

  • Foundry for testing

  • Solidity inheritance analysis

Recommendations

  • Add UUPSUpgradeable inheritance to LevelTwo:

contract LevelTwo is Initializable, UUPSUpgradeable {
// ... existing code ...
}
  • Implement proper _authorizeUpgrade function with access control:

function _authorizeUpgrade(address newImplementation) internal override onlyPrincipal {
// Add any additional upgrade validation if needed
}
  • Add proxiableUUID function to ensure upgrade compatibility:

function proxiableUUID() external pure returns (bytes32) {
return keccak256("org.openzeppelin.contracts.proxy.UUPSUpgradeable");
}
  • Add upgrade validation in the graduate function:

function graduate() public reinitializer(2) {
// Add validation to ensure upgrade is authorized
require(msg.sender == principal, "Only principal can graduate");
}
  • Consider implementing a timelock for upgrades to add an additional security layer

  • Add comprehensive tests for upgrade authorization:

    • Test that only principal can upgrade

    • Test that unauthorized addresses cannot upgrade

    • Test that upgrade validation works correctly

This vulnerability is particularly dangerous because it combines with the storage collision vulnerability we found earlier, potentially allowing an attacker to both upgrade the contract and corrupt its state.

Updates

Lead Judging Commences

yeahchibyke Lead Judge 7 months ago
Submission Judgement Published
Validated
Assigned finding tags:

failed upgrade

The system doesn't implement UUPS properly.

Support

FAQs

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

Give us feedback!