sherlock-audit / 2024-09-symmio-v0-8-4-update-contest-judging

0 stars 0 forks source link

safdie - Zero address and trivial inputs could affect contract logic relying on signature validation in `LibMuonV04ClientBase.sol` #24

Open sherlock-admin3 opened 1 week ago

sherlock-admin3 commented 1 week ago

safdie

Medium

Zero address and trivial inputs could affect contract logic relying on signature validation in LibMuonV04ClientBase.sol

Summary

Zero address and trivial inputs LibMuonV04ClientBase.sol could affect contract logic relying on signature validation in.

Root Cause

In the verifySignature function, there is a check to prevent trivial or zero-value inputs, which includes zero addresses or empty parameters. However, improper handling of these checks can still lead to security vulnerabilities, especially if such inputs bypass the validation process. Let’s explore how an attacker might exploit this, and its potential impact.

The contract checks for zero inputs with this line: https://github.com/sherlock-audit/2024-09-symmio-v0-8-4-update-contest/blob/main/protocol-core/contracts/libraries/LibMuonV04ClientBase.sol#L116-L117 While this ensures that trivial values like 0x0 can't be used for some of the key inputs, this does not guarantee that malicious inputs won’t bypass checks under certain conditions (e.g., if ecrecover returns 0x0 due to invalid signatures).

Malicious users might try to trigger signature validation failures or force the ecrecover to return 0x0, which could affect contract logic relying on signature validation.

Internal pre-conditions

No response

External pre-conditions

No response

Attack Path

An attacker could try to force ecrecover to return address(0) by providing manipulated inputs. For example, setting the signature, message hash, or other key inputs to certain values might cause the verification to pass incorrectly. In PoC below, the attacker provides trivial but non-zero values for signingPubKeyX, signature, and msgHash. By manipulating the elliptic curve math internally, they might trick ecrecover into returning address(0) or passing the validation checks even though the inputs don't represent a legitimate signature.

Also, the contract doesn't properly handle cases where ecrecover returns address(0), so the attacker might reuse this to bypass signature verification. This could potentially allow the attacker to replay previously valid transactions with zero inputs, resulting in replay attacks or unauthorized actions. Since the check relies on the fact that nonceTimesGeneratorAddress != address(0), an attacker could exploit cases where the address becomes zero, such as through invalid ecrecover behavior.

Impact

  1. If an attacker can bypass the zero-input checks by manipulating elliptic curve math or forcing ecrecover to return address(0), they might be able to forge valid signatures or reuse signatures across transactions. This could lead to unauthorized actions being executed in the system.
  2. If trivial or zero values (such as a zero address or zero signature) are accepted in certain edge cases, attackers could replay old transactions or unauthorized signatures, resulting in a loss of funds or control over certain functionalities.
  3. The attacker could potentially exploit the system by sending trivial or malformed signatures repeatedly, causing the system to spend gas on failed signature verifications. This could create a denial of service (DoS) attack, making it harder for legitimate users to interact with the contract.

PoC

// Malicious actor attempts to force a valid but trivial signature
uint256 maliciousPubKeyX = 1; // Small, but non-zero value
uint8 pubKeyYParity = 0; // Assuming even Y coordinate
uint256 maliciousSignature = 1; // Small, trivial signature
uint256 maliciousMsgHash = 1; // Small, but non-zero message hash
address maliciousNonceAddress = address(0); // Invalid nonce address

bool success = LibMuonV04ClientBase.verifySignature(
   maliciousPubKeyX,
   pubKeyYParity,
   maliciousSignature,
   maliciousMsgHash,
   maliciousNonceAddress
);

require(success, "Exploit failed");

Mitigation

  1. Ensure that all elliptic curve values (like signingPubKeyX, signature, msgHash) are checked thoroughly. Use stricter checks to ensure these values are within valid ranges and avoid passing trivial values like 1, small integers, or zero-like values.
    require(nonceTimesGeneratorAddress != address(0), "Invalid nonce address");
    require(signingPubKeyX > 1e10, "Public key too small"); // Example: Large enough to avoid trivial values
    require(signature > 1e10, "Signature too small"); // Similar check
    require(msgHash > 1e10, "Message hash too small"); // Avoid trivial hashes
  2. Ensure that the output of ecrecover is always validated. For instance, check that the recovered address is non-zero and matches the expected output. If ecrecover returns address(0), the function should revert or return false.