Open code423n4 opened 1 year ago
Picodes marked the issue as duplicate of #167
Picodes marked the issue as satisfactory
Picodes marked the issue as selected for report
Keeping High severity as this seems exploitable to lock funds with no cost as the fallback function is payable
sanjay-staderlabs marked the issue as sponsor confirmed
This is fixed in the code
Lines of code
https://github.com/code-423n4/2023-06-stader/blob/7566b5a35f32ebd55d3578b8bd05c038feb7d9cc/contracts/VaultProxy.sol#L20-L36 https://github.com/code-423n4/2023-06-stader/blob/7566b5a35f32ebd55d3578b8bd05c038feb7d9cc/contracts/VaultProxy.sol#L41-L50
Vulnerability details
Impact
When the
VaultFactory
contract is deployed and initialized, theinitialise
method on the newly createdVaultProxy
implementation contract is never called. As such, anyone can call that method and pass in whatever values they want as arguments. One important argument is the_staderConfig
address, which controls where thefallback
function will directdelegatecall
operations. If an attacker passes in a contract that callsselfdestruct
it will be run in the context of theVaultProxy
implementation contract, and will erase all code from that address. Since the clones from the VaultProxy contract merely delegate calls to the implementation address, all subsequent calls for all created vaults from that implementation, will be treated like an EOA and returntrue
even though calls to functions on that proxy were never executed.Proof of Concept
AttackContract
that callsselfdestruct
in itsfallback
function.initialise
method on theVaultProxy
implementation contract. That address is stored in thevaultProxyImplementation
variable on theVaultFactory
contract. The attacker passes in the address ofAttackContract
as the_staderConfig
argument for theinitialise
function.VaultProxy
implementation contract, which triggers it'sfallback
function. Thefallback
function callsstaderConfig.getNodeELRewardVaultImplementation()
, and sincestaderConfig
is set theAttackContract
address, it returns the address of theAttackContract
.delegatecall
runs the fallback function ofAttackContract
in its own execution environment.selfdestruct
is called in the execution environment of theVaultProxy
implementation, which erases the code at that address.VaultProxy
implementation contract are now forwarding calls to an implementation address that has no code stored at it. These calls will be treated like calls to an EOA and returntrue
forsuccess
.Tools Used
Manual Analysis
Recommended Mitigation Steps
Prevent the
initialise
function from being called on theVaultProxy
implementation contract by inheriting from OpenZeppelin'sInitializable
contract, like the system is doing in other contracts. Call the_disableInitializers
function in the constructor and protectinitialise
with theinitializer
modifier. Alternatively, theinitialise
function can be called from theinitialize
function of theVaultFactory
contract when theVaultProxy
contract is instantiated.Assessed type
Access Control