Attacker can block LayerZero channel on the root chain due to execution outside of try/catch #721
Labels
2 (Med Risk)
Assets not at direct risk, but function/availability of the protocol could be impacted or leak value
bug
Something isn't working
downgraded by judge
Judge downgraded the risk level of this issue
duplicate-399
satisfactory
satisfies C4 submission criteria; eligible for awards
sufficient quality report
This report is of sufficient quality
Lines of code
https://github.com/code-423n4/2023-09-maia/blob/main/src/RootBridgeAgent.sol#L430
Vulnerability details
Impact
This is an issue that results in pathway blocking on the RootChain and disabling any cross-chain communication between Branches and RootChain.
The consequence of this is that anyone can with a low cost and high frequency keep on blocking the pathway between any two chains, making the whole system unusable and locking user funds.
Proof of Concept
The root core of this issue is that
lzReceive
has additional logic outside thetry/catch
block.The objective of the attacker is to cause an "out of gas" error inside the
lzReceiveNonBlocking
.As
lzReceiveNonBlocking
is an external call, according toEIP-150
63/64 amount of gas is forwarded to this external call and the rest is left for the rest of the execution.The 1/64 gas leftover needs to be less than the gas needed for executing the logic inside the
if(!success) block
.There are several ways of achieving "out of gas" error inside the
lzReceiveNonBlocking
:RootBridgeAgent
deployed by Maia DAO but with a smaller amount of gas.As a consequence, the transaction will revert somewhere during the
lzReceiveNonBlocking
function execution.I've set up a POC that demonstrates the second scenario. You can place the POC inside the
RootTest.t.sol
and run it withforge test --mt testBlockingPathwayOnRootChain -vvvv --watch
to see the stack trace and the revert due to "out of gas error".callOutAndBridgeMultiple
function.lzReceive
function is invoked with the specified gasLimit.lzReceiveNonBlocking
and the rest is left for the rest of the execution.if(!success) block
and it reverts again.lzEndpoint catch block
resulting inStoredPayload
and blocking the pathway.Tools Used
Recommended Mitigation Steps
You should estimate the maximum amount of gas needed to execute the logic inside the [
if(!success) block
].The remaining gas after the first external call should always be above that value. Also, this assumes that on the sending side this minimum gas is higher or equal to
GAS_ALLOCATION
.Assessed type
DoS
The text was updated successfully, but these errors were encountered: