NFTBridge
60,000 USDC
View results
Submission Details
Severity: low
Invalid

Potential Vulnerability to Replay Attacks While Storing `RequestHash`

Description:

The current implementation of request processing lacks protection against replay attacks. Replay attacks occur when the same transaction is submitted multiple times, potentially leading to unintended behavior, such as transferring tokens multiple times or executing the same action repeatedly. This vulnerability arises because there is no mechanism to track whether a particular RequestHash has already been processed, allowing malicious actors to reuse the same transaction data.

Impact:

If left unaddressed, replay attacks could result in severe consequences, including the duplication of token transfers, unauthorized actions, and overall inconsistencies in the contract's state. This could undermine the security and integrity of the entire system, potentially leading to financial losses and reduced trust in the platform.

Proof of Concept:

To mitigate replay attacks, the following proof of concept can be implemented:

  1. Store the RequestHash in Contract Storage: Add a mapping to keep track of processed RequestHash values:

mapping(bytes32 => bool) private usedRequestHashes;
  1. Mark the RequestHash as "Used": Before processing a request, check if the RequestHash has already been processed. If it has, revert the transaction. Otherwise, mark it as used:

function processRequest(bytes32 requestHash, /* other params */) external {
require(!usedRequestHashes[requestHash], "Request has already been processed");
// Mark the requestHash as used
usedRequestHashes[requestHash] = true;
// Process the request
// ... (rest of your function logic)
}
  1. Use a Nonce for Unique Transactions: Introduce a nonce that is tied to each user or transaction, ensuring uniqueness:

mapping(address => uint256) private nonces;
function computeRequestHash(
address user,
uint256 nonce,
/* other params */
) internal view returns (bytes32) {
return keccak256(abi.encodePacked(user, nonce, /* other params */));
}
function processRequest(address user, /* other params */) external {
uint256 nonce = nonces[user];
bytes32 requestHash = computeRequestHash(user, nonce, /* other params */);
require(!usedRequestHashes[requestHash], "Request has already been processed");
// Mark the requestHash as used
usedRequestHashes[requestHash] = true;
// Increment the nonce for the next transaction
nonces[user]++;
// Process the request
// ... (rest of your function logic)
}

Recommended Mitigation:

To effectively mitigate the risk of replay attacks, it is recommended to:

  • Store each RequestHash in contract storage and mark it as "used" after processing.

  • Implement a nonce system to ensure that each transaction is unique and can only be processed once.

  • Revert any transaction where the RequestHash has already been used, preventing replay attacks.

Updates

Lead Judging Commences

n0kto Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
Assigned finding tags:

invalid-replay-attack-hash-not-stored-nonce-not-used

There is no impact here: Transaction cannot be replayed because the blockchain use the nonce in the signature. Hash is computed on-chain. Using or trying to have the same hash mean you need to buy the token, and they will be sent to their origin owner. Why an attacker would buy tokens to give them back ? No real impact.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.