sherlock-audit / 2024-09-orderly-network-solana-contract-judging

0 stars 0 forks source link

Sunny Syrup Worm - Flaw in Token Validation Process Allows Users to Deposit Unauthorized Tokens for Authorized Tokens #104

Open sherlock-admin3 opened 4 days ago

sherlock-admin3 commented 4 days ago

Sunny Syrup Worm

High

Flaw in Token Validation Process Allows Users to Deposit Unauthorized Tokens for Authorized Tokens

Summary

A malicious user can bypass the current whitelist system by tricking it into believing that they have deposited USDC, thereby making off with more tokens than they actually deposited. This is done by specifying the hash of an approved token (e.g., USDC) while depositing a different, lower-value token (e.g., BONK).

Root Cause

The Orderly Solana vault currently has a whitelist system that restricts deposits to certain tokens that have been whitelisted or allowed by the admin. However, during deposits, it is still possible for a malicious user to deposit tokens other than the allowed token. This is due to the fact that the system checks if a token is allowed based on the token hash input but does not verify whether the actual deposit token matches the allowed token.

    #[account(
        seeds = [TOKEN_SEED, deposit_params.token_hash.as_ref()],
        bump = allowed_token.bump,
        constraint = allowed_token.allowed == true @ VaultError::TokenNotAllowed
    )]
    pub allowed_token: Box<Account<'info, AllowedToken>>,

Internal Preconditions

None

External Preconditions

None

Attack Path

The currently allowed token is USDC. An attacker can follow this path to trick the system by depositing BONK instead while passing in the hash of USDC. This will incorrectly update the ledger in the EVM to store that the user deposited a certain amount of USDC when, in fact, they deposited BONK in the solana vault.

  1. The malicious user will fill the deposit parameters with the token hash correctly set to the USDC token hash:

    pub struct DepositParams {
       pub account_id: [u8; 32],
       pub broker_hash: [u8; 32],
       pub token_hash: [u8; 32],  // <---- @
       pub user_address: [u8; 32],
       pub token_amount: u64,
    }
  2. Then, they will call solana_vault::deposit with deposit_token set to the BONK token in the context:

    #[account()]
    pub deposit_token: Box<Account<'info, Mint>>,
  3. The token is then transferred to the vault token account, and the deposit message is sent via LayerZero to the SolConnector.

As of the time of writing this report, 1 USDC is equivalent to 46,281 BONK. Given that BONK's token decimal precision is 5, while USDC's is 6, if the token_amount is set to 4,628.1e6, the malicious user will deposit 1 USDC worth of BONK tokens for 4,628 USDC. In the destination chain, SolConnector, the user will thus appear to have deposited 4,628 USDC.

Impact

Malicious users could deposit low-value tokens instead of USDC, making off with significantly more tokens than they actually deposited.

Proof of Concept (PoC)

https://github.com/sherlock-audit/2024-09-orderly-network-solana-contract/blob/a40ed80ce4a196bc81bfa6dfb749c19b92c623b0/solana-vault/packages/solana/contracts/programs/solana-vault/src/lib.rs#L22-L28

https://solscan.io/token/DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263

Mitigation

Update Deposit::deposit_token to:

#[account(constraint = allowed_token.mint_account == deposit_token.key())]
pub deposit_token: Box<Account<'info, Mint>>,