Beginner FriendlyFoundryBridge
100 EXP
View results
Submission Details
Severity: high
Valid

Signature Replay Vulnerability

Vulnerability Details

L1BossBridge.sol present a vulnerability related to signature replay. This issue arises from the way signatures are handled in the withdrawTokensToL1 and sendToL1 functions. These functions require a signature for execution, intended to provide security and verify the legitimacy of transactions. However, the current implementation does not include a mechanism to prevent the reuse of a signature.

This means that once a valid signature is generated and used for a transaction, it could potentially be replayed by a malicious actor to authorize subsequent transactions without the consent of the original signer.

function withdrawTokensToL1(address to, uint256 amount, uint8 v, bytes32 r, bytes32 s) external {
...
sendToL1(
v, r, s,
abi.encode(
address(token),
0, // value
abi.encodeCall(IERC20.transferFrom, (address(vault), to, amount))
)
);
}
function sendToL1(uint8 v, bytes32 r, bytes32 s, bytes memory message) public nonReentrant whenNotPaused {
address signer = ECDSA.recover(MessageHashUtils.toEthSignedMessageHash(keccak256(message)), v, r, s);
...
}

Impact

The impact of this vulnerability is significant. If an attacker obtains a signature, they can replay it to initiate unauthorized transactions. This could lead to unauthorized token transfers or other malicious activities, compromising the security of the funds and the integrity of the contract operations. Such vulnerabilities are critical in the context of financial applications where security and trust are paramount.

Recommendations

To address this vulnerability, it is recommended to implement a nonce-based mechanism or a signature tracking system. Each signature should be linked to a unique identifier (nonce) that is checked and updated with each transaction. This approach ensures that each signature can only be used once, preventing any possibility of replay.

A potential implementation could involve adding a nonce for each user and requiring that each signature include the current nonce value. The nonce should be incremented after each successful transaction, rendering the signature unusable for future transactions.

mapping(address => uint256) private nonces;
function withdrawTokensToL1(address to, uint256 amount, uint8 v, bytes32 r, bytes32 s, uint256 nonce) external {
require(nonce == nonces[to], "Invalid nonce");
nonces[to]++;
...
}
function sendToL1(uint8 v, bytes32 r, bytes32 s, bytes memory message, uint256 nonce) public nonReentrant whenNotPaused {
...
}

This revision adds a nonce check to the withdrawal process, ensuring each signature is bound to a specific transaction, thereby mitigating the risk of signature replay attacks.

Updates

Lead Judging Commences

0xnevi Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

withdrawTokensToL1()/sendToL1(): signature replay

Support

FAQs

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