code-423n4 / 2023-07-axelar-findings

2 stars 0 forks source link

Lack of validation for `destinationChain` #347

Open code423n4 opened 1 year ago

code423n4 commented 1 year ago

Lines of code

https://github.com/code-423n4/2023-07-axelar/blob/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L135-L137

Vulnerability details

Impact

If a user supplies an incorrect destination chain their funds will be locked/burnt in the token manager.

Proof of Concept

When doing a cross chain transfer using InterchainTokenService eventually all calls ends up in a cross chain instruction:

https://github.com/code-423n4/2023-07-axelar/blob/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L707-L724

File: its/interchain-token-service/InterchainTokenService.sol

707:    function _callContract(
708:        string calldata destinationChain,
709:        bytes memory payload,
710:        uint256 gasValue,
711:        address refundTo
712:    ) internal {
713:        string memory destinationAddress = remoteAddressValidator.getRemoteAddress(destinationChain);
714:        if (gasValue > 0) {
716:            gasService.payNativeGasForContractCall{ value: gasValue }(
717:                address(this),
718:                destinationChain,
719:                destinationAddress,
720:                payload,
721:                refundTo
722:            );
723:        }
724:        gateway.callContract(destinationChain, destinationAddress, payload);
725:    }

Here the address for the corresponding InterchainTokenService contract is queried, then message is passed to AxelarGateway.

In RemoteAddressValidator this lookup is done:

https://github.com/code-423n4/2023-07-axelar/blob/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L133-L138

File: its/remote-address-validator/RemoteAddressValidator.sol

133:    function getRemoteAddress(string calldata chainName) external view returns (string memory remoteAddress) {
134:        remoteAddress = remoteAddresses[chainName];
135:        if (bytes(remoteAddress).length == 0) {
136:            remoteAddress = interchainTokenServiceAddress.toString(); // <-- defaults to current chain interchainTokenServiceAddress
137:        }
138:    }

Here a default value of the InterchainTokenService address for the source chain is sent if the chain is not configured. Thus if a user makes a mistake with the string for the chain. This message will be accepted and their tokens locked/burnt.

Almost all tests in tokenService.js and tokenServiceFullFlow.js are actually a PoC for this since none of them configure the destination chain in RemoteAddressValidator.

Tools Used

Manual audit

Recommended Mitigation Steps

Revert when the chainName provided is not configured.

Assessed type

Invalid Validation

c4-pre-sort commented 1 year ago

0xSorryNotSorry marked the issue as duplicate of #254

c4-judge commented 1 year ago

berndartmueller changed the severity to QA (Quality Assurance)