Attacker can selfdestruct the code/logic of SmartAccount's implementation contract, leading to permanent loss of funds, of the owner of SmartAccount #357
Labels
3 (High Risk)
Assets can be stolen/lost/compromised directly
bug
Something isn't working
duplicate-496
satisfactory
satisfies C4 submission criteria; eligible for awards
sponsor confirmed
Sponsor agrees this is a problem and intends to fix it (OK to use w/ "disagree with severity")
Lines of code
Vulnerability details
Vulnerability
The core issue is that the implementation contract of SmartAccount has NOT been initialised in its OWN context. Though it has been, in its Proxy's context. This gives anybody the ability to directly call SmartAccount.init() in its own context, and become owner of this implementation contract and set any value they wish to the _entryPoint variable. Now, they can call SmartAccount.execFromEntryPoint() which can delegate call to a malicious contract that can selfdestruct() itself. This results in the code of SmartAccount implementation contract getting destroyed forever, giving no chance for its Proxy to upgrade its logic, because the contract upgrade logic, i.e updateImplementation() function is defined in the destroyed implementation contract itself. This bug is very similar to the one in OpenZeppelin's UUPS proxies: https://forum.openzeppelin.com/t/uupsupgradeable-vulnerability-post-mortem/15680
Impact
Because the code or logic of the SmartAccount is destroyed forever with no possibility to upgrade it, all the funds that it held will be permanently lost, plus the smart contract wallet becomes completely unusable as its Proxy will essentially be delegating calls to an address with no executable code.
Proof of Concept
Add this malicious contract, Suicide.sol in
contracts/smart-contract-wallet
directory:Add the following piece of code in testGroup1.ts on line 124 (https://github.com/code-423n4/2023-01-biconomy/blob/53c8c3823175aeb26dee5529eeefa81240a406ba/scw-contracts/test/smart-wallet/testGroup1.ts#L124), to add implementation contract destroy logic to the test suite and see its consequence (P.S. refer diffchecker below for completely updated testGroup1.ts with initialisations etc.):
Also find the diffchecker of
testGroup1.ts original
vstestGroup1.ts with POC
here: https://www.diffchecker.com/cOE0nXaL/As a result of this logic addition, all the tests that were initially passing, now fail with
Error: call revert exception
on every function call made to the SmartAccount proxy, asdata="0x"
on its implementation contract:BEFORE
AFTER
Tools Used
Manual
Recommended Mitigation Steps
In SmartAccountFactory, add
BaseSmartAccount(_defaultImpl).init(_owner, _entryPoint, _handler);
indeployCounterFactualWallet()
as:The text was updated successfully, but these errors were encountered: