DistributionV2
contract inheriting UUPSUpgradeable
so overriding _authorizeUpgrade()
function. But adding no access control to this function can lead to setting implementation contract by anyone since this function is called for authorization in UUPSUpgradeable
. By setting any malicious contract as implementation attacker can selfdestruct() the proxy contract. Since implementation is called using delegatecall from proxy.
contracts/mock/DistributionV2.sol
Since DistributionV2
contract is inheriting UUPSUpgradeable
from openzeppelin we can see in upgrading implementation address _authorizeUpgrade()
is called.
https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/proxy/utils/UUPSUpgradeable.sol#L86C5-L90C1
DistributionV2
implementation contractFirst attacker will call upgradeToAndCall
to main proxy contract which will change the implementation contract address to his malicious DistributionV2
contract.
Now Attacker will call createPool
to main proxy contract of DistributionV2
and by delegatecall
proxy will call implementation contract .It will destroy the main proxy contract using selfdestruct()
. And erase all the storage from main proxy contract of DistributionV2.
The main proxy contract will be destroyed and erase all the storage from main proxy contract of DistributionV2.
Manual Review
Add proper access control to _authorizeUpgrade()
function since it is used for authorization at the time of changing implementation contract address. This can be mitigated by using 'OwnableUpgradeable' of openzeppelin and add onlyOwner
modifier to the _authorizeUpgrade()
function so. Only owner can be authorized to upgrade the implementation address. Add one initalizer function also to initialize the owner.
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.