SCWE-055: Missing Protection against Signature Replay Attacks
Stable Version v1.0
This content is in the version-(v1.0) and still under active development, so it is subject to change any time (e.g. structure, IDs, content, URLs, etc.).
Relationships¶
- CWE-294: Authentication Bypass by Capture-replay
https://cwe.mitre.org/data/definitions/294.html
Description¶
Signature replay attacks occur when a valid signature from a previous transaction is reused in a different context, such as a different transaction or contract call. Without proper protection, an attacker can capture and replay a signature, potentially bypassing authentication checks and causing unauthorized actions or transactions.
Remediation¶
To prevent signature replay attacks, include additional checks that ensure the signature is valid for a specific transaction or context. This can be done by incorporating unique identifiers like a nonce, timestamp, or a unique transaction hash into the signature to bind it to a specific use. Always verify that the signature is only valid for the intended action.
Vulnerable Contract Example¶
contract ReplayAttackExample {
mapping(address => uint256) public nonces;
function authenticate(bytes32 message, uint8 v, bytes32 r, bytes32 s) public {
address signer = ecrecover(message, v, r, s);
require(signer == msg.sender, "Invalid signature");
// No protection against replay attacks; attacker can reuse the same signature
}
}
Fixed Contract Example¶
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
contract SecureReplayProtectionExample {
using ECDSA for bytes32;
mapping(address => uint256) public nonces;
function authenticate(bytes32 message, bytes memory signature) public {
uint256 nonce = nonces[msg.sender]++;
bytes32 messageWithContext = keccak256(abi.encodePacked(message, nonce, block.chainid));
address signer = messageWithContext.toEthSignedMessageHash().recover(signature);
require(signer == msg.sender, "Invalid signature");
}
}
chainId (prevents cross-chain replay attacks).
- Uses OpenZeppelin’s ECDSA library (avoids signature malleability risks).