An attacker can create a custom contract with a withdraw function that invokes the StarklaneMessaging::_consumeMessageAutoWithdraw
method, enabling them to withdraw any token held by the L1 Bridge.
The C-1 finding of this audit report, identifies a critical vulnerability in the Starklane::withdrawTokens
function. When the WITHDRAW_AUTO flag in the request header is set to true, it triggers a call to the StarklaneMessaging::_consumeMessageAutoWithdraw
function, where no validation is performed on the request to confirm that a message was actually sent from L2. This oversight allows an attacker to pass a request into the withdrawTokens endpoint that didn’t originate from L2, enabling the withdrawal of any token held by the L1 Bridge.\
The protocol attempted to 'fix' the issue by commenting out the function call in Starklane::withdrawTokens
. Now, if the function is called with the WITHDRAW_AUTO flag set to true, it reverts with the NotSupportedYetError
error:
While this fix might be sufficient if StarklaneMessaging::_consumeMessageAutoWithdraw
were a private
function as it will be callable only within our contract, the problem is that it's internal
. Since internal
functions can be called from any contract that inherits from the original contract, an attacker could exploit this vulnerability. By creating a malicious contract that inherits from the target contract and includes a custom withdraw function, the attacker could invoke StarklaneMessaging::_consumeMessageAutoWithdraw
with the token ID of another user, effectively transferring ownership of the token to themselves.
To understand the vulnerability in more detail, here is a coded PoC exploiting it:
Follow these steps:
Create an AttackContract.t.sol contract in the apps/blockchain/ethereum/test folder and paste the following code inside:
Again, inside the test folder, create an Auditor.t.sol file and paste the following code:
Run in your terminal the following command:
An attacker can withdraw any token held by the L1 Bridge.
Manual review, Foundry
For the shor-term making the StarklaneMessaging::_consumeMessageAutoWithdraw
function private
or commenting it out can be a solution. However, for the long term, as suggested in C-1 of the audit report, it is recommended to consume the L2 message.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.