Flat Watermelon Terrier
High
Signatures
needed to execute a transaction can be reused on another chain if several conditions are satisfied
The HatsSignerGate.sol::_countValidSignatures
to check signatures
validity uses ecrecover
function that is subject to cross-chain replay attack.
function _countValidSignatures(bytes32 dataHash, bytes memory signatures, uint256 sigCount)
internal
view
returns (uint256 validSigCount)
{
// There cannot be an owner with address 0.
address currentOwner;
uint8 v;
bytes32 r;
bytes32 s;
uint256 i;
for (i; i < sigCount; ++i) {
(v, r, s) = signatureSplit(signatures, i);
if (v == 0) {
// If v is 0 then it is a contract signature
// When handling contract signatures the address of the contract is encoded into r
currentOwner = address(uint160(uint256(r)));
} else if (v == 1) {
// If v is 1 then it is an approved hash
// When handling approved hashes the address of the approver is encoded into r
currentOwner = address(uint160(uint256(r)));
} else if (v > 30) {
// If v > 30 then default va (27,28) has been adjusted for eth_sign flow
// To support eth_sign and similar we adjust v and hash the messageHash with the Ethereum message prefix before
// applying ecrecover
currentOwner = ecrecover(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", dataHash)), v - 4, r, s);
} else {
// Default is the ecrecover flow with the provided data hash
// Use ecrecover with the messageHash for EOA signatures
@> currentOwner = ecrecover(dataHash, v, r, s);
}
if (isValidSigner(currentOwner)) {
// shouldn't overflow given reasonable sigCount
unchecked {
++validSigCount;
}
}
}
}
Safe.sol, HatsSignerGate.sol
deployed on two blockchains so that:
Safe.nonce() chain A > Safe.nonce() chain B
and the signatures
have been already used in a transaction in chain A
An attacker that takes signatures through the block explorer and use them in another chain (aforementioned chain B) when the Safe.nonce()
value will be equal to the one used in chain A
The attacker could get from a block explorer the signatures used on one chain and replay them on another chain that has a lower nonce
value when it will be equal to the nonce
used in the OG transaction (first chain).
Permissions to execute a transaction coming from the Safe
contract can be bypassed replaying signatures
already used in another transaction on a different chain when the Safe.nonce()
values are the same.
No response
Use ECDSA library functions