NFTBridge
60,000 USDC
View results
Submission Details
Severity: low
Invalid

Incorrect Implementation of the `onlyInit` Modifier Leads to Loss of Access Control in the Bridge Contract

Summary

The initialize function in the bridge contract can be called each time the contract undergoes an upgrade. This flaw allows an attacker to invoke the initialize function immediately after the bridge contract is upgraded, thereby gaining ownership and control over the contract.

Vulnerability Details

The bridge smart contract inherits from the UUPSProxied contract, which includes the onlyInit modifier. This modifier is intended to ensure that the initialize function is only called once per contract lifecycle.

Below is the code snippet demonstrating how the onlyInit modifier is implemented:

modifier onlyInit() {
address impl = _getImplementation();
require(!_initializedImpls[impl], "Already init");
_initializedImpls[impl] = true;
_;
}

Additionally, here is the code for the initialize function:

function initialize(
bytes calldata data
)
public
onlyInit
{
(
address owner,
IStarknetMessaging starknetCoreAddress,
uint256 starklaneL2Address,
uint256 starklaneL2Selector
) = abi.decode(
data,
(address, IStarknetMessaging, uint256, uint256)
);
_enabled = false;
_starknetCoreAddress = starknetCoreAddress;
_transferOwnership(owner);
setStarklaneL2Address(starklaneL2Address);
setStarklaneL2Selector(starklaneL2Selector);
}

The initialize function is designed to set up the initial state of the bridge contract and should only be executed once during the contract’s lifetime. However, the current implementation of the onlyInit modifier permits the initialize function to be called again whenever the implementation address changes.

This vulnerability enables an attacker to execute the initialize function right after the bridge contract is upgraded by the admin using the upgradeTo or upgradeToAndCall functions. As a result, the attacker can gain ownership of the bridge contract.

Impact

If exploited, this vulnerability allows an attacker to gain ownership and full control over the bridge contract, which is a highly critical security risk.

Tools Used

Manual Review

Recommendations

The onlyInit modifier should be revised to ensure that the initialize function can only be called once throughout the entire lifespan of the smart contract.

Updates

Lead Judging Commences

n0kto Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

invalid-bridge-initialize-frontrun

If frontrun at the first deployment, protocol will deploy again, no real impact: informational. Moreover it is already deployed and initialize on mainnet. For the upgrades, `initialize` can/will change for the next update since the owner is already set. A lot of protocol make that change. That’s why I consider it like a future feature and it is out of scope.

Appeal created

bladesec Submitter
about 1 year ago
0xgenaudits Judge
about 1 year ago
n0kto Lead Judge
about 1 year ago
n0kto Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

invalid-bridge-initialize-frontrun

If frontrun at the first deployment, protocol will deploy again, no real impact: informational. Moreover it is already deployed and initialize on mainnet. For the upgrades, `initialize` can/will change for the next update since the owner is already set. A lot of protocol make that change. That’s why I consider it like a future feature and it is out of scope.

Support

FAQs

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