Hawk High

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

Missing _disableInitializers()

summary

we must need to have _disableInitializers() inside the constructor of the LevelOne contract

vulnerability details

-> In UUPS proxies, all state lives in the proxy, while the implementation’s functions must be “initialized” via an external initialize() function rather than a constructor. If _disableInitializers() is not called in the implementation contract’s constructor, anyone can call initialize() directly on the implementation, thereby becoming its “owner” and bypassing the proxy’s access controls.

-> Once an attacker controls the implementation, they can invoke upgradeToAndCall() (protected by the malicious owner role) to delegatecall into a contract containing a selfdestruct opcode, effectively deleting the implementation’s code
. After self-destruction, all proxies pointing to that implementation will have no logic to delegate to, breaking the upgrade path.

Steps To Attack

  1. Deploy the UUPS implementation without _disableInitializers() in its constructor.

  2. Call initialize(attackerAddress) directly on the implementation contract: the attacker becomes owner.

  3. Deploy a malicious upgrade contract with a function that executes selfdestruct(address(proxy)).

  4. As “owner,” the attacker calls upgradeToAndCall(maliciousAddress, data) on the proxy, which delegatecalls into the malicious contract and triggers selfdestruct, wiping the implementation

impact - High

likelyhood - High

Recommendations

constructor() {
_disableInitializers();
}
Updates

Lead Judging Commences

yeahchibyke Lead Judge 16 days ago
Submission Judgement Published
Validated
Assigned finding tags:

contract can be re-initialized

The system can be re-initialized by an attacker and its integrity tampered with due to lack of `disableInitializer()`

Support

FAQs

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