code-423n4 / 2024-03-revert-lend-findings

13 stars 10 forks source link

`V3Vault.sol` permit signature does not check receiving token address is USDC #368

Open c4-bot-3 opened 7 months ago

c4-bot-3 commented 7 months ago

Lines of code

https://github.com/code-423n4/2024-03-revert-lend/blob/main/src/V3Vault.sol#L717-L725 https://github.com/code-423n4/2024-03-revert-lend/blob/main/src/V3Vault.sol#L893-L898 https://github.com/code-423n4/2024-03-revert-lend/blob/main/src/V3Vault.sol#L877-L917

Vulnerability details

In V3Vault.sol there all 3 instances of permit2.permitTransferFrom(), all 3 does not check token transfered in is USDC token. Allowing user to craft permit signature from any ERC20 token and Vault will accept it as USDC.

Impact

User can steal all USDC from vault using permit signature of any ERC20 token.

Proof of Concept

Here is how Vault accept USDC from user. Vault will accept Uniswap.Permit2 signature transfer allowance from Permit2 then to vault contract. https://github.com/code-423n4/2024-03-revert-lend/blob/435b054f9ad2404173f36f0f74a5096c894b12b7/src/V3Vault.sol#L877C1-L917C6

    if (params.permitData.length > 0) {
        (ISignatureTransfer.PermitTransferFrom memory permit, bytes memory signature) =
            abi.decode(params.permitData, (ISignatureTransfer.PermitTransferFrom, bytes));
        permit2.permitTransferFrom(
            permit,
            ISignatureTransfer.SignatureTransferDetails(address(this), state.liquidatorCost),
            msg.sender,
            signature
        );
    } else {
        // take value from liquidator
        SafeERC20.safeTransferFrom(IERC20(asset), msg.sender, address(this), state.liquidatorCost);
    }

Below is permit signature struct that can be decoded from user provided data.

interface ISignatureTransfer is IEIP712 {
    /// @notice The token and amount details for a transfer signed in the permit transfer signature
    struct TokenPermissions {
        // ERC20 token address
        address token;
        // the maximum amount that can be spent
        uint256 amount;
    }

    /// @notice The signed permit message for a single token transfer
    struct PermitTransferFrom {
        TokenPermissions permitted;
        // a unique value for every token owner's signature to prevent signature replays
        uint256 nonce;
        // deadline on the permit signature
        uint256 deadline;
    }
}

V3Vault.sol need to check TokenPermissions.token is USDC, same as vault main asset.

Uniswap.permit2.permitTransferFrom() only check sign signature is correct. This is meaningless is Vault does not validate input data.

This allow user to use any ERC20 token. give allowance and permit to Uniswap.Permit2 Vault will accept any transfer token from Permit2 as USDC.

Allowing user to deposit any ERC20 token and steal USDC from vault.

Tools Used

Recommended Mitigation Steps

fix missing user input validation in 3 all instances of permit2 https://github.com/code-423n4/2024-03-revert-lend/blob/main/src/V3Vault.sol#L717C1-L725C15 https://github.com/code-423n4/2024-03-revert-lend/blob/main/src/V3Vault.sol#L893C1-L898C15 https://github.com/code-423n4/2024-03-revert-lend/blob/main/src/V3Vault.sol#L877C1-L917C6

    if (params.permitData.length > 0) {
        (ISignatureTransfer.PermitTransferFrom memory permit, bytes memory signature) =
            abi.decode(params.permitData, (ISignatureTransfer.PermitTransferFrom, bytes));
        require(permit.permitted.token == asset, "V3Vault: invalid token");
        //@permitted amount is checked inside uniswap Permit2
        permit2.permitTransferFrom(
            permit,
            ISignatureTransfer.SignatureTransferDetails(address(this), state.liquidatorCost),
            msg.sender,
            signature
        );
    } else {
        // take value from liquidator
        SafeERC20.safeTransferFrom(IERC20(asset), msg.sender, address(this), state.liquidatorCost);
    }

Assessed type

ERC20

c4-pre-sort commented 7 months ago

0xEVom marked the issue as primary issue

c4-pre-sort commented 7 months ago

0xEVom marked the issue as sufficient quality report

c4-sponsor commented 7 months ago

kalinbas (sponsor) confirmed

c4-judge commented 7 months ago

jhsagd76 marked the issue as satisfactory

c4-judge commented 7 months ago

jhsagd76 marked the issue as selected for report

kalinbas commented 7 months ago

https://github.com/revert-finance/lend/pull/19