The verifySig function of Gravity calls the Solidity ecrecover function directly to verify the given signatures. However, the ecrecover EVM opcode allows malleable (non-unique) signatures and thus is susceptible to replay attacks.
Although a replay attack seems not possible here since the nonce is increased each time, ensuring the signatures are not malleable is considered a best practice (and so is checking _signer != address(0), where address(0) means an invalid signature).
Lines of code
https://github.com/code-423n4/2022-05-cudos/blob/main/solidity/contracts/Gravity.sol#L185
Vulnerability details
Impact
The verifySig function of Gravity calls the Solidity ecrecover function directly to verify the given signatures. However, the ecrecover EVM opcode allows malleable (non-unique) signatures and thus is susceptible to replay attacks.
Although a replay attack seems not possible here since the nonce is increased each time, ensuring the signatures are not malleable is considered a best practice (and so is checking _signer != address(0), where address(0) means an invalid signature).
Proof of Concept
https://swcregistry.io/docs/SWC-117
https://swcregistry.io/docs/SWC-121
Tools Used
Code Review
Recommended Mitigation Steps
Use the recover function from OpenZeppelin's ECDSA library for signature verification.