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

Malicious actor can steal all `L1Vault.sol` funds

Vulnerability Details

The vulnerability identified relates to the sendToL1 function in the L1BossBridge contract and its interaction with the vault.approveTo(address(this), type(uint256).max) call from the L1Vault contract. The sendToL1 function lacks proper access control, and coupled with the unrestricted approval granted to L1BossBridge by the L1Vault, it creates a significant security risk.

This issue arises because sendToL1 can execute arbitrary calls, including sensitive functions like transferOwnership() or transferFrom(), on behalf of the L1Vault. The unrestricted approval (type(uint256).max) means that any token amount can be transferred. Without specific access controls on sendToL1, a malicious actor could craft a message that misuses these capabilities to seize control of the L1Vault or to transfer all tokens from the vault, effectively draining it.

contract L1Vault is Ownable {
...
function approveTo(address target, uint256 amount) external onlyOwner {
token.approve(target, amount);
}
...
}
contract L1BossBridge is Ownable, Pausable, ReentrancyGuard {
...
constructor(IERC20 _token) Ownable(msg.sender) {
token = _token;
vault = new L1Vault(token);
// Allows the bridge to move tokens out of the vault to facilitate withdrawals
vault.approveTo(address(this), type(uint256).max);
}
...
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);
if (!signers[signer]) {
revert L1BossBridge__Unauthorized();
}
(address target, uint256 value, bytes memory data) = abi.decode(message, (address, uint256, bytes));
(bool success,) = target.call{ value: value }(data);
if (!success) {
revert L1BossBridge__CallFailed();
}
}
...
}

Impact

The impact of this vulnerability is extremely high, as it directly jeopardizes the security of the assets within the L1Vault. Malicious actors can exploit this vulnerability to gain unauthorized control or transfer out all the tokens, leading to a total loss of funds stored in the vault. Such an exploit would severely undermine the trust and integrity of the entire system.

Recommendations

To address this vulnerability, it's crucial to implement robust access control on the sendToL1 function. Specifically, it is advisable to:

  1. Restrict the types of calls and targets that can be made through sendToL1. This could involve maintaining a whitelist of allowable functions or contracts that can be interacted with.

  2. Implement role-based access control (RBAC) using mechanisms such as OpenZeppelin's AccessControl to enforce more granular permissions on who can call sendToL1.

  3. Reconsider the necessity of granting unlimited approval (type(uint256).max) from L1Vault to L1BossBridge. Instead, adopt a more conservative approval strategy, as previously recommended for mitigating the ERC20 Contract Approval vulnerability.

Updates

Lead Judging Commences

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

sendToL1(): Wrong function visibility

Support

FAQs

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