Anchor، سولانا ایکوسسٹم کا سب سے زیادہ استعمال ہونے والا ڈویلپمنٹ فریم ورک ہے۔ یہ اعلانیہ اکاؤنٹ تصدیق، خودکار سیریلائزیشن اور داخلہ سیکیورٹی چیکس جیسی خصوصیات کے ذریعے ڈویلپمنٹ کی رکاوٹوں کو بہت زیادہ کم کرتا ہے۔ تاہم، فریم ورک کی سہولت فراہم کرتے ہوئے، پیچھے ہر پروگرام میں کچھ ایسے اندر کے حکمات ڈالتا ہے جن کے بارے میں ڈویلپرز شاید نہ جانیں۔ یہ "چھپے ہوئے" حکمات خاص حالات میں حملہ آور کے ذریعہ استعمال کیے جا سکتے ہیں اور جس سے شدید رقم کا نقصان ہو سکتا ہے۔
Beosin سیفٹی ٹیم ایک اہم خرابی کے نمونے کو کھولے گی: کم ورژن Anchor میں، جب ڈویلپرز AccountInfo کا استعمال کرتے ہوئے پروگرام مالک PDA اکاؤنٹس کو دیتے ہیں، تو حملہ آور Anchor کے ذریعہ خودکار طور پر داخل کیے گئے IDL احکامات کا استعمال کرکے صرف دو اقدامات میں اکاؤنٹ کا کنٹرول حاصل کر سکتے ہیں اور اس میں موجود تمام SOL خالی کر سکتے ہیں، جس کے لیے کسی بھی خصوصی اجازت کی ضرورت نہیں ہوتی۔
ایک، IDL ہدایات اور متعلقہ مکینزم کا تجزیہ
1.1 IDL حکم
اینکور ہر پروگرام میں ایک IDL (Interface Definition Language، انٹرفیس ڈیفینیشن لینگویج) مینجمنٹ احکامات کا مجموعہ خودبخود شامل کر دیتا ہے، جب تک کہ بناوٹ کے دوران no-idl فیچر کو واضح طور پر سکریب نہ کیا جائے۔ یہ احکامات درج ذیل ہیں:
IdlCreateAccount: ایک آن چین IDL اکاؤنٹ بنائیں
IdlWrite: IDL اکاؤنٹ / کیش اکاؤنٹ میں ڈیٹا لکھیں
IdlSetAuthority: IDL اکاؤنٹ کے اتھارٹی (کنٹرولر) کو تبدیل کریں
IdlCloseAccount: IDL اکاؤنٹ بند کریں اور اس کے تمام lamports مخصوص وصول کنندہ کو منتقل کریں
IdlResizeAccount: IDL اکاؤنٹ کا سائز تبدیل کریں
IdlCreateBuffer: IDL بفر اکاؤنٹ (IDL Buffer) بنائیں
IdlSetBuffer: بفر اکاؤنٹ کے ڈیٹا کو اصل IDL اکاؤنٹ پر اووررائیٹ کریں
یہ حکمات کو چین پر IDL انتظام کے لیے ڈیزائن کیا گیا تھا، لیکن ان کے پاس پروگرام کے ملکیت والے اکاؤنٹس پر خاص عمل کی صلاحیت ہے (ڈیٹا پڑھنا/لکھنا، کنٹرولر تبدیل کرنا، بند کرنا اور lamports منتقل کرنا) — جو کہ خرابی کا مرکزی نقطہ ہے۔ حملہ آور کو ڈویلپر کے لکھے گئے کسی بھی بزنس حکمت کو بلانے کی ضرورت نہیں، وہ صرف ان内置 حکمات کو بلا سکتا ہے۔
1.2 IDL بفر اکاؤنٹ
IDL بفر اکاؤنٹ (IDL Buffer) Anchor کے ذریعہ بڑے IDL ڈیٹا کو ٹکڑوں میں اپ لوڈ کرنے کے لیے متعارف کرایا گیا ایک عارضی اکاؤنٹ ہے۔ کیونکہ مکمل IDL (JSON کمپریسڈ) ایک ٹرانزیکشن کے سائز کے حد سے زیادہ ہو سکتا ہے، Anchor اجازت دیتا ہے کہ پہلے IdlCreateBuffer کے ذریعہ ایک بفر بنایا جائے، پھر متعدد IdlWrite ٹرانزیکشنز کے ذریعہ اسے ٹکڑوں میں لکھا جائے، اور آخر میں IdlSetBuffer کے ذریعہ ایک بار میں جمع کر دیا جائے۔
اہم بات یہ ہے کہ IDL اکاؤنٹ / کیش اکاؤنٹ کی ڈیٹا سٹرکچر ایک فکسڈ لے آؤٹ والے ہیڈر سے شروع ہوتی ہے، جس میں authority: Pubkey فیلڈ ہوتا ہے (جسے اس مضمون کے ٹیسٹ آؤٹ پٹ میں controller کہا گیا ہے)۔ IDL ہدایات اس فیلڈ کے ذریعے "کون اس اکاؤنٹ کے ساتھ کام کرنے کا اختیار رکھتا ہے" کا فیصلہ کرتی ہیں۔
لیکن مسئلہ یہ ہے کہ کم ورژن Anchor کا IdlCreateBuffer منطق، اپنے پروگرام کے مالکانہ کسی بھی اکاؤنٹ کو بفر اکاؤنٹ کے طور پر شروع کردیتا ہے اور اتھارٹی کو براہ راست ٹرانزیکشن کے دستخط کرنے والے کو مقرر کردیتا ہے۔ یعنی، اگر کسی اکاؤنٹ کا مالک اپنا پروگرام ہے (مثلاً پروگرام کا PDA خزانہ)، تو حملہ آور اپنے آپ کو اس کا کنٹرولر بناسکتا ہے، اور پھر IdlCloseAccount کا استعمال کرتے ہوئے اکاؤنٹ میں موجود تمام SOL کو قانونی طور پر منتقل کر سکتا ہے۔
1.3 خامی کا فعال ہونے کا شرط
خرابی کو فعال کرنے کے لیے درج ذیل شرائط одно وقت پوری ہونی چاہئیں:
- پرانے ورژن Anchor کا استعمال کریں: خطرناک IDL ہدایات میں اکاؤنٹس کی درست تشخیص نہیں ہے، جس سے بزنس اکاؤنٹس کو IDL اکاؤنٹس کے طور پر غلط طریقے سے آپریٹ کیا جا سکتا ہے۔
- no-idl فعال نہیں ہے: پروگرام کے تعمیر کے دوران ڈیفالٹ انجیکٹڈ IDL اینٹری پوائنٹ برقرار رکھا گیا، جس سے حملے کا سامنا ہو رہا ہے۔
- اکاؤنٹInfo کے ساتھ پروگرام کے مالک PDA کو اعلان کریں: ڈیولپرز خالی AccountInfo کا استعمال کرتے ہیں تاکہ فنڈ اکاؤنٹ (جیسے خزانہ PDA) کو لے جائیں، جس میں Anchor ٹائپڈ اکاؤنٹ (جیسے Account) کے ساتھ آنے والے discriminator / owner کی تشخیص نہیں ہوتی، جس سے یہ اکاؤنٹ IDL ہدایات کے لحاظ سے IDL اکاؤنٹ سے "تمايز نہیں کیا جا سکتا"۔
- اکاؤنٹ پروگرام کا ہے اور لیمپورٹس رکھتا ہے: owner == یہ پروگرام IDL ہدایات کے لیے اسے کنٹرول کرنے کی پیشگوئی ہے؛ SOL رکھنا ہی اسے خالی کرنے کی قیمت رکھتا ہے۔
اُپر والی شرائط کو پورا کرنے کے بعد، حملہ آور کو صرف دو عام ٹرانزیکشنز کی ضرورت ہوتی ہے: پہلے IdlCreateBuffer کے ذریعے کنٹرولر حاصل کریں، پھر IdlCloseAccount کے ذریعے تمام SOL منتقل کر دیں، اور اس پورے عمل میں ہدف کے پروگرام کو کوئی اجازت دینے کی ضرورت نہیں ہوتی۔
1.4 حملہ کا سلسلہ
انڈر کے اندری تکنیک کے ساتھ، حملہ آور کیسے صرف دو内置 حکمات کا استعمال کرکے ایک عام فنڈ والٹ کو IDL اکاؤنٹ کے طور پر چھپاتا ہے اور اسے خالی کر دیتا ہے، اس کا مرحلہ وار تجزیہ کیا جاتا ہے۔
حملہ کرنے کا جائزہ
مرحلہ 1: IdlCreateBuffer(treasury, signer = attacker)
└─ treasury.controller ==> attacker (کنٹرولر بن جائیں)
مرحلہ 2: IdlCloseAccount(treasury, authority = attacker, dest = attacker)
└─ treasury.lamports ==> attacker (خزانہ خالی کر دیں)
مرحلہ اول: IdlCreateBuffer سے اธรیٹی حاصل کریں
انکر کا اندر کا عمل تقریباً اس طرح ہے:
#[derive(Accounts)]pub struct IdlCreateBuffer {
#[account(zero)] // ← Key: ایک اکاؤنٹ جس کا ڈسکریمینیٹر تمام 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; // سرکاری کے طور پر حملہ سیٹ کریں Ok(())}
#[account(zero)] کا مطلب ہے: ایک ایسا اکاؤنٹ جس کا discriminator صفر ہو اور جس پر پروگرام کا ملکیت ہو، اسے ایک غیر شروع شدہ IDL اکاؤنٹ کے طور پر شروع کرنا۔ اور وولٹ بالکل دونوں شرائط کو پورا کرتا ہے:
والٹ کی حالت
شرائط
پروگرام کی ملکیت
init_if_needed کے بعد مالک کو اس پروگرام کے طور پر سیٹ کر دیا گیا ہے
ڈسکریمنیٹر پوری طرح صفر
AccountInfo ٹائپ کا استعمال کرتے ہوئے، Anchor ڈسکریمنیٹر نہیں لکھتا، ڈیٹا صفر ہے
اس طرح حملہ آور نے وولٹ کو IdlCreateBuffer میں ڈال دیا:
- Anchor، vault کے پہلے 8 بائٹس میں IdlAccount کا ڈسکریمینیٹر لکھتا ہے؛
- حملہ کرنے والے کی عوامی کلید کو authority فیلڈ میں لکھیں۔
اس طرح، وولٹ کو ایک ایسے IdlAccount کے طور پر "دھوکہ دیا" گیا جس کا اثباتیہ حملہ آور ہے — جبکہ اس کے اندر کا SOL ایک سیل بھی نہیں بدلा۔
دوسرا قدم: IdlCloseAccount —— فنڈز خالی کریں
#[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}
اب وولٹ مکمل طور پر تصدیق ہو چکا ہے:
- ڈسکریمنیٹر IdlAccount سے ملتا ہے
- authority فیلڈ = حملہ آور کی عوامی کلید
- has_one = اختیار کی تصدیق ہو گئی
اس لیے وولٹ میں تمام لیمپورٹس (صارفین نے جمع کرائے گئے تمام SOL) قانونی طور پر حملہ آور کے اکاؤنٹ میں منتقل کر دیے گئے، جس سے وولٹ صفر ہو گیا۔
بنیادی وجوہ:
ڈیپازٹ.rs میں ٹائپڈ اینکور اکاؤنٹ کے بجائے AccountInfo کا استعمال کرنا اس خامی کا موت کا سبب ہے:
(1) اکاؤنٹ کے قسم (جیسے اکاؤنٹ) کو شروع کرتے وقت اس ڈیٹا ڈھانچے کے لیے مخصوص 8 بائٹ ڈسکریمینیٹر لکھا جاتا ہے؛
(2) اپنا ڈسکریمینیٹر لکھنے کے بعد، اینکر اسے IdlAccount کے طور پر نہیں سمجھ سکتا (ڈسکریمینیٹر میل نہیں کھاتا)، اس لیے پہلا قدم IdlCreateBuffer ناکام ہو جائے گا اور حملہ کا سلسلہ توڑ دیا جائے گا۔
دو، معاملات کا تجزیہ
یہ ٹیسٹ Anchor 0.31.0 پر بنائے گئے کراس چین برج کنٹریکٹ کے PoC پر مبنی ہے۔ ٹیسٹ ایک حقیقی برج خزانہ (Bridge Treasury) کا خیال رکھتا ہے جس کا مالک برج پروگرام خود ہے، جس میں صارفین کی طرف سے جمع کرائے گئے 1.001281 SOL ہیں۔ حملہ آور کا ویلٹ شروع میں 2 SOL رکھتا ہے اور اس کے پاس کوئی خصوصی اجازت نہیں ہے۔
منصوبہ
عدد / وضاحت
بریج پروگرام
CJutNlr8d3oxdb11ReOLaZd5jPsqUxgwt2mv5e7equtE
خزانہ اکاؤنٹ (Treasury)
DxGkzaMhP5Wy824GhoehErdD6MudfuEPGPwaV2s77FsM
کوائن کا مالک
برج پروگرام (program-owned PDA)
کیوکن کا ابتدائی باقیہ
1.001281 SOL (صارف نے فنڈز جمع کرائے)
ابتدائی کنٹرولر
0x0000...0000 (سب صفر، سیٹ نہیں کیا گیا)
حملہ کرنے والے کی والٹ کا ابتدائی باقی
2.000000 SOL
درکار اختیارات
کوئی اجازت نہیں درکار
ٹریڈنگ کی تعداد
2 ٹریڈز
کیوکن کا آخری بیلنس
0.000000 SOL (خالی کر دیا گیا)
حاصل کرنے والا حملہ آور
+1.001281 SOL
PoC رن سکرین شاٹ (tests/poc-idl-hijack.ts):
دیکھا جا سکتا ہے کہ مرحلہ 1 کا IdlCreateBuffer حملہ آور کو خزانہ کا کنٹرولر (باقیات نہیں بدلی) بناتا ہے؛ مرحلہ 2 کا IdlCloseAccount خزانہ سے 1.001281 SOL کی تمام رقم حملہ آور کی والٹ میں منتقل کر دیتا ہے، جس سے خزانہ کا باقی صفر ہو جاتا ہے۔
درستگی/حفاظت کی تجاویز:
(1) Anchor کا ورژن اپ گریڈ کریں: نئی ترین ورژن میں یہ مسئلہ درست کر دیا گیا ہے (IDL ہدایات IDL اکاؤنٹ اور بزنس اکاؤنٹ کو سختی سے الگ رکھتی ہیں)، کم ورژن Anchor کا استعمال نہ کرنا سب سے براہ راست اور بنیادی تحفظ کا طریقہ ہے۔
(2) بیلڈ کے دوران no-idl کو سکریپٹ کریں: پروڈکشن ماحول کے لیے IDL ہدایات کے انjecشن کو واضح طور پر بند کریں تاکہ اس حمل کے ذریعے سے نکالا جا سکے۔
(3) خالی AccountInfo کے بجائے ٹائپڈ اکاؤنٹ کا استعمال کریں: اکاؤنٹ کے لیے discriminator اور owner چیک کے ساتھ Account / SystemAccount جیسے ٹائپس کا استعمال کریں تاکہ IDL ہدایات اسے غلط طور پر نہ پہچان سکیں۔
(4) کم سے کم پروگرام کے مالکانہ حسابات: فنڈز کے لیے استعمال ہونے والے PDA پر واضح owner / seeds / discriminator پابندیاں نافذ کریں اور اہم ہدایات میں اکاؤنٹ ڈسکریمینیٹر کی تصدیق کریں۔
اختتام
یہ خرابی بنیادی طور پر “فریم ورک کے پوشیدہ حکمات + اکاؤنٹ قسم کی تشخیص کا فقدان” کا مجموعہ ہے۔ ڈویلپرز کو یہ سمجھنا چاہیے کہ Anchor کے ذریعہ ڈالے گئے IDL حکمات حقیقی حملے کا امکان ہیں، فریم ورک کا ورژن اپ گریڈ کریں اور فنڈ اکاؤنٹس پر سٹرانگ ٹائپ کنسترینٹس لاگو کریں، تاکہ اس قسم کے غیر مجاز فنڈز خالی کرنے کے خطرے کو مؤثر طریقے سے ختم کیا جا سکے۔
Beosin ایک اگرے والی بلاکچین سیکورٹی اور ریگولیٹری کمپلائنس ٹیک کمپنی ہے جو پروجیکٹ کے لانچ سے پہلے اسمارٹ کنٹریکٹ سیکورٹی آڈٹ، پروجیکٹ کے عمل کے دوران سیکورٹی خطرات کی نگرانی اور روک تھام، چوری شدہ اثاثوں کی واپسی، ورچوئل اثاثوں کے خلاف منی لانڈرنگ (AML) اور تحقیق و ٹریکنگ پر توجہ دیتی ہے۔ Beosin نے عالمی سطح پر 20 سے زائد ممالک اور علاقوں کے ریگولیٹری اور ایگزیکیوٹو اداروں، 200 سے زائد ورچوئل اثاثہ سروس فراہم کنندگان اور 4500 سے زائد Web3 پروجیکٹس کو "ایک ہی جگہ" بلاکچین کمپلائنس مصنوعات + سیکورٹی سروسز فراہم کی ہیں۔ براہ راست ہمارے گوگل پر مسج کے باکس پر کلک کر کے ہم سے رابطہ کریں۔

