-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Attacker can block LayerZero channel due to variable gas cost of saving payload #697
Comments
raymondfam marked the issue as sufficient quality report |
raymondfam marked the issue as duplicate of #693 |
alex-ppg marked the issue as selected for report |
The Warden has demonstrated that even though the V2 OFT token implements a non-blocking LayerZero application, the insecure Such an action is irreversible, and I consider a severity of High to be appropriate. As feedback for the Warden, this submission would not have been selected the best if any of its duplicates properly explained the issue. I strongly advise the Warden to not cite other findings to avoid "effort" as this finding will be part of a publicly available C4 report that should properly describe the issue without having the readers go through other resources. |
alex-ppg marked the issue as satisfactory |
Hey, @alex-ppg I believe the following issue is not valid, because LZ implement a check for the payload size inisde
|
Hey @alex-ppg , what @NicolaMirchev has just mentioned is true, the LZ contracts have an internal mechanism to prevent exactly what is been reported here. Additionally, if we take a look at the report that this report is referencing, there is a unique precondition for the "issue" to even occur, such a precondition (I'm quoting from the referenced report) is: "if the project decides to change the default payload size to something smaller(or bigger) it will be dictated by the message with the biggest possible payload size."
|
I agree with @NicolaMirchev and @stalinMacias, this issue is invalid. The issue cited: code-423n4/2023-07-tapioca-findings#1220 is valid only because the attacker can pass some arbitrary length data in the form of an
require(_payloadSize <= payloadSizeLimit, "LzApp: payload size is too large"); EDIT: Nevermind, I misread the issue, |
Hi @alex-ppg, many thanks for the detailed response on every submission and the feedback on this one, that is incredibly helpful. I will keep that in mind for future submissions. @NicolaMirchev the referenced finding does take into account that the maximum payload size is 10k bytes, which is the @stalinMacias the excerpt you're mentioning is not a precondition, but simply mentioned as an aside in the referenced issue to inform the finding's remediation. The full quote is as follows:
@DadeKuma the |
@0xEVom For one second I almost believed that your report was valid, but guess what, it is totally invalid, here is why. So, you are saying that the Or in other words, you are saying that the
So, you are saying that when the You missed an important thing in the report you mentioned, in those contracts, if the external call to the final target contract fails, they indeed explicitly cause a revert, but in this protocol, if the external call fails, they refund the funds back and they never revert the tx.
@alex-ppg Please read carefully this comment to understand why this report is totally invalid. The report of the other contest is valid in the context of the other contest, but in the execution flow of this contest is impossible to deliberately force the same issue to occur on these contracts. |
My report was referenced here so I believe I can provide some additional context.
So there is no return bomb and the
By draining this gas the attacker would only drain what he has additionally paid on the sending side. The whole point of the So the basic assumptions of this report are not accurate. The only real issue is the size of the payload, which in cases when it's too big causes a huge overhead when it's being saved inside the I have explained these dynamics in the: #670. |
Thanks to everyone for contributing to the PJQA process! I will remind you that all Wardens should adhere to civilized conduct and that snarky remarks are unwelcome. We have already established that the gas limit allocation is very small to properly execute across-chain transactions and that may lead to a failure in the cross-chain message relay. This is a valid concern and can be rectified by updating how gas is configured and so on. This particular submission relates to how even with a configurable payload it may be possible to still hijack the transaction, causing blockage of the LayerZero channel. @NicolaMirchev the default payload size is indeed accounted for in the submission as it is quite high at @DadeKuma as you have correctly re-evaluated an arbitrary payload can indeed be passed in the cross-chain transaction. @stalinMacias your initial reply treats the adjustment of the default payload size as a precondition but it is not. The original submission clearly uses the Your second reply seems to misunderstand what would occur in this scenario. If the called contract would result in an OOG error, the bridge executors would have to perform refunds with the remaining What we are concerned with is whether the final I will re-evaluate the issue as it may potentially be a superset of the out-of-gas error described in #525, but will retain it as separate for now. |
First of all, apologies for the snarky remarks, will pay more attention to the wording on my comments. So, if we track the execution flow on the lzContracts, we have:
When retying a failed payload:
By taking a deeper look at the lz contracts involved in the DcntEth contract, I realized that when an execution to retry a payload is sent, it is possible to send more gas for this execution, see here.
Because of the logic of the contracts in this protocol and the fail-safe mechanism to refund funds in the DecentBridgeExecutor if the external call fails rather than reverting the whole execution, the layer zero messaging can't be blocked permanently (With that said and after I've reviewed #525, I believe this report should be a dupe of #525 instead of being assessed as a unique finding |
@alex-ppg really appreciate how much thought and consideration you're putting into judging. I reached out to @windhustler yesterday and while I would gladly take the solo high, I've come around to agreeing with him that the situation here is not quite the same as in the Tapioca case and this finding is pretty much just a needlessly complicated duplicate of #525. The main difference is that in the referenced finding, the gas was available for the entire call trace and causing a revert required the target contract to consume so much gas that the storing of the payload hit an OOG with the remaining 1/64 of the gas. However, in this case, At the same time, the endpoint passes a different amount of gas to So we have:
Since |
Hey @stalinMacias and @0xEVom, thank you for providing additional information to this submission. @stalinMacias I believe you misunderstand how LayerZero works and how an uncaught revert on the OFT would be handled. Specifically, a cross-chain transaction cannot be retried on-chain if it fails in an uncaught error; it can only be retried if it was properly stored in the failed payloads. Otherwise, it is repeated as a normal transaction until it executes (or is gracefully handled) and the channel is blocked until that occurs. @0xEVom I appreciate the re-evaluation of your own submission, but you have to keep in mind that point 2 is relatively indeterminate. The gas cost is theoretically unbound for the input argument (only limited by the Based on the above, the submission is somewhat related but not directly linked to what value the I would normally keep the submissions separate based on the above, however, given that the wardens all agree to their merging (including the main submission's original author), I will de-dupe this submission under the gas-related LayerZero flaw. This discussion is considered final as PJQA has concluded the contest; thanks to everyone who contributed their knowledge to this ruling! |
alex-ppg marked the issue as duplicate of #525 |
alex-ppg marked the issue as not selected for report |
Lines of code
https://github.com/decentxyz/decent-bridge/blob/7f90fd4489551b69c20d11eeecb17a3f564afb18/src/DecentEthRouter.sol#L197
https://github.com/decentxyz/decent-bridge/blob/7f90fd4489551b69c20d11eeecb17a3f564afb18/src/DecentEthRouter.sol#L103-L109
https://github.com/decentxyz/decent-bridge/blob/7f90fd4489551b69c20d11eeecb17a3f564afb18/src/DecentEthRouter.sol#L161
Vulnerability details
Impact
This issue is internally the same as described in code-423n4/2023-07-tapioca-findings#1220. To avoid duplication of efforts and unnecessary copy-pasting, only the differences are explained in this issue.
Proof of Concept
The entry point here is the
bridgeWithPayload()
function in theDecentEthRouter
contract, which allows the caller to pass a variable-lengthadditionalPayload
variable. This variable is then encoded as part of thepayload
variable returned by_getCallParams()
and passed as parameter toDcntEth.sendAndCall()
. This is a function thatDcntEth
inherits fromOFTV2
, which inherits it fromBaseOFTV2
. This function calls the internal_sendAndCall()
function inherited fromOFTCoreV2
, which finally calls_lzSend()
. This ties into the description of the vulnerability in the aforementioned issue.On the other end, the message will be processed in the
onOFTReceived()
function of the same contract, which is invoked in theOFTCoreV2.callOnOFTReceived()
function when receiving a message. Our payload will be extracted as thecallPayload
variable and passed on to the executor, where themsgType
is hardcoded asMT_ETH_TRANSFER_WITH_PAYLOAD
inbridgeWithPayload()
. Finally, inDecentBridgeExecutor
, we always get a call to our target address with the payload we defined (of which only its size matters), in which we can drain as much gas as needed for the attack. This completes the exploit as all intermediary steps are explained in great detail in the issue referenced above.Tools Used
Manual review
Recommended Mitigation Steps
The recommended mitigation is similar to the one in the reference issue. Alternatively or in addition to it, a maximum size for any variable-length parameters that can be passed in a LayerZero message to an arbitrary address could be implemented.
Assessed type
Other
The text was updated successfully, but these errors were encountered: