In the contracts that implement Openzeppelin’s Upgreadable model, uninitialized Implementation contract can be taken over by an attacker with initialize() function.
Example LLMOracleManager contract.
Scenario:
Proxy & Implementation are deployed.
The Proxy delegates calls to Implementation.initialize() which sets the owner and switches initialized to true in the state of the Proxy.
The storage of Implementation however is still intact e.g owner is unset and initialized is false.
An attacker calls initialize() directly on Implementation and sets himself as the owner.
From here, he has full control to perform any maliceous activities.
Take-over by an attacker means contract sabbotage allowing him to execute privileged activities maliceously.
Manual Review
From Openzeppelin Docs:
Do not leave an implementation contract uninitialized. An uninitialized implementation contract can be taken over by an attacker, which may impact the proxy. To prevent the implementation contract from being used, you should invoke the _disableInitializers function in the constructor to automatically lock it when it is deployed:
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.