Skip to content

Missing ProgramData Ownership Validation Allows Attacker to Hijack Admin and Drain Treasury #3859

@research-infsec

Description

@research-infsec

Summary

source: https://github.com/litentry/heima/tree/dev/tee-worker/omni-executor/contracts/accounting/solana

The set_admin function only verifies that the signer matches program_account.upgrade_authority_address, but does not validate whether the ProgramData account belongs to the current contract. An attacker can pass in the ProgramData account of any upgradeable program they control, bypass the authorization check, set themselves as the contract admin, and then drain all treasury funds via withdraw_funds or set_worker + create_pay_request.

Root Cause

The vulnerability exists in the SetAdmin struct (lines 177-185) and set_admin function (lines 14-25) in lib.rs:

#[derive(Accounts)]
pub struct SetAdmin<'info> {
    #[account(init_if_needed, payer = signer, space = 8 + AdminAccount::INIT_SPACE, seeds = [b"admin"], bump)]
    pub admin_account: Account<'info, AdminAccount>,
    #[account(mut)]
    pub signer: Signer<'info>,
    pub program_account: Account<'info, ProgramData>,  // Missing address constraint
    pub system_program: Program<'info, System>,
}

The program_account field only declares its type as ProgramData, but has no address/constraint validation to verify it belongs to this program.

Attack Steps:

  1. Attacker deploys their own upgradeable program (where they are the upgrade_authority)
  2. Attacker calls target contract's set_admin, passing in their own program's ProgramData account
  3. Validation passes (attacker is indeed the upgrade_authority of that ProgramData)
  4. Attacker becomes admin and calls withdraw_funds to drain all treasury funds

Recommended Fix: Add an address constraint to enforce program_account is this program's ProgramData:

#[account(
    address = bpf_loader_upgradeable::get_program_data_address(&crate::ID)
        @ ErrorCode::InvalidProgram
)]
pub program_account: Account<'info, ProgramData>,

About us

We would greatly appreciate it if you could consider providing a Bug Bounty reward for this vulnerability submission.

Looking for an audit? We're InfiniteSec, a professional blockchain security team. Our auditors have deep expertise in Solana, EVM, and Cosmos ecosystems.

We helped identify this vulnerability before any exploit occurred. We'd love to become your long-term security partner and help protect your future releases.

Get in touch:
Telegram: @infinitesec_io
Website: https://infsec.io

Best regards,
InfiniteSec Team

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions