hats-finance / Tapioca--Lending-Engine--0x5bee198f5b060eecd86b299fdbea6b0c07c728dd

Other
0 stars 0 forks source link

The `Usdo#fallback()` allows any one to access the `UsdoReceiver` module and call any function #17

Open hats-bug-reporter[bot] opened 4 months ago

hats-bug-reporter[bot] commented 4 months ago

Github username: @bauchibred Twitter username: bauchibred Submission hash (on-chain): 0x1c2d46ee0c064a6aec05426bffb2e426b165c41baa25d2fb4ef746a85bb0a498 Severity: high

Description: Description The window here is a bit similar to this previous issue, albeit in this instance the module the attacker can access is limited to the UsdoReceiver.

Now, take a look at https://github.com/hats-finance/Tapioca--Lending-Engine--0x5bee198f5b060eecd86b299fdbea6b0c07c728dd/blob/8920782db6044643fd0c682f58ef37f7e59f99b1/contracts/usdo/Usdo.sol#L101-L105

    fallback() external payable {
        /// @dev Call the receiver module on fallback, assume it's gonna be called by endpoint.
        _executeModule(uint8(IUsdo.Module.UsdoReceiver), msg.data, false);
    }

Evidently, we can conclude protocol blindly assumes this fallback function can oly be triggered by the lz endPoint, however that's not the case, as anyone querying this contract without specifying any matching function would have access to execute the fallback, this then means that anyone can then execute any logic on the UsdoReceiver module.

Would be key to note that the UsdoReceiver contract inherits the TapiocaOmnichainReceiver, which means that the attacker can specify any logic they want to be triggered in the UsdoReceiver from the functions inherited through TapiocaOmnichainReceiver even if these actions should not be accessible to them considering they aren't permitted.

Attack Scenario One just needs to specify any non-matching function to trigger the fallback. Recommendation Consider having a real check to ensure it's indeed the endpoint that's querying that's trying to access the fallback. Attachments

  1. Proof of Concept (PoC) File

N/A

  1. Revised Code File (Optional)

N/A

cryptotechmaker commented 3 months ago

The only method in TapiocaOmniChainReceiver is lzCompose which is verified

  if (_from != address(this)) {
            revert InvalidComposer(_from);
        }
        if (msg.sender != address(endpoint)) {
            revert InvalidCaller(msg.sender);
        }

Also, down the line of inheritance, the lzReceive is also verified https://github.com/LayerZero-Labs/LayerZero-v2/blob/417cbb9eb68a4f678490d18728973c8c99f3f017/packages/layerzero-v2/evm/oapp/contracts/oapp/OAppReceiver.sol#L93