Delegatecall به قراردادهای غیرمطمئن ( Delegatecall to Untrusted Callee) ؛ چرا باید با احتیاط استفاده شود؟

در دنیای قراردادهای هوشمند، دستور delegatecall
یکی از قابلیتهای پیشرفته و البته خطرناک Solidity محسوب میشود. این تابع، برخلاف فراخوانیهای معمولی، کد قرارداد مقصد را در بستر (context) قرارداد فراخواننده اجرا میکند. به این معنا که msg.sender
و msg.value
بدون تغییر باقی میمانند، اما کد خارجی میتواند به متغیرهای داخلی قرارداد شما دسترسی داشته باشد و حتی آنها را تغییر دهد.
این ویژگی قدرتمند اگر بهدرستی مدیریت نشود، میتواند دروازهای برای حملات جدی و آسیبپذیریهای امنیتی خطرناک باز کند. بنابراین، استفاده از delegatecall باید کاملاً محدود به قراردادهای مورد اعتماد باشد — مانند ماژولهای داخلی یا کتابخانههایی که خودتان توسعه دادهاید.
چه آسیبهایی ممکن است با استفاده نادرست از Delegatecall رخ دهد؟
1. تصادم متغیرهای وضعیت (State Variable Collisions)
یکی از شایعترین مشکلات، ناسازگاری بین ساختار دادههای ذخیرهسازی در قرارداد فراخوانیکننده و قرارداد مقصد است. چون delegatecall کد را در بستر قرارداد فراخواننده اجرا میکند، اگر چینش متغیرها همراستا نباشد، ممکن است مقادیر نادرستی نوشته یا خوانده شود. نتیجه؟ رفتاری غیرمنتظره و در بدترین حالت، سوءاستفاده توسط مهاجم.
2. اعطای ناخواسته اختیارات (Unintended Authority Granting)
وقتی delegatecall به یک قرارداد دیگر انجام میشود، درواقع کنترل اجرای تابع را به آن قرارداد میدهید. حال اگر آن قرارداد به هر دلیل غیرقابل اعتماد باشد، ممکن است بدون اینکه قصد داشته باشید، تواناییهایی مثل انتقال توکنها، تغییر مالک یا تنظیم دسترسیها را به آن بدهید.
3. خطاهای منطقی و امکان حملات (Logic Errors & Attacks)
انعطافپذیری delegatecall میتواند منجر به بروز خطاهای منطقی شود. از طرف دیگر، اگر بهدرستی محدود و کنترل نشود، ممکن است در تعامل با کدهای خارجی، در معرض حملاتی مانند بازگشت مجدد (reentrancy) قرار بگیرد.
تاثیر امنیتی استفاده از delegatecall به قراردادهای غیرمطمئن
تابع delegatecall
این امکان را فراهم میکند که توابعی از یک قرارداد خارجی، طوری اجرا شوند که انگار بخشی از قرارداد فعلی هستند. حال تصور کنید این قرارداد مقصد، خودش کدی مخرب داشته باشد یا آدرس آن توسط کاربر تزریق شده باشد — در چنین حالتی، عملاً درِ پشت را برای مهاجم باز گذاشتهاید تا به جای شما عمل کند. بهعنوان مثال، مهاجم میتواند با استفاده از یک proxy contract، کنترل دارایی یا منطق قرارداد را بهدست بگیرد.
چه اقداماتی برای افزایش امنیت توصیه میشود؟
-
فقط با قراردادهای شناختهشده و مورد اعتماد از delegatecall استفاده کنید. بهترین کار این است که فقط به کتابخانههایی که خودتان نوشتهاید یا بهطور رسمی اعتبارسنجی شدهاند، اجازه delegate بدهید.
-
در مواردی که آدرس قرارداد از ورودی کاربر دریافت میشود، حتماً آن را اعتبارسنجی کنید. یک راهکار مطمئن، استفاده از لیست سفید (whitelist) است تا فقط قراردادهای تأییدشده امکان فراخوانی داشته باشند.
-
با استفاده از codeauditplus ، در کمترین زمان و با هزینه بسیار معقول، میتوانید آسیب پذیری ها را شناسایی و در نتیجه برای بهبود کد قرارداد اقدام متناسب انجام دهید.
Delegatecall میتواند در توسعه قراردادهای ماژولار یا قابل ارتقا مفید باشد، اما استفاده بیملاحظه از آن، یکی از خطرناکترین اشتباهات امنیتی است. اگر به امنیت پروژه خود اهمیت میدهید، باید با دقت، آگاهی و کنترل مناسب از این قابلیت استفاده کنید. در غیر این صورت، ممکن است با آسیبپذیریهایی روبهرو شوید که جبران آنها بسیار سخت و پرهزینه خواهد بود.
راهکار ما:
- ثبت درخواست ممیزی
- مشاهده راهنمای چگونگی ثبت درخواست ممیزی در آپارات
- مشاهده راهنمای چگونگی ثبت درخواست ممیزی در یوتیوب
منابع
https://swcregistry.io/docs/SWC-112/