Closed c4-submissions closed 10 months ago
raymondfam marked the issue as sufficient quality report
raymondfam marked the issue as duplicate of #62
raymondfam marked the issue as duplicate of #368
alex-ppg marked the issue as not a duplicate
alex-ppg marked the issue as duplicate of #313
alex-ppg marked the issue as unsatisfactory: Invalid
Lines of code
https://github.com/code-423n4/2023-10-brahma/blob/main/contracts/src/core/registries/PolicyRegistry.sol#L35-L59
Vulnerability details
Summary
Whenever a Gnosis safe is interacted with in a way that it does not know or have a specific implementation for it then passes execution to a specific fallback handler. For Console Accounts that have a valid policy hash and sub-accounts that handler is set as
ConsoleFallbackHandler
and is specifically used to:Console Accounts can also be created without a valid policy hash. In that case, the fallback handler that is used is the default Gnosis safe one.
The console system allows for a policy to be updated (or added) after creation via
PolicyRegistry::updatePolicy
. However, when a console account that was initially created without a policy is added a policy, the default fallback handler is not changed, skipping validation completely. This can happen maliciously or unintentional but the effect is the same, that policy validation is skipped.Vulnerability Details
When an account is deployed via
SafeDeployer::deployConsoleAccount
, execution flows toSafeDeployer::_setupConsoleAccount
where a fallback is set as argument for theIGnosisSafe.setup
call that will setup the Gnosis safe account:https://github.com/code-423n4/2023-10-brahma/blob/main/contracts/src/core/SafeDeployer.sol#L110-L160
where
AddressProviderService._getAuthorizedAddress(_GNOSIS_FALLBACK_HANDLER_HASH)
points to a deployment ofConsoleFallbackHandler
andAddressProviderService._getAuthorizedAddress(_GNOSIS_FALLBACK_HANDLER_HASH)
, the else branch without a valid policy, points to a standard compatibility fallback that is already deployed on all relevant blockchains. This standard fallback, evidently, does not have console policy validation logic.In order to updated/add a policy to an existing console, the
PolicyRegistry::updatePolicy
function is to be used:The update function:
policyCommit != bytes32(0)
)The function however, does not check if the console account had a zero policy then it's fallback handler should be changed to the
ConsoleFallbackHandler
.POC
Add the following test to
contracts\test\branch-trees\PolicyValidator\validate-policy-signature-safe-tx\ValidatePolicySignatureSafeTx.t.sol
and run it via:forge test --fork-url "https://eth-mainnet.g.alchemy.com/v2/<ALCHEMY_API_KEY>" -vvv --ffi --match-test testValidateSafe_InvalidValiditySigIsWronglyAccepted
As an observation, the issue was not spotted in the tests because they didn't follow the execution flow, instead presumed execution would reach
PolicyValidator
and all were tested as so.Impact
Policy added to a console account that was initially created without one is never validated due to fallback never being also changed from standard gnosis to
ConsoleFallbackHandler
. The entire policy system is bypassed. This can be done intentionally, with malicious intent, or unintentionally but with the same permission check bypass.Tools Used
Manual review.
Recommendations
Since a console account has either a 0 policy or, if one was provided at deployment, it must be valid, my suggestion would be to rename the current
ConsoleFallbackHandler
toConsoleSubAccountFallbackHandler
, used it only for sub-accounts and create a new one, that is similar to the initial (it may even inherit from it), name itConsoleAccountFallbackHandler
and in theisValidSignature(bytes,bytes)
method only check the validity of the hash if it exists.An example implementation:
Assessed type
Error