Skip to content

Possible replay attack #88

Open
Open
@hats-bug-reporter

Description

Github username: @obingo31
Twitter username: --
Submission hash (on-chain): 0xe89620ff010e672c753b01833e787f6db5c8efacf602e86b726a06174f704afb
Severity: high

Description:
Description
The _validateSignature function in the AtomWallet contract is responsible for validating the signatures of user operations. However, there is a potential replay attack vulnerability due to the lack of nonce handling or unique operation identifiers within the signature verification process. This vulnerability allows an attacker to reuse a valid signature for multiple transactions, bypassing the intended authorization checks. The vulnerability also allows an attacker to potentially replay a valid user operation multiple times, leading to unintended consequences such as double spending or manipulating internal accounting.

Attack Scenario
The legitimate owner of the wallet signs a UserOperation with a specific userOpHash and submits it for execution.
The transaction is successfully executed, and the signature is deemed valid.
Replay Attack:
An attacker obtains the userOpHash and the corresponding valid signature from the previous transaction.
The attacker resubmits the same UserOperation with the identical userOpHash and signature.
The _validateSignature function verifies the signature as valid because the userOpHash is the same and was previously signed by the legitimate owner.
The transaction is executed again, allowing the attacker to perform unauthorized actions without the owner's consent.

Attachments

  1. Proof of Concept (PoC) File
    Revised _validateSignature function
function _validateSignature(UserOperation calldata userOp, bytes32 userOpHash)
    internal
    virtual
    override
    returns (uint256 validationData)
{
  bytes32 hash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", userOpHash, userOp.nonce));

  (address recovered,,) = ECDSA.tryRecover(hash, userOp.signature);

  if (recovered != owner() || userOp.nonce <= usedNonces[recovered]) {
    return SIG_VALIDATION_FAILED;
  }

  usedNonces[recovered] = userOp.nonce + 1; // Update used nonces after successful validation
  return 0;
}

// fix
mapping(address => uint256) public usedNonces;
  1. Added a new field 'nonce' to UserOperation struct (not shown here)

  2. Included 'nonce' in the data hashed before signature verification

  3. Added check for 'nonce' after signature verification

    • Checks if the 'nonce' is greater than the last used nonce for the signer address
    • Maintains a mapping 'usedNonces' to track used nonces
  4. Updates 'usedNonces' after successful validation to prevent replaying the same operation

  5. Revised Code File (Optional)
    We recommend implementing the suggested fix or a similar approach to mitigate replay attacks in the _validateSignature function. This will significantly enhance the security of the smart contract and prevent attackers from exploiting this vulnerability.

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingduplicateThis issue or pull request already exists

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions