New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AmbireAccount implementation can be destroyed by privileges #10
Comments
On first reading, I'm confused because there is a constructor but no initializer, so I don't get how a wallet could be deployed behind a minimal proxy: how do you set the first privilege addresses? So it seems that either the constructor needs to be changed to an initializer, or the intent is to deploy the whole bytecode for every wallet |
@Picodes we use a completely different mechanism in which we geenerate bytecode which directly SSTORES the relevant We absolutely disagree with using an initializer, it is leaving too much room for error as it can be seen from the two Parity exploits. That said, this finding is valid and removing the constructor is one solution, another is just ensuring we deploy the implementation with no privileges. Wyt? |
@Picodes we are in the process of fixing this by removing the constructor. I would say this finding is excellent but I am considering whether the severity should be degraded, as once the implementation is deployed with empty |
@Picodes we decided to remove the constructor because it just makes things more obvious (that in production privileges are not set via the constructor) but with that said, I just remembered that this vulnerability is mitigated by the fact the implementation will be deployed via CREATE2 and can be re-deployed |
So:
Overall, considering that there shouldn't be any trust assumption in this repository, I think Medium severity is appropriate, under "the function of the protocol or its availability could be impacted, or leak value with a hypothetical attack path with stated assumptions, but external requirements". |
Picodes marked the issue as satisfactory |
I'm not sure I agree with this: anyone can use CREATE2 on the factory to deploy the contract, so the team cannot extort anyone for anything |
Ah right I don't know why I had in mind a permissioned factory |
In that light, I think this can be downgraded. But we took the recommendation and removed the constructor in the v2 branch, also to avoid confusion |
But in that case the issue would be present again, and the same could happen if you redeploy it. I think the severity is well justified given the potential consequences. |
Keeping Medium severity for this one for the arguments above (even if the team intended to deploy through the factory they could do differently) and because of the security model of the wallet which is very strict as it assumes no privileged role |
Lines of code
https://github.com/AmbireTech/ambire-common/blob/5c54f8005e90ad481df8e34e85718f3d2bfa2ace/contracts/AmbireAccount.sol#L58-L65
Vulnerability details
AmbireAccount implementation can be destroyed by privileges
The AmbireAccount implementation can be destroyed, resulting in the bricking of all associated wallets.
Impact
The AmbireAccount contract has a constructor that setups privileges, these are essentially addresses that have control over the wallet.
https://github.com/AmbireTech/ambire-common/blob/5c54f8005e90ad481df8e34e85718f3d2bfa2ace/contracts/AmbireAccount.sol#L58-L65
Normally this constructor is not really used, as wallets are deployed using proxies. The proxy constructor is the actual piece of code that setups the privileges storage to grant initial permission to the owner of the wallet.
However these proxies need to rely on a reference implementation of the AmbireAccount contract. A single contract is deployed and its address is then injected into the proxy code.
The main issue is that privileges defined in the reference implementation have control over that instance, and could eventually force a destruction of the contract using a fallback handler with a
selfdestruct
instruction (see PoC for a detailed explanation). This destruction of the implementation would render all wallets non-functional, as the proxies won't have any underlying logic code. Consequently, wallets would become inaccessible, resulting in potential loss of funds.It is not clear the purpose of this constructor in the AmbireAccount contract. It may be present to facilitate testing. This issue can be triggered by a malicious deployer (or any of the defined privileges) or by simply setting up a wrong privilege accidentally. Nevertheless, its presence imposes a big and unneeded security risk, as the destruction of the reference implementation can render all wallets useless and inaccessible.
Proof of Concept
The following test reproduces the described issue. A deployer account deploys the implementation of the AmbireAccount contract that is later used by the user account to create a proxy (AccountProxy contract) over the implementation. The deployer then forces the destruction of the reference implementation using a fallback handler (Destroyer contract). The user's wallet is now inaccessible as there is no code behind the proxy.
The majority of the test is implemented in the
setUp()
function in order to properly test the destruction of the contract (in Foundry contracts are deleted when the test is finalized).Note: the snippet shows only the relevant code for the test. Full test file can be found here.
Recommendation
Remove the constructor from the AmbireAccount contract.
Assessed type
Other
The text was updated successfully, but these errors were encountered: