مصنف: جیو جیو
ایڈیٹ: 77
پس منظر
4 ستمبر 2026 کو، مشہور ڈی سینٹرلائزڈ لینڈنگ پلیٹ فارم Notional Finance پر حملہ ہوا، جس کے نتیجے میں تقریباً 1.73 ملین امریکی ڈالر کا نقصان ہوا۔ درج ذیل سلو میگ سیکورٹی ٹیم کی جانب سے اس حملے کا تفصیلی تجزیہ ہے:
پیشگی معلومات
Notional Finance V1 میں، fCash کو ایک ایسے نقد مالکانہ حق کے طور پر سمجھا جا سکتا ہے جس کی ایک مقررہ تاریخ ہوتی ہے۔ ادائیگی کے وقت، کیش ریسیور کو رقم ملے گی اور کیش پےئر ادائیگی کرے گا۔ پروٹوکول دونوں پوزیشنز کو پورٹ فولیو میں ریکارڈ کرتا ہے، اور پھر ایک اکاؤنٹ کی صحت کا جائزہ لینے کے لیے فری مارجین چیک کا استعمال کرتا ہے۔
ERC1155Trade کا safeTransferFrom یہاں اثاثوں کی کتابی رکھائی کا کام کرتا ہے۔ جب داخل کیا گیا اثاثہ کسی کیش ریسیور کا ہو، تو کنٹریکٹ Portfolios.mintfCashPair کو فراہم کرتا ہے، اور اداکار کو ایک ذمہ داری اور وصول کرنے والے کو ایک مساوی حقداری درج کرتا ہے۔ یہ فراہمی ERC1155 ٹرانسفر جیسی لگتی ہے، لیکن نتیجہ ایک fCash جوڑے کی تخلیق ہوتی ہے۔
نیا پوزیشن Portfolio میں لکھنے کے بعد، فری ایسٹ کی حساب کتاب اور جانچ کی ضرورت ہوتی ہے۔ RiskFramework معاہدہ پہلے payer کے fCash فریز کو سائن شدہ int256 میں جمع کرتا ہے، پھر ہر کرنسی کے بیلنس کو ETH میں تبدیل کرکے جمع کرتا ہے۔ منفی عدد ادائیگی کے قابل نقد رقم کو ظاہر کرتا ہے، جبکہ مثبت عدد اکاؤنٹ میں موجود نقد رقم یا مطالبات کو ظاہر کرتا ہے۔ یہ حساب کتاب نتیجہ یہ فیصلہ کرتا ہے کہ ٹریڈ کی اجازت دی جائے گی یا نہیں۔
پوزیشن کے ختم ہونے کے بعد، پورٹ فولیو Escrow کے portfolioSettleCash فنکشن کو کال کرے گا تاکہ ختم ہونے والے fCash کو نقد رہنمائی میں تبدیل کیا جا سکے۔ اکاؤنٹ پھر Escrow سے متعلقہ DAI یا USDC اثاثے نکالنے کے لیے اٹھانے والی فنکشن کا استعمال کرے گا۔
بنیادی وجوہ
اس حملے کا مرکزی خلل Escrow کنٹریکٹ میں استعمال ہونے والے ExchangeRate._convertToETH میں ہے، جہاں ایک کوڈ سائنڈ انٹیجر کے مطلق قیمت کو براہ راست uint128 میں تبدیل کرتا ہے۔

حمل کارکن نے دو ایسے مساوی پیئر کے لیے قرض کے کھاتے بنائے، جن کی رقم 1 اور uint128.max ہیں۔ دونوں قرضوں کو جمع کرنے پر بالکل 2^128 حاصل ہوتا ہے۔ چونکہ خطرہ کی حساب کتاب میں پیئر کی ادائیگی منفی کے طور پر درج کی جاتی ہے، اس لیے Escrow کی convertBalancesToETH میں داخل کیا جانے والا اہم پیرامیٹر -2^128 ہوتا ہے۔
لیکن اس معاہدے میں استعمال کی جانے والی Solidity کا ورژن 0.6.x ہے، اس لیے اس کا مطلق قیمت 2^128 کو uint128 میں تبدیل کرنے پر اس میں اوورفلو ہو جاتا ہے اور 0 بن جاتا ہے، جس کی وجہ سے یہ ذمہ داری ETH کی قیمت میں شامل نہیں ہوتی۔
آخر میں، mintfCashPair فنکشن میں صرف اداکار کا آزاد ضمانتی رقم صفر یا اس سے زیادہ ہونا چاہیے، اس لیے نتیجہ صفر پر اوورفلو ہونے کے بعد یہ چیک پاس ہو جاتا ہے، اور ایک ایسا اکاؤنٹ جس کے پاس مطلوبہ مالیات کو کور کرنے کے لیے کافی اثاثے نہیں ہیں، اب بھی پوزیشن بناسکتا ہے۔
حملہ کے مراحل کا تجزیہ
1. پری ٹریڈ (0xe1589a19…d60a) میں، حملہ آور نے پہلے کئی مددی معاہدے بنائے اور مددی معاہدے کے لیے ERC1155Trade معاہدے کے setApprovalForAll فنکشن کو بلایا؛ اس کے علاوہ، اس نے دو CashMarket کی ادائیگی کی تاریخوں کا پہلے سے ہی جائزہ لیا اور بعد میں درکار تین AssetId پیرامیٹرز کی قیمتیں گھنٹیں۔

2. اس کے بعد، حملہ آور نے ERC1155Trade کنٹریکٹ کے safeTransferFrom فنکشن کو کال کرکے 1 کی مقدار کا fCash جوڑا جاری کیا، جس کے متعلقہ بانڈ اثاثے کا cashGroupId 2 ہے اور اس کی مدت ختم ہونے کی ٹائم اسٹیمپ 1788480000 (4 ستمبر 2026، 8:00 بجے) ہے۔ اس کے دوران، اندر کا فنکشن _upsertAsset from ایڈریس (حملہ آور کنٹریکٹ) اور to ایڈریس (接收 کنٹریکٹ 1) کے لیے ان کے فریضوں اور توقعات شدہ آمدنی کو اپڈیٹ کرتا ہے۔

جب جوڑی کا تخلیق مکمل ہو جائے، تو پورٹ فولیوز فوراً حملہ کنندہ معاہدے کی آزاد ضمانت کا جائزہ لیتے ہیں، اور چونکہ پہلی بار تخلیق کی مقدار بہت کم ہے، اس لیے موجودہ ادائیگی کے اور درستگی کے تحت ETH میں تبدیل کرنے پر اسے صفر کے طور پر گول کر دیا جاتا ہے، اس لیے پہلا جائزہ کامیاب ہوتا ہے۔
3. حملہ آور نے بعد ازاں ERC1155Trade معاہدے کے safeTransferFrom فنکشن کو دوبارہ کال کیا تاکہ uint128.max رقم کا fCash جوڑا جاری کیا جائے، جس کے متعلقہ بانڈ اثاثے کا cashGroupId 2 ہے، لیکن اس کی سرحدی تاریخ کا ٹائم اسٹیمپ 1796256000 (3 دسمبر 2026، 8:00 بجے) ہے۔
یہاں ایک تفصیل ہے کہ حملہ آور نے دو مختلف پتے پر مختلف منقضی ہونے کی تاریخوں والے بانڈ اثاثے جاری کیے۔ اس کا سبب یہ ہے کہ جب from پتے پر ذمہ داری کو اپڈیٹ کیا جاتا ہے، تو اگر بانڈ اثاثہ ایک جیسا ہو تو اسے براہ راست جمع کر لیا جاتا ہے، جس سے جمع کرنے کے دوران اوورفلو کی وجہ سے واپسی (revert) ہو جاتی ہے (کنٹریکٹ نے safeMath لائبریری استعمال کی ہے)۔

4. دوسرے مِنٹنگ کے لیے منبع ایڈریس (حملہ کنندہ معاہدہ) اور مقصد ایڈریس (接收 معاہدہ 2) پر ذمہ داری اور توقع شدہ آمدنی کو اپڈیٹ کرنے کے بعد، mintfCashPair فنکشن freeCollateral فنکشن کو بلاتی ہے تاکہ منبع ایڈریس کا صاف مالیاتی پوزیشن حساب لگائے اور یہ چیک کرے کہ یہ صفر یا اس سے زیادہ ہو۔

اس میں پہلے RiskFramework کنٹریکٹ میں getRequirement فنکشن میں from ایڈریس کے دو بار مینٹ کی گئی ذمہ داریوں کا مجموعہ کیا جائے گا:

نتیجہ نہائی طور پر -2^128 ہوگا، جس کے بعد Escrow کنٹریکٹ کی convertBalancesToETH فنکشن کو بلایا جائے گا تاکہ اس قیمت کو ETH میں تبدیل کیا جا سکے، اور convertBalancesToETH فنکشن بھی ExchangeRate لائبریری کی _convertToETH فنکشن کو کال کرے گی تجزیہ کے لیے:


_convertToETH فنکشن میں جانے پر، یہ پتہ چلتا ہے کہ یہ پہلے balance کا مطلق قیمت لیتا ہے اور پھر uint128 کا استعمال کرتا ہے تاکہ 256 بٹ کو 128 بٹ میں تبدیل کیا جا سکے، جبکہ اوپر مندرجہ ذیل from کی کل قرضہ رقم -2^128 ہے، جس کا مطلق قیمت 2^128 ہوتا ہے، اور جب اسے uint128() میں مضبوط طور پر تبدیل کیا جاتا ہے تو اس کی حد سے زیادہ ہو جانے کی وجہ سے 0 پر اوورفلو ہو جاتا ہے۔ اس کا مطلب یہ ہے کہ پروٹوکول غلط طور پر سمجھتا ہے کہ from ایڈریس کا آزاد ضمانت بیلنس 0 ہے، جس کی وجہ سے mintfCashPair فنکشن کا آخری چیک پاس ہو جاتا ہے۔

5. اس کے بعد، معاہدہ 2 کو وصول کرکے اس نے اپنا پوزیشن دو اور مددگار معاہدوں میں تقسیم کر دیا، جن میں سے دونوں safeTransferFrom اب بھی mintfCashPair فنکشن میں داخل ہوں گے۔ لیکن اس وقت، پےئر دوسری بار مینٹ کرنے والے معاہدہ 2 ہے، جو پہلے مرحلے میں حاصل کیا گیا بہت بڑا توقعاتی آمدنی پوزیشن رکھتا ہے، جس کی خطرہ کی حساب کتاب اسے مثبت حوالہ کے طور پر سمجھتی ہے اور اس طرح ضمانت کی جانچ پڑتال پاس ہو جاتی ہے، جس کی وجہ سے دو مددگار معاہدے کو اس وقت کے بعد نقد میں تبدیل کرنے کے لیے ریسیور fCash حاصل ہوتا ہے۔

6. حملہ آور نے بعد میں ایک دوسری سرکاری منافع کی ٹریڈ شروع کی، جس میں پچھلی ٹریڈ کے دوں ہی پوزیشنز کے متعلقہ سپلیمنٹری کنٹریکٹس کے حوالہ جات بند کر دیے گئے، متعلقہ اثاثوں کے نقد رہنمائی بیلنس میں اضافہ کیا گیا، اور پھر Escrow کنٹریکٹ کے withdraw فنکشن کو کال کرکے اپنا اثاثہ نکال لیا۔
خلاصہ
اس حملے کا اہم نقطہ یہ ہے کہ حملہ آور نے پہلے دو الگ الگ پوزیشنز کا استعمال کرکے پیئر کی کل ذمہ داری کو 2^128 تک مکمل کیا، اور پھر Escrow کو اس ذمہ داری کو ETH میں تبدیل کرنے کے لیے مجبور کیا۔ نوعیت کے تبدیل ہونے کے دوران اوورفلو کے خرابی کا فائدہ اٹھاتے ہوئے نتیجہ صفر پر کٹ گیا، جس کی وجہ سے خطرہ چیک سے گزر گیا۔
慢雾 سیکورٹی ٹیم کی سفارش ہے کہ پراجیکٹ کے ٹیم کو قسم کے تبدیلی سے پہلے رینج چیک ضرور کرنا چاہیے، type(uint128).max سے زیادہ کے نتائج کو فوراً مسترد کر دیا جائے، اس کے علاوہ، تمام مثبت رقم، درستگی کی سکیلنگ اور اثاثوں کے نامزدہ کے حدود پر انتہائی قدر کا ٹیسٹ شامل کیا جانا چاہیے، خاص طور پر uint128.max، uint128.max + 1 اور منفی اقدار کے لیے۔ تبدیلی کے عمل کے لیے Openzeppelin کے SafeCast لائبریری کا استعمال یا حوالہ دیا جا سکتا ہے۔
