BaseTOFTReceiver::_toeComposeReceiver some compose calls are not authenticated
Summary
In layerzero v2, the concept of compose message has been introduced, enabling users to break the execution of complex xChain transactions in multiple steps.
Compose message is the second call which can be executed after lzReceive has been called to acknowledge reception of the main message on target chain.
The variable _srcChainSender allows for checking the cross-chain initiator of the compose message. There is an issue with Tapioca's handling of some type of calls, which disregard _srcChainSender. These calls end up unauthenticated, and malicious users can exploit hanging approvals or cross-chain permits to execute actions on a user behalf without authorization.
Alice uses sendPacket on a TOFT to execute a series of cross-chain actions:
1/ send TOFT to chain B (main message)
2/ wrap TOFT in yieldBox (compose message 1 action 1)
2/ permit TOFT to market M (compose message 1 action 2)
3/ buyCollateral (compose message 1 action 3)
Bob sees the action initiated on the source chain, and does the following:
4/ extracts the signature from compose message 1 action 2 (signature based permit), and calls permit directly on behalf of Alice
5/ then uses a compose call of his own, calling on the market where the permit was used, and uses the hanging approval to initiate another action on behalf of alice
Impact
Malicious users can conduct some undesired actions on the accounts of other users because some compose messages are unpermissioned, and cross chain approvals can be front-run.
Code Snippet
Tool used
Manual Review
Recommendation
check that _srcChainSender equals composeMessage.user for those types of compose messages (e.g authenticate the actions in the compose receiver).
cergyk
high
BaseTOFTReceiver::_toeComposeReceiver some compose calls are not authenticated
Summary
In layerzero v2, the concept of compose message has been introduced, enabling users to break the execution of complex xChain transactions in multiple steps.
Compose message is the second call which can be executed after lzReceive has been called to acknowledge reception of the main message on target chain.
The variable
_srcChainSender
allows for checking the cross-chain initiator of the compose message. There is an issue with Tapioca's handling of some type of calls, which disregard_srcChainSender
. These calls end up unauthenticated, and malicious users can exploit hanging approvals or cross-chain permits to execute actions on a user behalf without authorization.Vulnerability Detail
See the following cross-chain compose types: https://github.com/sherlock-audit/2024-02-tapioca/blob/main/TapiocaZ/contracts/tOFT/modules/BaseTOFTReceiver.sol#L68-L78
https://github.com/sherlock-audit/2024-02-tapioca/blob/main/TapiocaZ/contracts/tOFT/modules/BaseTOFTReceiver.sol#L95-L101
Which do not use the
_srcChainSender
valueScenario
Alice uses sendPacket on a TOFT to execute a series of cross-chain actions:
1/ send TOFT to chain B (main message) 2/ wrap TOFT in yieldBox (compose message 1 action 1) 2/ permit TOFT to market M (compose message 1 action 2) 3/ buyCollateral (compose message 1 action 3)
Bob sees the action initiated on the source chain, and does the following:
4/ extracts the signature from
compose message 1 action 2
(signature based permit), and calls permit directly on behalf of Alice 5/ then uses a compose call of his own, calling on the market where the permit was used, and uses the hanging approval to initiate another action on behalf of aliceImpact
Malicious users can conduct some undesired actions on the accounts of other users because some compose messages are unpermissioned, and cross chain approvals can be front-run.
Code Snippet
Tool used
Manual Review
Recommendation
check that
_srcChainSender
equalscomposeMessage.user
for those types of compose messages (e.g authenticate the actions in the compose receiver).Duplicate of #14