Skip to content
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

ComposableSecurity - OFT can be impersonated through _lzCompose with multiple compose messages #135

Closed
sherlock-admin3 opened this issue Mar 15, 2024 · 10 comments
Labels
Duplicate A valid issue that is a duplicate of an issue with `Has Duplicates` label Escalation Resolved This issue's escalations have been approved/rejected High A valid High severity issue Reward A payout will be made for this issue

Comments

@sherlock-admin3
Copy link
Contributor

sherlock-admin3 commented Mar 15, 2024

ComposableSecurity

high

OFT can be impersonated through _lzCompose with multiple compose messages

Summary

The _lzCompose function in TapiocaOmnichainReceiver contract handles the cross-chain messages retrieved from different chains. The first parameter srcChainSender_ represents the sender of the message on the source chain.

The issue is the following: if the message contains the next compose message, the _lzCompose function is called with address(this) as the srcChainSender_. This allows anyone to make a cross-chain calls with multiple compose messages, and execute the messages (all except the first one) as the OFT contract.

The user can send a message with multiple compose messages using sendPacket function in OTF tokens.

Vulnerability Detail

The OFT tokens (USDO, TOFT, mTOFT) delegate the lzReceive() execution to the Omnichain receiver that inherits from TapiocaOmnichainReceiver. This means that the cross-chain messages (send via Layer Zero) are handled by _lzCompose function from TapiocaOmnichainReceiver.

https://github.com/sherlock-audit/2024-02-tapioca/blob/main/Tapioca-bar/gitmodule/tapioca-periph/contracts/tapiocaOmnichainEngine/TapiocaOmnichainReceiver.sol#L146-L184

The first parameter of the function (srcChainSender_) represents the sender of the message on the source chain. The main compose message is executed with correct value of srcChainSender_ parameter.

However, the nested messages will be executed with address(this) as the srcChainSender_ - it means that the operation will be executed on behalf of OFT token.

The next message is retrieved by the decodeToeComposeMsg function:

https://github.com/sherlock-audit/2024-02-tapioca/blob/main/Tapioca-bar/gitmodule/tapioca-periph/contracts/tapiocaOmnichainEngine/TapiocaOmnichainEngineCodec.sol#L117-L137

The sendPacket function accepts any bytes for _composeMsg parameter, which is forwarded to the same function in TapiocaOmnichainSender contract. There, it is passed to _buildOFTMsgAndOptions without any modification and, in the end, it is encoded using LayerZero's OFTMsgCodec library - again, with no modification.

That said, the sender has full control over the compose message and can specify any number of nested messages (represented as _nextMsg).

Impact

HIGH - Anyone is able to execute operations in Tapioca on behalf of the OFT tokens.

Code Snippet

https://github.com/sherlock-audit/2024-02-tapioca/blob/main/Tapioca-bar/contracts/usdo/Usdo.sol#L188

https://github.com/sherlock-audit/2024-02-tapioca/blob/main/TapiocaZ/contracts/tOFT/mTOFT.sol#L234

https://github.com/sherlock-audit/2024-02-tapioca/blob/main/TapiocaZ/contracts/tOFT/TOFT.sol#L182

https://github.com/sherlock-audit/2024-02-tapioca/blob/main/Tapioca-bar/gitmodule/tapioca-periph/contracts/tapiocaOmnichainEngine/TapiocaOmnichainReceiver.sol#L180-L183

Tool used

Manual Review

Recommendation

Execute next messages with current value of srcChainSender_ as the first parameter to the _lzCompose recurrent call.

Duplicate of #113

@github-actions github-actions bot added High A valid High severity issue Duplicate A valid issue that is a duplicate of an issue with `Has Duplicates` label labels Mar 20, 2024
@sherlock-admin4
Copy link
Contributor

1 comment(s) were left on this issue during the judging contest.

takarez commented:

there didnt seem to be any impact mentioned, impersonate to cause DOS, steal funds break functionality?

@sherlock-admin3 sherlock-admin3 changed the title Future Azure Locust - OFT can be impersonated through _lzCompose with multiple compose messages ComposableSecurity - OFT can be impersonated through _lzCompose with multiple compose messages Mar 31, 2024
@sherlock-admin3 sherlock-admin3 added the Reward A payout will be made for this issue label Mar 31, 2024
@ComposableSecurityTeam
Copy link

Escalate

This issue is not duplicate of #111. Actually, the issue #111 is a dup of another issue I reported (#136).

This issue has different:

  • attack vector,
  • impact,
  • Fix.

Attack vector

In #111 the root cause is in _remoteTransferReceiver function:https://github.com/sherlock-audit/2024-02-tapioca/blob/main/Tapioca-bar/gitmodule/tapioca-periph/contracts/tapiocaOmnichainEngine/TapiocaOmnichainReceiver.sol#L224). The sender of cross-chain message can make the recipient to initiate another cross-chain message (e.g. another remote transfer message).

In this issue (#135) the root cause lies in the _lzCompose function (https://github.com/sherlock-audit/2024-02-tapioca/blob/main/Tapioca-bar/gitmodule/tapioca-periph/contracts/tapiocaOmnichainEngine/TapiocaOmnichainReceiver.sol#L182). That is, when the OFT contract executes a list of compose messages, the first is executed with the correct sender in srcChainSender_ parameter, and the rest of messages contain the address of OFT contract in the srcChainSender_ parameter (set in the line linked above).

The attacker can simply create a cross-chain call with more than one compose message where the first message is executed as intended and the rest have the OFT contract as the sender.

Impact

In #111 the attacker is able to execute a remote transfer on behalf of any user, thus stealing their tokens.

In this issue the attacker is able to execute any cross-chain message on behalf of OFT contract. There might be two important results:

  1. DoS: The chain of messages is started on the source chain but never executed of the destination chain because the latter messages always revert due to invalid sender (e.g. trying to exercise option as OFT contract instead of the original sender).
  2. Abusing approvals: The attacker is able to steal any tokens that the user approved OFT contract for. It can simply initiate a remote transfer with OFT as the sender and victim of the owner of tokens.

Fix

In #111 the fis to change parameter of _internalRemoteTransferSendPacket function and it’s ready waiting in PR.

In this issue, the fix is in _lzCompose function (https://github.com/sherlock-audit/2024-02-tapioca/blob/main/Tapioca-bar/gitmodule/tapioca-periph/contracts/tapiocaOmnichainEngine/TapiocaOmnichainReceiver.sol#L182). I cannot see any PR that.

@sherlock-admin2
Copy link
Contributor

Escalate

This issue is not duplicate of #111. Actually, the issue #111 is a dup of another issue I reported (#136).

This issue has different:

  • attack vector,
  • impact,
  • Fix.

Attack vector

In #111 the root cause is in _remoteTransferReceiver function:https://github.com/sherlock-audit/2024-02-tapioca/blob/main/Tapioca-bar/gitmodule/tapioca-periph/contracts/tapiocaOmnichainEngine/TapiocaOmnichainReceiver.sol#L224). The sender of cross-chain message can make the recipient to initiate another cross-chain message (e.g. another remote transfer message).

In this issue (#135) the root cause lies in the _lzCompose function (https://github.com/sherlock-audit/2024-02-tapioca/blob/main/Tapioca-bar/gitmodule/tapioca-periph/contracts/tapiocaOmnichainEngine/TapiocaOmnichainReceiver.sol#L182). That is, when the OFT contract executes a list of compose messages, the first is executed with the correct sender in srcChainSender_ parameter, and the rest of messages contain the address of OFT contract in the srcChainSender_ parameter (set in the line linked above).

The attacker can simply create a cross-chain call with more than one compose message where the first message is executed as intended and the rest have the OFT contract as the sender.

Impact

In #111 the attacker is able to execute a remote transfer on behalf of any user, thus stealing their tokens.

In this issue the attacker is able to execute any cross-chain message on behalf of OFT contract. There might be two important results:

  1. DoS: The chain of messages is started on the source chain but never executed of the destination chain because the latter messages always revert due to invalid sender (e.g. trying to exercise option as OFT contract instead of the original sender).
  2. Abusing approvals: The attacker is able to steal any tokens that the user approved OFT contract for. It can simply initiate a remote transfer with OFT as the sender and victim of the owner of tokens.

Fix

In #111 the fis to change parameter of _internalRemoteTransferSendPacket function and it’s ready waiting in PR.

In this issue, the fix is in _lzCompose function (https://github.com/sherlock-audit/2024-02-tapioca/blob/main/Tapioca-bar/gitmodule/tapioca-periph/contracts/tapiocaOmnichainEngine/TapiocaOmnichainReceiver.sol#L182). I cannot see any PR that.

The escalation could not be created because you are not exceeding the escalation threshold.

You can view the required number of additional valid issues/judging contest payouts in your Profile page,
in the Sherlock webapp.

@damianrusinek
Copy link

Escalate

This issue is not duplicate of #111. Actually, the issue #111 is a dup of another issue I reported (#136).

This issue has different:

attack vector,
impact,
Fix.
Attack vector

In #111 the root cause is in _remoteTransferReceiver function:https://github.com/sherlock-audit/2024-02-tapioca/blob/main/Tapioca-bar/gitmodule/tapioca-periph/contracts/tapiocaOmnichainEngine/TapiocaOmnichainReceiver.sol#L224). The sender of cross-chain message can make the recipient to initiate another cross-chain message (e.g. another remote transfer message).

In this issue (#135) the root cause lies in the lzCompose function (https://github.com/sherlock-audit/2024-02-tapioca/blob/main/Tapioca-bar/gitmodule/tapioca-periph/contracts/tapiocaOmnichainEngine/TapiocaOmnichainReceiver.sol#L182). That is, when the OFT contract executes a list of compose messages, the first is executed with the correct sender in srcChainSender parameter, and the rest of messages contain the address of OFT contract in the srcChainSender_ parameter (set in the line linked above).

The attacker can simply create a cross-chain call with more than one compose message where the first message is executed as intended and the rest have the OFT contract as the sender.

Impact

In #111 the attacker is able to execute a remote transfer on behalf of any user, thus stealing their tokens.

In this issue the attacker is able to execute any cross-chain message on behalf of OFT contract. There might be two important results:

DoS: The chain of messages is started on the source chain but never executed of the destination chain because the latter messages always revert due to invalid sender (e.g. trying to exercise option as OFT contract instead of the original sender).
Abusing approvals: The attacker is able to steal any tokens that the user approved OFT contract for. It can simply initiate a remote transfer with OFT as the sender and victim of the owner of tokens.
Fix

In #111 the fis to change parameter of _internalRemoteTransferSendPacket function and it’s ready waiting in PR.

In this issue, the fix is in _lzCompose function (https://github.com/sherlock-audit/2024-02-tapioca/blob/main/Tapioca-bar/gitmodule/tapioca-periph/contracts/tapiocaOmnichainEngine/TapiocaOmnichainReceiver.sol#L182). I cannot see any PR that.

@sherlock-admin2
Copy link
Contributor

Escalate

This issue is not duplicate of #111. Actually, the issue #111 is a dup of another issue I reported (#136).

This issue has different:

attack vector,
impact,
Fix.
Attack vector

In #111 the root cause is in _remoteTransferReceiver function:https://github.com/sherlock-audit/2024-02-tapioca/blob/main/Tapioca-bar/gitmodule/tapioca-periph/contracts/tapiocaOmnichainEngine/TapiocaOmnichainReceiver.sol#L224). The sender of cross-chain message can make the recipient to initiate another cross-chain message (e.g. another remote transfer message).

In this issue (#135) the root cause lies in the lzCompose function (https://github.com/sherlock-audit/2024-02-tapioca/blob/main/Tapioca-bar/gitmodule/tapioca-periph/contracts/tapiocaOmnichainEngine/TapiocaOmnichainReceiver.sol#L182). That is, when the OFT contract executes a list of compose messages, the first is executed with the correct sender in srcChainSender parameter, and the rest of messages contain the address of OFT contract in the srcChainSender_ parameter (set in the line linked above).

The attacker can simply create a cross-chain call with more than one compose message where the first message is executed as intended and the rest have the OFT contract as the sender.

Impact

In #111 the attacker is able to execute a remote transfer on behalf of any user, thus stealing their tokens.

In this issue the attacker is able to execute any cross-chain message on behalf of OFT contract. There might be two important results:

DoS: The chain of messages is started on the source chain but never executed of the destination chain because the latter messages always revert due to invalid sender (e.g. trying to exercise option as OFT contract instead of the original sender).
Abusing approvals: The attacker is able to steal any tokens that the user approved OFT contract for. It can simply initiate a remote transfer with OFT as the sender and victim of the owner of tokens.
Fix

In #111 the fis to change parameter of _internalRemoteTransferSendPacket function and it’s ready waiting in PR.

In this issue, the fix is in _lzCompose function (https://github.com/sherlock-audit/2024-02-tapioca/blob/main/Tapioca-bar/gitmodule/tapioca-periph/contracts/tapiocaOmnichainEngine/TapiocaOmnichainReceiver.sol#L182). I cannot see any PR that.

You've created a valid escalation!

To remove the escalation from consideration: Delete your comment.

You may delete or edit your escalation comment anytime before the 48-hour escalation window closes. After that, the escalation becomes final.

@nevillehuang
Copy link
Collaborator

This seems like a duplicate of #113, will need to review further. They are all very similar to each other.

@cvetanovv
Copy link
Collaborator

I agree with the escalations and @nevillehuang comment. We can deduplicate from #111 and duplicate with #113.

@cvetanovv
Copy link
Collaborator

Planning to accept the escalation and remove the duplication with #111, but duplicate with #113.

@Evert0x
Copy link

Evert0x commented Apr 10, 2024

Result:
High
Duplicate of #113

@sherlock-admin4
Copy link
Contributor

sherlock-admin4 commented Apr 10, 2024

Escalations have been resolved successfully!

Escalation status:

@sherlock-admin2 sherlock-admin2 removed the Escalated This issue contains a pending escalation label Apr 10, 2024
@sherlock-admin3 sherlock-admin3 added the Escalation Resolved This issue's escalations have been approved/rejected label Apr 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate A valid issue that is a duplicate of an issue with `Has Duplicates` label Escalation Resolved This issue's escalations have been approved/rejected High A valid High severity issue Reward A payout will be made for this issue
Projects
None yet
Development

No branches or pull requests

8 participants