Malicious caller of processMessage()
can pocket the fee while forcing excessivelySafeCall()
to fail
#97
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
edited-by-warden
M-14
primary issue
Highest quality submission among a set of duplicates
🤖_69_group
AI based duplicate group recommendation
satisfactory
satisfies C4 submission criteria; eligible for awards
selected for report
This submission will be included/highlighted in the audit report
sponsor confirmed
Sponsor agrees this is a problem and intends to fix it (OK to use w/ "disagree with severity")
sufficient quality report
This report is of sufficient quality
Lines of code
https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/bridge/Bridge.sol#L280-L298
Vulnerability details
Summary
The logic inside function
processMessage()
provides a reward to the msg.sender if they are not therefundTo
address. However this reward or_message.fee
is awarded even if the_invokeMessageCall()
on L282 fails and the message goes into aRETRIABLE
state. In the retriable state, it has to be called by someone again and the currentmsg.sender
has no obligation to be the one to call it.This logic can be gamed by a malicious user using the 63/64th rule specified in EIP-150.
Description
The
_invokeMessageCall()
on L282 internally callsexcessivelySafeCall()
on L497. WhenexcessivelySafeCall()
makes an external call, only 63/64th of the gas is used by it. Thus the following scenario can happen:Malicious user notices that L285-L307 uses approx 165_000 gas.
He also notices that L226-L280 uses approx 94_000 gas.
He calculates that he must provide approximately a minimum of
94000 + (64 * 165000) = 10_654_000
gas so that the function execution does not revert anywhere.Meanwhile, a message owner has message which has a
_message.gasLimit
of 11_000_000. This is so because thereceive()
function of the contract receiving ether is expected to consume gas in this range due to its internal calls & transactions. The owner expects at least 10_800_000 of gas would be used up and hence has provided some extra buffer.Note that any message that has a processing requirement of greater than
63 * 165000 = 10_395_000
gas can now become a target of the malicious user.Malicious user now calls
processMessage()
with a specific gas figure. Let's use an example figure of{gas: 10_897_060}
. This means only63/64 * (10897060 - 94000) = 10_634_262
is forwarded toexcessivelySafeCall()
and1/64 * (10897060 - 94000) = 168_797
will be kept back which is enough for executing the remaining lines of code L285-L307. Note that since(10897060 - 94000) = 10_803_060
which is less than the message owner's provided_message.gasLimit
of11_000_000
, what actually gets considered is only10_803_060
.The external call reverts inside
receive()
due to out of gas error (since 10_634_262 < 10_800_000) and hence_success
is set tofalse
on L44.The remaining L285-L307 are executed and the malicious user receives his reward.
The message goes into
RETRIABLE
state now and someone will need to callretryMessage()
later on.A different bug report titled "No incentive for message non-owners to retryMessage()" has also been raised which highlights the incentivization scheme of
retryMessage()
.Impact
Protocol can be gamed by a user to gain rewards while additionaly saving money by providing the least possible gas.
There is no incentive for any external user now to ever provide more than
{gas: 10_897_060}
(approx figure).Proof of Concept
Apply the following patch to add the test inside
protocol/test/bridge/Bridge.t.sol
and run viaforge test -vv --mt test_t0x1c_gasManipulation
to see it pass:Tools Used
Foundry
Recommended Mitigation Steps
Reward the
msg.sender
(provided it's a non-refundTo address) with_message.fee
only if_invokeMessageCall()
returnstrue
. Additionally, it is advisable to release this withheld reward after a successfulretryMessage()
to that function's caller.Assessed type
Other
The text was updated successfully, but these errors were encountered: