sherlock-audit / 2024-02-tapioca-judging

3 stars 2 forks source link

bin2chen - exerciseOptionsReceiver() user can send dangerous compose across-chain as _options.from #110

Closed sherlock-admin2 closed 4 months ago

sherlock-admin2 commented 4 months ago

bin2chen

high

exerciseOptionsReceiver() user can send dangerous compose across-chain as _options.from

Summary

An important security guarantee for the lzCompose mechanism is that srcChainSender can guarantee that it is called by users themselves. However, exercisoptionsreceiver ()->_sendpacket () can specify _options.from as srcChainSender for remote call. This gives users beyond the original authorization to execute other methods in other chains as _options.from.

Vulnerability Detail

UsdoOptionReceiverModule.exerciseOptionsReceiver() the codes as follows:

    function exerciseOptionsReceiver(address srcChainSender, bytes memory _data) public payable {
....

@>            _sendPacket(msg_.lzSendParams, msg_.composeMsg, _options.from);

                // Refund extra amounts
                if (_options.tapAmount - amountToSend > 0) {
                    IERC20(tapOft).safeTransfer(_options.from, _options.tapAmount - amountToSend);
                }
            } else {
                //send on this chain
                IERC20(tapOft).safeTransfer(_options.from, _options.tapAmount);
            }
        }

...

    function _sendPacket(LZSendParam memory _lzSendParam, bytes memory _composeMsg, address _srcChainSender)
        private
        returns (MessagingReceipt memory msgReceipt, OFTReceipt memory oftReceipt)
    {

From the above code, we know Suppose: _options.from =bob just gave alice allowance, which can be used to execute exerciseOptionsReceiver(). But because _sendPacket () specifies _srcchainsender = bob. In this way,alice can use the identity of bob and send cross-chain information to execute other arbitrary composeMsg. For example, execute MSG_REMOTE_TRANSFER and other arbitrary USDO composeMsg.

Impact

The user goes beyond the original authorization and executes other methods in other chains as _options.from.

Code Snippet

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

Tool used

Manual Review

Recommendation

use old srcChainSender as new srcChainSender

    function exerciseOptionsReceiver(address srcChainSender, bytes memory _data) public payable {
....

-             _sendPacket(msg_.lzSendParams, msg_.composeMsg, _options.from);
+             _sendPacket(msg_.lzSendParams, msg_.composeMsg, srcChainSender);

                // Refund extra amounts
                if (_options.tapAmount - amountToSend > 0) {
                    IERC20(tapOft).safeTransfer(_options.from, _options.tapAmount - amountToSend);
                }
            } else {
                //send on this chain
                IERC20(tapOft).safeTransfer(_options.from, _options.tapAmount);
            }
        }

Duplicate of #134