Closed c4-submissions closed 10 months ago
raymondfam marked the issue as low quality report
raymondfam marked the issue as duplicate of #143
raymondfam marked the issue as duplicate of #398
alex-ppg marked the issue as not a duplicate
alex-ppg marked the issue as duplicate of #21
alex-ppg marked the issue as unsatisfactory: Invalid
Hi ser, thanks for the great work judging this contest. I would like to add here that this issue isn't a duplicate of #21 This issue describes how based on the protocol implementation the goal of allowing users to create deterministic wallets across different chains is oppressed. I have described how the issue spans from 1. the increment of the owner's safe count. 2. The use of contract version. While #21 and its likes described a possible DOS, that isn't what this report describes. Thank you.
To generate deterministic addresses for a given set of owners, the order of owner addresses and threshold should be same @param _owners list of owners addresses
Hey @Tendency001, thanks for following up! While the submission might not by a direct duplicate of the other issues, it relies on the same underlying mechanism.
This particular scenario relies on an incorrect assumption. In the described case, the “failures” would occur because a wallet is already present at the addresses the SafeDeployer
attempted to deploy it.
As such, chain A would actually have 3 Console Accounts while chain B would have 1 Console Account. Regardless of this, I list a reason why these are non issues in Weakness 2.
If a new deployer is created for a different version of Brahma Console Accounts, it is wise to use a different address generation system as different versions of Brahma would have different features, comply to different interfaces, etc.
Even if the original SafeDeployer
is not available for some reason, users can directly interact with the Gnosis Safe deployer to deploy the addresses they want as the address generation ultimately is done by Gnosis and not by Brahma.
Under all cases, no loss of funds will be caused. It is advisable for Brahma to include a VERSION
in their system to ensure address generations are distinct between Brahma versions.
Please let me know if the above address your concerns and if you require any further clarifications.
Thanks for the response ser, this will do
Lines of code
https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/SafeDeployer.sol#L56-L72 https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/SafeDeployer.sol#L219-L245 https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/SafeDeployer.sol#L253-L255
Vulnerability details
Impact
In
Brahma
, Users can interact withSafeDeployer::deployConsoleAccount
to deploy console accounts/wallets. To deploy the wallet to the same address across all supported chains, the user needs to interact with thedeployConsoleAccount
function on all chains providing a list of owners in the same order and using the same unique salt value.The function
_genNonce
plays an important role in deploying these deterministic safes, as given an owner's hash and salt, this function returns thesaltNonce
which is used in generating the salt used for deploying the safe.I have observed two possible issues with the current method of generating nonces in the
_genNonce
function. These issues can obstruct the user's ability to deploy wallets to deterministic addresses on different chains, even while using the same set of owners and salt value.Weakness 1: Reliance on
ownerSafeCount
for Nonce GenerationThe problem is that the value of
ownerSafeCount
is incremented each time the_genNonce
function is called within the_createSafe
function, this can create a disparity between the owner safe count used in generating a nonce in chain A from the value used in chain B. How_createSafe
function works is, assuming the first call with nonce1 toGnosisSafe::createProxyWithNonce
function fails,genNonce
function is called to generate a new nonce, and thencreateProxyWithNonce
function call is retried again. On retry(i.e.genNonce
call), theownerSafeCount
value is incremented. Now, consider a scenario where the owner's safe count is initially zero (0). If the user's first and second attempts at creating a wallet fail but the third attempt succeeds, the nonce is generated based on an owner safe count of two (2). Now, assuming the same user tries to deploy a wallet with the same identical parameters on a different chain. On this new chain, the wallet creation occurs whenownerSafeCount
equals zero (0). Consequently, a different nonce is employed in this deployment. As a result, the wallet is deployed to a distinct address.Weakness 2: Reliance on VERSION for Nonce Generation
The second weakness arises from the reliance on the version of the
SafeDeployer
contract (VERSION
) for nonce generation. This reliance complicates the ability to deploy a safe to a deterministic address on different chains. To illustrate, let's consider a scenario:Suppose a user deploys a safe or wallet on the Ethereum blockchain at x time when the
SafeDeployer
contract's version is, for example, 'One (1)'. Later on, at a different point in time, the same group of safe owners intends to deploy their safe on other chains. However, at this latter time, there is a newSafeDeployer
contract version, let's say two(2), and the previous version is discarded: Here is a message from a sponsor:Under these circumstances, despite all other conditions remaining the same, a different nonce will be generated. Since the
GnosisSafe::createProxyWithNonce
function relies on both the generated nonce and the initializer to calculate a salt value for deployment. The safe will be deployed to a distinct deterministic address on the other chain, leading to non-deterministic deployments.Proof of Concept
https://github.com/code-423n4/2023-10-brahma/blob/dd0b41031b199a0aa214e50758943712f9f574a0/contracts/src/core/SafeDeployer.sol#L219
https://vscode.blockscan.com/gnosis/0x8b4404de0caece4b966a9959f134f0efda636156
Tools Used
Manual Review
Recommended Mitigation Steps
I will recommend you allow the user to retry with a different salt if call to IGnosisProxyFactory::createProxyWithNonce fails. I will also recommend changing
_genNonce
to:Assessed type
en/de-code