Beosin ay Ipinakita ang Mahalagang Vulnerability sa IDL Instruction sa Mababang Bersyon ng Solana Anchor Framework

iconMetaEra
I-share
AI summary iconSummary
Ang security team ng Beosin ay nakakita ng kritikal na vulnerability sa IDL instruction sa mga mababang bersyon ng Solana Anchor frameworks. Ang kakulangan ay nagpapahintulot sa mga attacker na kunin ang mga account na PDA na may-ari ng program sa pamamagitan ng pagpapagamit ng AccountInfo declarations, na nagpapahintulot sa pagkakawala ng pera sa dalawang hakbang nang walang mga pribilehiyo ng user. Ang insidente ay nagpapakita ng pangangailangan ng mas malakas na framework para sa compliance sa pagbuo ng smart contract. Habang malapit na ang MiCA (EU Markets in Crypto-Assets Regulation), ang ganitong mga vulnerability ay nagte-teklado sa kahalagahan ng real-time security audits at pagsunod sa mga regulatoryong pamantayan.

Ang Anchor ay ang pinakamalaking development framework sa ecosystem ng Solana. Sa pamamagitan ng mga tampok tulad ng declarative account verification, automatic serialization, at built-in security checks, napakadali nito ang pagbuo. Gayunpaman, habang binibigay ng framework ang kahalagahan, ito ay naglalagay ng ilang internal instructions sa bawat program na maaaring hindi alam ng mga developer. Ang mga "nakatago" na instruction na ito ay maaaring gamitin ng mga attacker sa ilang partikular na kondisyon upang magdulot ng malalaking pagkawala ng pera.

Iipakita ng Beosin Security Team ang isang mahalagang pattern ng vulnerability: sa mga mas mababang bersyon ng Anchor, kapag ginagamit ng developer ang AccountInfo upang ilarawan ang PDA account na may-ari ng program, maaaring mag-atake ang isang hacker gamit ang IDL instruction na awtomatikong inilalagay ng Anchor, at kailangan lamang ng dalawang hakbang upang kunin ang kontrol ng account at walang iwanang SOL, nang walang kailangang magkaroon ng anumang espesyal na pahintulot.

Isa. Pagsusuri sa mga utos ng IDL at kaugnay na mekanismo

1.1 IDL Instruction

Ang Anchor ay magpapaloob ng isang set ng mga utos na IDL (Interface Definition Language) sa bawat programa, maliban kung ang no-idl feature ay aktibado nang eksplisito sa pagbuo. Ang mga utos na ito ay kasama ang:

IdlCreateAccount: Lumikha ng isang chain-based IDL account

IdlWrite: Isulat ang data sa IDL account / buffer account

IdlSetAuthority: Baguhin ang authority ng IDL account

IdlCloseAccount: Isara ang IDL account at ilipat ang lahat ng lamports sa nakatakdang tagatanggap

IdlResizeAccount: I-adjust ang laki ng IDL account

IdlCreateBuffer: Lumikha ng IDL Buffer account (IDL Buffer)

IdlSetBuffer: I-overwrite ang opisyal na IDL account gamit ang data mula sa buffer account

Ang mga utos na ito ay disenyo para sa pamamahala ng chain-based IDL, ngunit may espesyal na kapasidad sa mga akawnt na may-ari ng programa (basahin at isulat ang data, baguhin ang tagapag-ugnay, isara at ilipat ang mga lamports)—ito ang puso ng butas. Hindi kailangan ng attacker na tawagan ang anumang negosyo utos na isinulat ng developer; direktang tatawagin nila ang mga itinakdang utos.

1.2 IDL Buffer Account

Ang IDL Buffer account ay isang pansamantalang account na ipinakilala ng Anchor para sa pag-upload ng malalaking IDL data sa mga bahagi. Dahil ang buong IDL (na compressed sa JSON) ay maaaring lumampas sa limitasyon ng laki ng isang transaksyon, pinapayagan ng Anchor na unang lumikha ng buffer gamit ang IdlCreateBuffer, sumunod ay isulat ito sa mga bahagi gamit ang maraming IdlWrite, at huling i-submit nang isang beses gamit ang IdlSetBuffer.

Ang pangunahing punto ay ang data structure ng IDL account / buffer account: ito ay nagsisimula sa isang header na may fixed layout, na naglalaman ng isang authority: Pubkey field (tinatawag na controller sa test output ng artikulong ito). Ang IDL instruction ay gumagamit ng field na ito upang matukoy kung "sino ang may awtoridad na mag-operate sa account".

Ang problema ay: ang lohika ng IdlCreateBuffer sa mas mababang bersyon ng Anchor ay mag-iinitialize ang anumang account na may-ari ng programa bilang isang buffer account, at direktang i-set ang authority bilang signatory ng transaksyon. Ibig sabihin, kung ang owner ng isang account ay ang programa mismo (halimbawa, ang PDA vault ng programa), ang isang attacker ay makakasulat ng sarili bilang controller nito, at pagkatapos ay gamitin ang IdlCloseAccount upang legal na ilipat ang lahat ng SOL mula sa account.

1.3 Mga kondisyon para sa pag-trigger ng vulnerability

Kailangan ng parehong mga kondisyon upang masira ang butas:

  • Gumamit ng mas lumang bersyon ng Anchor: Ang nakapagpapalabas na IDL instruction ay hindi sapat na nagpapahiwatig ng account, na nagpapahintulot na maliit ang business account bilang IDL account.
  • Hindi pinagana ang no-idl: ang programa ay nagpanatili ng default na injected IDL instruction entry sa pagbuo, na nagpapakita ng attack surface.
  • Gamitin ang AccountInfo upang ipahayag ang PDA na may-ari ng programa: Ang mga developer ay gumagamit ng裸 na AccountInfo upang magdala ng account ng pondo (tulad ng treasury PDA), na kulang sa discriminator / owner na pagkilala na dala ng Anchor-typed account (tulad ng Account), na ginagawa itong “hindi makikilala” sa IDL instruction kumpara sa IDL account.
  • Ang account ay may-ari at nagtataglay ng lamports: owner == ang programa ito ay kondisyon para sa IDL instruction na makapag-operate dito; kailangan magkaroon ng SOL upang may halaga na mabawasan.

Pagkatapos matugunan ang mga kondisyon, kailangan lang ng attacker ng dalawang karaniwang transaksyon: una ay IdlCreateBuffer upang kunin ang controller, at pagkatapos ay IdlCloseAccount upang ilipat ang lahat ng SOL, at maaari nilang tapusin ang pag-atake nang walang kailangang bigyan ng anumang pahintulot ang target na programa.

1.4 Chain of Attack

Sa ibaba, kasama ang pagsusuri sa loob ng Anchor, hihiwalay namin ang paraan kung paano ginamit ng attacker ang dalawang nakapaloob na utos lamang upang “magkamali” ang isang karaniwang pautang na vault bilang IDL account at pagkatapos ay buuin ito.

Overview ng Attack Process

Hakbang 1  IdlCreateBuffer(treasury, signer = attacker)    
└─ treasury.controller  ==>  attacker   (maging controller) 
Hakbang 2  IdlCloseAccount(treasury, authority = attacker, dest = attacker)  
  └─ treasury.lamports    ==>  attacker   (awasan ang treasury)

Unang hakbang: IdlCreateBuffer ay humahawak ng awtoridad

Ang Anchor ay may panloob na implementasyon na ganito:

#[derive(Accounts)]pub struct IdlCreateBuffer {  
#[account(zero)]          // ← Key: isang account na may discriminator na lahat 0  pub buffer: Account,  
pub authority: Signer,}    
pub fn idl_create_buffer(ctx: Context) -> Result 
{ 
 let idl = &mut ctx.accounts.buffer;  idl.authority = *ctx.accounts.authority.key; // itakda ang attack bilang authority  Ok(())}

Ang kahulugan ng #[account(zero)] ay: tumanggap ng isang account na may discriminator na lahat ay zero at binabawasan ng programa, bilang isang hindi pa inisyalisadong IDL account. At ang vault ay sumasapat sa parehong kondisyon:

Kalagayan ng vault

Mga kondisyon

nagmamay-ari ng programa

Pagkatapos ng init_if_needed, ang owner ay itinakda bilang ang programa na ito

discriminator lahat ng zero

Gumagamit ng AccountInfo type, hindi isusulat ng Anchor ang discriminator, ang data ay zero lahat

Kaya isinumite ng attacker ang vault sa IdlCreateBuffer pagkatapos:

  • Isulat ang discriminator ng IdlAccount sa mga unang 8 byte bago ang vault;
  • Isulat ang public key ng attacker sa field na authority.

Sa point na ito, ang vault ay “nakapagtakip” bilang isang IdlAccount na may authority sa attacker—at ang mga SOL nito ay hindi nababawas.

Pangalawang hakbang: IdlCloseAccount —— Linisin ang mga pondo

#[derive(Accounts)]pub struct IdlCloseAccount {  #[account(mut, has_one = authority)]  // ← check authority == signer  pub account: Account,  pub authority: Signer,  #[account(mut)]  pub destination: AccountInfo,  // ← attack wallet}

Ang vault ay naging ganap na nakapagpasa ng pagsusuri:

  • magkakatugma ang discriminator sa IdlAccount
  • ang field na authority = public key ng attacker
  • has_one = authority ay nagsagawa ng pag-verify

Kaya ang lahat ng lamports (lahat ng SOL na ipinapadala ng user) sa vault ay legal na napadala sa account ng attacker, at naging zero ang vault.

Pangunahing dahilan:

Ang paggamit ng AccountInfo sa deposit.rs kaysa sa typed na Anchor Account ay ang patayong ugat ng butas na ito:

(1) Ang mga account na may uri (tulad ng Account) ay sumusulat ng 8-byte na discriminator na espesipiko sa estructura kapag iniihinto ito;

(2) Pagkatapos isulat ang sariling discriminator, hindi na kayang gamitin ng Anchor ang ito bilang IdlAccount (hindi tumutugma ang discriminator), at mabubuo ang unang hakbang na IdlCreateBuffer, at putol ang serye ng pag-atake.

Pangalawa: Pag-aaral ng kaso

Ang sumusunod na pagsubok ay batay sa PoC ng smart contract ng cross-chain bridge na binuo gamit ang Anchor 0.31.0. Ang pagsubok ay nagmumodelo ng isang tunay na bridge treasury kung saan ang owner ay ang sariling bridge program, na naglalaman ng 1.001281 SOL na ipinapasa ng mga user. Ang wallet ng attacker ay may 2 SOL sa simula at walang anumang espesyal na karapatan.

Proyekto

Halaga / Paliwanag

Bridge Program

CJutNlr8d3oxdb11ReOLaZd5jPsqUxgwt2mv5e7equtE

Treasury account

DxGkzaMhP5Wy824GhoehErdD6MudfuEPGPwaV2s77FsM

Owner ng KuCoin

= Program-owned PDA

Initial balance ng KuCoin

1.001281 SOL (deposito ng user)

Initial Controller

0x0000...0000 (lahat ng zero, hindi itinakda)

Initial balance of attacker's wallet

2.000000 SOL

Mga kinakailangang pribilehiyo

WALANG KAILANGANG PAGPAPAWALA

Bilang ng mga transaksyon

2 na transaksyon

Final wallet balance

0.000000 SOL (na-clear)

Nakakuha ng kita ang attacker

+1.001281 SOL

Screenshot ng PoC (tests/poc-idl-hijack.ts):

https://wdcdn.qpic.cn/MTMxMDI3MDE1MTgxMDU0NzA_812435_a37-yrU_dY02i1_I_1785900257?w=1080&h=1287

Nakikita mo na, ang IdlCreateBuffer sa Step 1 ay nagtakda ng attacker bilang controller ng vault (hindi nagbago ang balanse); ang IdlCloseAccount sa Step 2 ay naglipat ng buong 1.001281 SOL ng vault patungo sa wallet ng attacker, at naging sero ang balanse ng vault.

Mga rekomendasyon para sa pagpapabuti/atubili:

(1) I-upgrade ang Anchor version: Ang pinakabagong bersyon ay nag-aayos ng problema na ito (ang IDL instruction ay magkakaroon ng malinaw na pagkakaiba sa IDL account at business account), at ang pinakadirektang at pinakamainam na paraan upang makaiwas ay ang pag-iwas sa paggamit ng mas lumang bersyon ng Anchor.

(2) I-enable ang no-idl sa pagbuo: I-disables ang pag-inject ng IDL instructions para sa mga program sa production environment, at alisin ang attack surface mula sa pinagmulan.

(3) Gamitin ang typed account kaysa sa裸 AccountInfo: Gamitin ang Account / SystemAccount at iba pang mga uri na may discriminator at owner verification para sa mga account ng pondo, upang maiwasan ang maling pagkilala ng IDL instruction.

(4) Minimizing the number of accounts that the program can empty: Magdagdag ng malinaw na pagkakakilanlan / seeds / discriminator sa PDA na naglalaman ng pera, at i-verify ang account discriminator sa mga mahahalagang utos.

Pangwakas

Ang susi sa vulnerability ay ang kombinasyon ng “framework na nagtatago ng utos + kulang sa pagkilala sa uri ng akawnt.” Dapat maunawaan ng mga developer na ang IDL command na automoang ikinukuwenta ng Anchor ay isang totoong panganib, at ang pag-upgrade sa bersyon ng framework at ang paggamit ng malakas na uri ng pagpapahiwatig sa mga akawnt ng pondo ay maaaring makapagpapawi nang epektibo ng ganitong uri ng panganib ng hindi pinahintulutang pagbawi ng pondo.

Ang Beosin ay isang pangunahing kompanya sa teknolohiya para sa seguridad at pagtutugma sa regulasyon ng blockchain, na nakatuon sa pag-audit ng seguridad ng smart contract bago ang paglunsad ng proyekto, pagmonito at pagpigil sa mga panganib sa seguridad habang nagpapatakbo ang proyekto, pagkuha muli ng mga nasakop, virtual asset anti-money laundering (AML), at pag-imbestiga at pagtatakas. Ang Beosin ay nagbigay ng “isang-solusyon” na mga produkto sa pagtutugma sa blockchain at serbisyo sa seguridad para sa 20+ na ahensya ng regulasyon at pagsasapilitan sa buong mundo, 200+ na mga serbisyong virtual asset, at 4,500+ na mga Web3 project. Mangyaring i-click ang box ng mensahe sa aming public account para makipag-ugnayan sa amin.

Disclaimer: Ang information sa page na ito ay maaaring nakuha mula sa mga third party at hindi necessary na nagre-reflect sa mga pananaw o opinyon ng KuCoin. Ibinigay ang content na ito para sa mga pangkalahatang informational purpose lang, nang walang anumang representation o warranty ng anumang uri, at hindi rin ito dapat ipakahulugan bilang financial o investment advice. Hindi mananagot ang KuCoin para sa anumang error o omission, o para sa anumang outcome na magreresulta mula sa paggamit ng information na ito. Maaaring maging risky ang mga investment sa mga digital asset. Pakisuri nang maigi ang mga risk ng isang produkto at ang risk tolerance mo batay sa iyong sariling kalagayang pinansyal. Para sa higit pang information, mag-refer sa aming Terms ng Paggamit at Disclosure ng Risk.