You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository has been archived by the owner on Jun 11, 2023. It is now read-only.
roguereddwarf - HatsSignerGateBase: signers can add / remove / swap signers which bypasses the HSG logic and can lead to multiple bad outcomes including DOS and increased control over Safe
#19
Closed
sherlock-admin opened this issue
Mar 9, 2023
· 0 comments
sherlock-admin opened this issue
Mar 9, 2023
· 0 comments
Labels
DuplicateA valid issue that is a duplicate of an issue with `Has Duplicates` labelHighA valid High severity issueRewardA payout will be made for this issue
HatsSignerGateBase: signers can add / remove / swap signers which bypasses the HSG logic and can lead to multiple bad outcomes including DOS and increased control over Safe
Summary
This report deals with a similar issue as the TRST-M-6 Signers can backdoor the safe to execute any transaction in the future without consensus issue from the previous audit.
The previous issue dealt with the fact that signers can execute transactions that change the modules that are registered with the Safe.
This report is similar in the sense that signers can execute actions on the Safe that are unsafe and can break the assumptions made by the HSG logic.
Specifically, signers can execute the OwnerManager.addOwnerWithThreshold, OwnerManager.removeOwner and OwnerManager.swapOwner functions from the OwnerManager contract that the Safe inherits from.
The changes to the owners will not be detected in the HatsSignerGateBase.checkAfterExecution function which is executed after the transaction by the signers.
The checkAfterExecution function's purpose is explicitly to check that the signers did not perform any dangerous actions. However it lacks checks that the owners have not been messed with which as I will explain is such a "dangerous action".
Vulnerability Detail
The dangerous functions that the signers can execute on the Safe are the following:
function removeOwner(addressprevOwner, addressowner, uint256_threshold) public authorized {
// Only allow to remove an owner, if threshold can still be reached.require(ownerCount -1>= _threshold, "GS201");
// Validate owner address and check that it corresponds to owner index.require(owner !=address(0) && owner != SENTINEL_OWNERS, "GS203");
require(owners[prevOwner] == owner, "GS205");
owners[prevOwner] = owners[owner];
owners[owner] =address(0);
ownerCount--;
emitRemovedOwner(owner);
// Change threshold if threshold was changed.if (threshold != _threshold) changeThreshold(_threshold);
}
function swapOwner(addressprevOwner, addressoldOwner, addressnewOwner) public authorized {
// Owner address cannot be null, the sentinel or the Safe itself.require(newOwner !=address(0) && newOwner != SENTINEL_OWNERS && newOwner !=address(this), "GS203");
// No duplicate owners allowed.require(owners[newOwner] ==address(0), "GS204");
// Validate oldOwner address and check that it corresponds to owner index.require(oldOwner !=address(0) && oldOwner != SENTINEL_OWNERS, "GS203");
require(owners[prevOwner] == oldOwner, "GS205");
owners[newOwner] = owners[oldOwner];
owners[prevOwner] = newOwner;
owners[oldOwner] =address(0);
emitRemovedOwner(oldOwner);
emitAddedOwner(newOwner);
}
So let's look at a DOS scenario:
Assume the are 5 hats with the signersHatId. I.e. 5 hats that can potentially be signers.
Only 3 signers are allowed to be registered at a max. I.e. maxSigners=3
The signers can now call OwnerManager.addOwnerWithThreshold to add signers beyond maxSigners
This leads to a DOS in HatsSignerGateBase.reconcileSignerCount in the following lines: Link
function reconcileSignerCount() public {
address[] memory owners = safe.getOwners();
uint256 validSignerCount =_countValidSigners(owners);
if (validSignerCount > maxSigners) {
revertMaxSignersReached();
}
There are more valid signers than maxSigners so the revert will be reached.
Owners should only be added by the HatsSignerGate not by the signers themselves. The HatsSignerGate.claimSigner and MultiHatsSignerGate.claimSigner function ensure that maxSigners is not exceeded.
Let's look at another scenario how a bad signer can make use of this issue:
Assume the are 5 hats with the signersHatId. I.e. 5 hats that can potentially be signers.
Only 3 signers are allowed to be registered at a max. I.e. maxSigners=3
One of the 3 signers is more conservative in the transactions he signs. The other 2 signers want to replace him.
So say the threshold is 2
Now the other 2 signers can call OwnerManager.swapOwner and swap the third signer with another signer that suits their agenda.
Now even when the threshold increases to 3 the two signers can get through with their agenda.
So basically there starts a "race" among the signers to swap each other.
This should not be possible. Swaps should only be executed by the HatsSignerGateBase contract in case a signer becomes invalid Link.
Impact
I have shown in this report how it can lead to multiple bad outcomes when signers can influence the signers (owners) registered in the Safe. Managing signers should be solely the job of the HatsSignerGate, not of the signers.
The scenarios I showed are DOS and signers being able to increase their control over the Safe.
Sign up for freeto subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Labels
DuplicateA valid issue that is a duplicate of an issue with `Has Duplicates` labelHighA valid High severity issueRewardA payout will be made for this issue
roguereddwarf
medium
HatsSignerGateBase: signers can add / remove / swap signers which bypasses the HSG logic and can lead to multiple bad outcomes including DOS and increased control over Safe
Summary
This report deals with a similar issue as the
TRST-M-6 Signers can backdoor the safe to execute any transaction in the future without consensus
issue from the previous audit.The previous issue dealt with the fact that signers can execute transactions that change the modules that are registered with the Safe.
This report is similar in the sense that signers can execute actions on the Safe that are unsafe and can break the assumptions made by the HSG logic.
Specifically, signers can execute the
OwnerManager.addOwnerWithThreshold
,OwnerManager.removeOwner
andOwnerManager.swapOwner
functions from the OwnerManager contract that the Safe inherits from.The changes to the owners will not be detected in the HatsSignerGateBase.checkAfterExecution function which is executed after the transaction by the signers.
The
checkAfterExecution
function's purpose is explicitly to check that the signers did not perform any dangerous actions. However it lacks checks that the owners have not been messed with which as I will explain is such a "dangerous action".Vulnerability Detail
The dangerous functions that the signers can execute on the Safe are the following:
OwnerManager.addOwnerWithThreshold
OwnerManager.removeOwner
OwnerManager.swapOwner
So let's look at a DOS scenario:
signersHatId
. I.e. 5 hats that can potentially be signers.maxSigners=3
OwnerManager.addOwnerWithThreshold
to add signers beyondmaxSigners
HatsSignerGateBase.reconcileSignerCount
in the following lines:Link
There are more valid signers than
maxSigners
so the revert will be reached.Owners should only be added by the HatsSignerGate not by the signers themselves. The
HatsSignerGate.claimSigner
andMultiHatsSignerGate.claimSigner
function ensure thatmaxSigners
is not exceeded.Let's look at another scenario how a bad signer can make use of this issue:
signersHatId
. I.e. 5 hats that can potentially be signers.maxSigners=3
threshold
is 2OwnerManager.swapOwner
and swap the third signer with another signer that suits their agenda.So basically there starts a "race" among the signers to swap each other.
This should not be possible. Swaps should only be executed by the
HatsSignerGateBase
contract in case a signer becomes invalid Link.Impact
I have shown in this report how it can lead to multiple bad outcomes when signers can influence the signers (owners) registered in the Safe. Managing signers should be solely the job of the HatsSignerGate, not of the signers.
The scenarios I showed are DOS and signers being able to increase their control over the Safe.
Code Snippet
https://github.com/Hats-Protocol/hats-zodiac/blob/9455cc0957762f5dbbd8e62063d970199109b977/src/HatsSignerGateBase.sol#L505-L529
https://github.com/safe-global/safe-contracts/blob/131f0d25135c1b98c185c940ae37fb0275ac4062/contracts/base/OwnerManager.sol#L58-L69
https://github.com/safe-global/safe-contracts/blob/131f0d25135c1b98c185c940ae37fb0275ac4062/contracts/base/OwnerManager.sol#L78-L90
https://github.com/safe-global/safe-contracts/blob/131f0d25135c1b98c185c940ae37fb0275ac4062/contracts/base/OwnerManager.sol#L99-L112
Tool used
Manual Review
Recommendation
The
HatsSignerGateBase.checkAfterExecution
function should check that the owners of the Safe are the same as before the execution.Just like it checks that the registered modules are the same.
Duplicate of #48
The text was updated successfully, but these errors were encountered: