code-423n4 / 2023-05-maia-findings

24 stars 13 forks source link

`RootBridgeAgent->CheckParamsLib#checkParams` does not check that `_dParams.token` is underlying of `_dParams.hToken` #687

Open code423n4 opened 1 year ago

code423n4 commented 1 year ago

Lines of code

https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootBridgeAgent.sol#L58

Vulnerability details

Impact

A malicious user would make a deposit specifying an hToken of a high value(say hEther), and a depositToken of relatively lower value(say USDC), and for that user, RootBridgeAgent would increment his hToken balance by the amount of depositTokens he sent

Proof of Concept

Here is the checkParams function:

function checkParams(address _localPortAddress, DepositParams memory _dParams, uint24 _fromChain)
        internal
        view
        returns (bool)
    {
        if (
            (_dParams.amount < _dParams.deposit) //Deposit can't be greater than amount.
                || (_dParams.amount > 0 && !IPort(_localPortAddress).isLocalToken(_dParams.hToken, _fromChain)) //Check local exists.
                || (_dParams.deposit > 0 && !IPort(_localPortAddress).isUnderlyingToken(_dParams.token, _fromChain)) //Check underlying exists.
        ) {
            return false;
        }
        return true;
    }

The function performs 3 checks:

The PROBLEM is that the check only requires that getLocalTokenFromUnder[_dParams.token]!=address(0), but does not check that getLocalTokenFromUnder[_dParams.token]==_dParams.hToken:

    function isUnderlyingToken(
        address _underlyingToken,
        uint24 _fromChain
    ) external view returns (bool) {
        return
            getLocalTokenFromUnder[_underlyingToken][_fromChain] != address(0);
    }

The checkParams function is used in the RootBridgeAgent#bridgeIn function.

This allows a user to call BranchBridgeAgent#callOutAndBridge with a hToken and token that are not related

ATTACK SCENARIO

Execution flow: BranchBridgeAgent#callOutAndBridge->BranchBridgeAgent#_callOutAndBridge->BranchBridgeAgent#_depositAndCall->BranchBridgeAgent#_performCall->RootBridgeAgent#anyExecute->RootBridgeAgentExecutor#executeWithDeposit->RootBridgeAgentExecutor#_bridgeIn->RootBridgeAgent#bridgeIn

Tools Used

Manual Review

Recommended Mitigation Steps

Currently, the protocol only checks if the token is recognized by rootport as an underlying token by checking that the registered local token for _dParams.token is not zero address.

Assessed type

Invalid Validation

c4-judge commented 1 year ago

trust1995 marked the issue as duplicate of #285

c4-judge commented 1 year ago

trust1995 marked the issue as satisfactory

c4-judge commented 1 year ago

trust1995 marked the issue as selected for report

trust1995 commented 1 year ago

Better POC

0xBugsy commented 1 year ago

@trust1995 Same as #273

c4-sponsor commented 1 year ago

0xBugsy marked the issue as sponsor confirmed

c4-judge commented 1 year ago

trust1995 marked the issue as duplicate of #273

c4-judge commented 1 year ago

trust1995 marked the issue as not a duplicate

c4-judge commented 1 year ago

trust1995 marked the issue as primary issue

0xLightt commented 1 year ago

Addressed https://github.com/Maia-DAO/eco-c4-contest/tree/687