Follow Us
Facebooktwitteryoutube
YouTube
Promo
banner
Promo
banner

توصیه های امنیتی قرارداد هوشمند Ethereum

وبلاگ 1NewsD DevelopersEnterpriseBlockchain ExplainedEvent ها و کنفرانس ها Pressخبرنامه ها

Contents

مشترک شدن در خبرنامه ما.

آدرس ایمیل

ما به حریم خصوصی شما احترام می گذاریم

صفحه اصلی وبلاگ توسعه Blockchain

توصیه های امنیتی قرارداد هوشمند Ethereum

از چگونگی مدیریت تماس های خارجی به برنامه های تعهد ، در اینجا 10+ الگو هوشمند امنیتی قرارداد وجود دارد که باید هنگام ساخت Ethereum دنبال کنید. توسط ConsenSys 10 ژوئیه 2020 منتشر شده در 10 ژوئیه 2020

توصیه های امنیتی قرارداد هوشمند Ethereum

همانطور که در ذهنیت هوشمند امنیت قرارداد قرار دادیم ، یک توسعه دهنده هوشیار Ethereum همیشه پنج اصل را در ذهن خود نگه می دارد:

  • برای شکست آماده شوید
  • با دقت رول کنید
  • قراردادها را ساده نگه دارید
  • به روز باشید
  • از خصوصیات خاص EVM آگاه باشید

در این پست ، ما به خصوصیات EVM فرو خواهیم رفت و لیستی از الگوهایی را که باید هنگام ایجاد هر سیستم قرارداد هوشمند در Ethereum دنبال کنید ، مرور خواهیم کرد. این قطعه در درجه اول برای توسعه دهندگان میانی Ethereum است. اگر هنوز در مراحل اولیه اکتشاف هستید ، برنامه توسعه بلاکچین درخواستی آکادمی ConsenSys را بررسی کنید. 

خوب ، بیایید غواصی کنیم.

تماس های خارجی

هنگام برقراری تماس های خارجی احتیاط کنید

تماس با قراردادهای هوشمند نامطمئن می تواند خطرات یا خطاهای غیرمنتظره متعددی را ایجاد کند. تماس های خارجی ممکن است کد مخربی را در آن قرارداد یا هر قرارداد دیگری که به آن بستگی دارد ، اجرا کنند. بنابراین ، با هر تماس خارجی به عنوان یک خطر بالقوه امنیتی برخورد کنید. درصورتی که حذف تماس های خارجی امکان پذیر یا نامطلوب است ، برای به حداقل رساندن خطر از توصیه های موجود در ادامه این بخش استفاده کنید.

قراردادهای غیرقابل اعتماد را علامت گذاری کنید

هنگام تعامل با قراردادهای خارجی ، متغیرها ، روش ها و رابط های قرارداد خود را به گونه ای نامگذاری کنید که روشن شود تعامل با آنها به طور بالقوه ناامن است. این مربوط به عملکردهای شما است که قراردادهای خارجی را می خوانند.

// بد بانک.withdraw (100)؛ // مشخص نیست تابع مورد اعتماد یا غیر قابل اعتماد makeWithdrawal (مقدار uint) {// آیا مشخص نیست که این تابع به طور بالقوه ناامن Bank.withdraw (مقدار) است. } // خوب UntrustedBank.withdraw (100)؛ // تماس خارجی غیر معتمد TrustedBank.withdraw (100)؛ // قرارداد بانکی خارجی اما قابل اعتماد که توسط تابع XYZ Corp makeUntrustedWithdrawal (مقدار uint) {UntrustedBank.withdraw (مقدار)؛ } زبان کد: PHP (php)

پس از تماس های خارجی از تغییر حالت خودداری کنید


چه با استفاده از تماس های خام (از فرم someAddress.call ()) یا تماس های قراردادی (از فرم ExternalContract.someMethod ()) ، فرض کنید کد مخرب ممکن است اجرا شود. حتی اگر ExternalContract مخرب نباشد ، کد مخرب با هر قراردادی که بخواند قابل اجرا است.

یک خطر خاص این است که کد مخرب ممکن است جریان کنترل را ربوده و منجر به آسیب پذیری ناشی از ورود مجدد شود. (دیدن ورود مجدد کالا برای بحث کاملتر در مورد این مشکل).

اگر در حال برقراری تماس با یک قرارداد خارجی غیرقابل اعتماد هستید ، از تغییرات وضعیت پس از تماس خودداری کنید. این الگو گاهی اوقات نیز نامیده می شود الگوی بررسی اثرات-فعل و انفعالات.

دیدن SWC-107

از انتقال () یا ارسال () استفاده نکنید.

.انتقال () و ارسال () دقیقاً 2،300 بنزین را به گیرنده انتقال دهید. هدف از این کمک هزینه گازدار رمزگذاری شده جلوگیری از این بود آسیب پذیری های ورود به سیستم, اما این تنها با فرض ثابت بودن هزینه های گاز منطقی است. EIP 1884, که بخشی از هارد فورک استانبول بود ، هزینه گاز عملیات SLOAD را افزایش داد. این باعث شد عملکرد عملکرد قرارداد بیش از 2300 گاز هزینه کند. توصیه می کنیم استفاده از.transfer () و.send () را متوقف کرده و در عوض use.call () را استفاده کنید.

// bad contract Vulnerable {عملکرد برداشت (مقدار uint256) خارجی {// این 2300 گاز را به جلو هدایت می کند ، که در صورت عقد قرارداد گیرنده // ممکن است کافی نباشد و هزینه های گاز تغییر کند. msg.sender.transfer (مقدار)؛ }} // قرارداد خوب رفع {تابع برداشت (مقدار uint256) خارجی {// این همه گاز موجود را ارسال می کند. حتما مقدار برگشتی را بررسی کنید! (موفقیت bool ،) = msg.sender.call.value (مقدار) ("") ایجاب می کند (موفقیت, "انتقال ناموفق بود.") }} زبان کد: JavaScript (javascript)

توجه داشته باشید که.call () هیچ کاری برای کاهش حملات ورودی مجدد انجام نمی دهد ، بنابراین باید اقدامات احتیاطی دیگری انجام شود. برای جلوگیری از حملات ورود مجدد ، از الگوی بررسی-اثرات-فعل و انفعالات.

در تماسهای خارجی خطاها را کنترل کنید

Solidid روش های تماس سطح پایین را ارائه می دهد که روی آدرس های خام کار می کنند: address.call ()، address.callcode ()، address.delegatecall () و address.send (). این روش های سطح پایین هرگز استثنائی را به وجود نمی آورند ، اما اگر تماس با یک استثنا مواجه شود نادرست برمی گردد. از طرف دیگر ، تماس های قراردادی (به عنوان مثال ، ExternalContract.doSomething ()) به طور خودکار پرتاب را گسترش می دهد (به عنوان مثال ، ExternalContract.doSomething () اگر doSomething () پرتاب کند نیز پرتاب می شود).

اگر استفاده از روش های تماس سطح پایین را انتخاب کردید ، با بررسی مقدار بازگشت مقدار اطمینان از عدم موفقیت در تماس را کنترل کنید..

// bad someAddress.send (55)؛ someAddress.call.value (55) ("") // این دو برابر خطرناک است ، زیرا تمام گازهای باقیمانده را هدایت می کند و برخی از address.call.value (100) (bytes4 (sha3 ("سپرده()"))) // اگر سپرده استثنائی را ایجاد کند ، فراخوان خام () فقط نادرست برمی گردد و معامله برگشت داده نمی شود // خوب (موفقیت بول ،) = someAddress.call.value (55) ("") if (! موفقیت) {// رسیدگی به کد خرابی} ExternalContract (someAddress) .deposit.value (100) ()؛ زبان کد: JavaScript (javascript)

دیدن SWC-104

برای تماس های خارجی فشار بیشتری را فشار دهید

تماس های خارجی می توانند به طور تصادفی یا عمدی از کار بیفتند. برای به حداقل رساندن آسیب های ناشی از چنین خرابی ها ، معمولاً بهتر است هر تماس خارجی را در معامله خاص خود که می تواند توسط گیرنده تماس آغاز شود ، جدا کنید. این امر به ویژه برای پرداخت ها بسیار مهم است ، در جایی که بهتر است به کاربران اجازه دهیم وجوه خود را برداشت کنند تا اینکه بطور خودکار وجوه را به آنها بکشند. (این نیز باعث کاهش احتمال مشکلات محدودیت گاز.) از ترکیب چندین انتقال اتر در یک معامله جداً خودداری کنید.

// حراج قرارداد بد {آدرس بالاترین پیشنهاد دهنده؛ uint aboveBid؛ پیشنهاد عملکرد () قابل پرداخت {نیاز (msg.value) >= بالاترین پیشنهاد)؛ if (بالاترین پیشنهاد دهنده! = آدرس (0)) {(موفقیت bool ،) = largestBidder.call.value (بالاترین پیشنهاد) ("") نیاز (موفقیت) // اگر این تماس به طور مداوم با شکست روبرو شود ، هیچ کس دیگری نمی تواند پیشنهاد دهد} largestBidder = msg.sender؛ aboveBid = msg.value؛ }} // حراج قرارداد خوب {آدرس largestBidder؛ uint aboveBid؛ نقشه برداری (آدرس => uint) بازپرداخت پیشنهاد عملکرد () قابل پرداخت خارجی {نیاز (msg.value) >= بالاترین پیشنهاد)؛ اگر (بالاترین پیشنهاد دهنده! = آدرس (0)) {بازپرداخت [بالاترین پیشنهاد دهنده] + = بالاترین پیشنهاد؛ // ضبط بازپرداختی را که این کاربر می تواند ادعا کند} largestBidder = msg.sender؛ maximumBid = msg.value؛ } function removeRefund () خارجی {uint refund = بازپرداخت [بازپرداخت [.. ارسال کننده]؛ بازپرداختها [msg.sender] = 0؛ (موفقیت bool ،) = msg.sender.call.value (بازپرداخت) ("") نیاز (موفقیت) }} زبان کد: JavaScript (javascript)

دیدن SWC-128

تماس با کد غیرقابل اعتماد را انجام ندهید

عملکرد delegatecall توابعی را از سایر قراردادها فراخوانی می کند که گویی متعلق به قرارداد تماس گیرنده است. بنابراین تماس گیرنده ممکن است وضعیت آدرس تماس را تغییر دهد. این ممکن است ناامن باشد. مثالی در زیر نشان می دهد که چگونه استفاده از فراخوانی delege می تواند منجر به از بین رفتن قرارداد و از بین رفتن تعادل آن شود.

contract Destructor {تابع doWork () خارجی {selfdestruct (0)؛ }} contract Worker {function doWork (آدرس _internalWorker) عمومی {// unsafe _internalWorker.delegatecall (bytes4 (keccak256 ("doWork ()"))) }} زبان کد: JavaScript (javascript)

اگر Worker.doWork () با آدرس قرارداد مستقر Destructor به عنوان یک استدلال فراخوانی شود ، قرارداد Worker خود تخریب می شود. تفویض اعدام فقط به قراردادهای قابل اعتماد ، و هرگز به آدرس ارائه شده توسط کاربر.

هشدار

تصور نکنید که قراردادها با تعادل صفر ایجاد شده اند. یک مهاجم می تواند قبل از ایجاد قرارداد ، اتر را به آدرس آن بفرستد. در قراردادها نباید فرض شود که حالت اولیه آن حاوی تعادل صفر باشد. دیدن شماره 61 برای جزئیات بیشتر.

دیدن SWC-112

به یاد داشته باشید که اتر را می توان به زور به یک حساب ارسال کرد

مراقب باشید که از رمزگذاری یک نامعتبر که تعادل قرارداد را دقیقاً بررسی می کند ، مراقب باشید.

یک مهاجم می تواند به زور اتر را به هر حسابی بفرستد. نمی توان جلوی این را گرفت (حتی با عملکرد برگشتی که برگشت انجام می دهد ()).

مهاجم می تواند این کار را با ایجاد یک قرارداد ، تأمین بودجه آن با 1 wei و استناد به selfdestruction (viktimaddress) انجام دهد. در viktimaddress هیچ کدی فراخوانی نمی شود ، بنابراین نمی توان از آن جلوگیری کرد. این برای پاداش بلوک که به آدرس ماینر ارسال می شود ، که می تواند هر آدرس دلخواهی باشد ، نیز صادق است.

همچنین ، از آنجا که آدرس های قرارداد می توانند از قبل محاسبه شوند ، می توان اتر را قبل از استقرار قرارداد به یک آدرس ارسال کرد.

دیدن SWC-132

به یاد داشته باشید که داده های زنجیره ای عمومی هستند

بسیاری از برنامه ها برای کار کردن ، نیاز دارند که داده های ارسالی تا برخی از زمان ها خصوصی باشند. بازی ها (به عنوان مثال قیچی های سنگی و کاغذی) و مکانیزم های حراج (به عنوان مثال مناقصه بسته شده) حراج های ویکی) دو دسته عمده از نمونه ها هستند. اگر در حال ساخت برنامه ای هستید که در آن حریم خصوصی مورد توجه است ، اطمینان حاصل کنید که کاربران نیازی به انتشار زودهنگام اطلاعات ندارند. بهترین استراتژی استفاده از آن است طرح های تعهد با مراحل جداگانه: ابتدا با استفاده از هش مقادیر و در مرحله بعد مقادیر را آشکار کنید.

مثال ها:

  • در قیچی کاغذ سنگ ، هر دو بازیکن را ملزم کنید که ابتدا هش حرکت مورد نظر خود را ارسال کنند ، سپس هر دو بازیکن را ملزم به ارسال حرکت خود کنید. اگر حرکت ارسالی با هش مطابقت ندارد آن را بیرون بیاندازید.
  • در یک حراجی ، از بازیکنان بخواهید که یک هش از ارزش پیشنهاد خود را در مرحله اولیه (همراه با سپرده بیشتر از ارزش پیشنهاد خود) ارسال کنند ، و سپس ارزش پیشنهاد حراج خود را در مرحله دوم ارائه دهند.
  • هنگام ایجاد برنامه ای که به یک مولد اعداد تصادفی بستگی دارد ، سفارش باید همیشه باشد (1) بازیکن حرکت را ارسال می کند ، (2) تعداد تصادفی ایجاد شده ، (3) بازیکن پرداخت می شود. بسیاری از افراد به طور فعال در حال تحقیق درباره مولدهای اعداد تصادفی هستند. بهترین راه حل های موجود در کلاس شامل عناوین بلوک بیت کوین است (تأیید شده از طریق http://btcrelay.org) ، طرح های هش مرتکب-آشکار (به عنوان مثال یک طرف یک عدد تولید می کند ، هش خود را برای “تعهد” به مقدار منتشر می کند ، و سپس مقدار را بعدا نشان می دهد) و RANDAO. از آنجا که Ethereum یک پروتکل قطعی است ، شما نمی توانید از هر متغیری در پروتکل به عنوان یک عدد تصادفی غیر قابل پیش بینی استفاده کنید. همچنین توجه داشته باشید که ماینرها تا حدی کنترل مقدار () block.blockhash را کنترل می کنند*.

مواظب باشید که برخی از شرکت کنندگان ممکن است “آفلاین شوند” و دیگر برنگردند

فرایندهای بازپرداخت یا ادعا را به شخص خاصی وابسته نکنید که اقدام خاصی را انجام داده باشد و راه دیگری برای دریافت وجه نداشته باشد. به عنوان مثال ، در یک بازی قیچی سنگی ، یک اشتباه رایج این است که تا زمانی که هر دو بازیکن حرکت خود را انجام ندهند ، پرداختی انجام نمی دهید. با این حال ، یک بازیکن مخرب می تواند با ناراحتی دیگری هرگز حرکت خود را “ناراحت” کند – در حقیقت ، اگر بازیکن بازیکن حرکت آشکار شده بازیکن دیگر را ببیند و تشخیص دهد که آنها باخته اند ، هیچ دلیلی برای ارسال حرکت خود ندارند. این مسئله همچنین ممکن است در زمینه حل و فصل کانال های دولتی بوجود آید. هنگامی که چنین شرایطی مطرح است ، (1) راهی برای دور زدن شرکت کنندگان غیر شرکت کننده ، شاید از طریق یک محدودیت زمانی ارائه می شود ، و (2) در نظر گرفتن یک انگیزه اقتصادی اضافی برای شرکت کنندگان برای ارسال اطلاعات در تمام شرایطی که در آن قرار دارند قرار است چنین کاری انجام شود.

مراقب نفی منفی ترین عدد صحیح امضا شده باشید

Solidid انواع مختلفی را برای کار با عدد صحیح امضا شده فراهم می کند. مانند اکثر زبانهای برنامه نویسی ، در Solidid یک عدد صحیح امضا شده با N بیت می تواند مقادیری از -2 ^ (N-1) تا 2 ^ (N-1) -1 را نشان دهد. این بدان معناست که معادل مثبتی برای MIN_INT وجود ندارد. منفی با یافتن مکمل این دو عدد اجرا می شود ، بنابراین نفی منفی ترین عدد در نتیجه همان تعداد است. این برای همه انواع صحیح امضا شده در Solidity (int8، int16،…، int256) صادق است..

contract Negation {function negate8 (int8 _i) بازده خالص عمومی (int8) {return -_i؛ } function negate16 (int16 _i) بازده خالص عمومی (int16) {return -_i؛ } int8 public a = negate8 (-128)؛ // -128 int16 public b = negate16 (-128)؛ // 128 int16 public c = negate16 (-32768)؛ // -32768} زبان کد: PHP (php)

یکی از راه های کنترل این مسئله این است که مقدار یک متغیر را قبل از نفی بررسی کنید و اگر برابر MIN_INT است پرتاب کنید. گزینه دیگر این است که اطمینان حاصل کنید منفی ترین عدد با استفاده از نوعی با ظرفیت بالاتر (مثلا int32 به جای int16) هرگز حاصل نمی شود.

مسئله مشابه انواع int وقتی رخ می دهد که MIN_INT ضرب یا تقسیم بر 1 شود.

آیا کد بلاکچین شما امن است? 

امیدواریم این توصیه ها مفید واقع شده باشد. اگر شما و تیم خود در حال آماده سازی برای راه اندازی یا حتی در ابتدای چرخه عمر هستید و نیاز به عقلانیت قراردادهای هوشمند خود دارید ، لطفا در صورت تمایل با تیم مهندسین امنیت ما در ConsenSys Diligence تماس بگیرید. ما اینجا هستیم تا به شما کمک کنیم برنامه های Ethereum خود را با اطمینان 100٪ راه اندازی و نگه دارید. 

یک چک لکه امنیتی را رزرو کنید

با تیم ما از کارشناسان امنیت بلاکچین یک مرور یک روزه رزرو کنید. Books YourS Today SecuritySmart Contracts Newsletter برای آخرین اخبار Ethereum ، راه حل های سازمانی ، منابع توسعه دهنده و موارد دیگر ، در خبرنامه ما مشترک شوید. آدرس ایمیل محتوای اختصاصیچگونه یک محصول بلاکچین موفق بسازیموبینار

چگونه یک محصول بلاکچین موفق بسازیم

نحوه تنظیم و اجرای گره Ethereumوبینار

نحوه تنظیم و اجرای گره Ethereum

چگونه API Ethereum خود را بسازیموبینار

چگونه API Ethereum خود را بسازیم

چگونه یک نشانه اجتماعی ایجاد کنیموبینار

چگونه یک نشانه اجتماعی ایجاد کنیم

استفاده از ابزارهای امنیتی در توسعه قرارداد هوشمندوبینار

استفاده از ابزارهای امنیتی در توسعه قرارداد هوشمند

آینده دارایی های دیجیتال مالی و DeFiوبینار

آینده مالی: دارایی های دیجیتال و DeFi

Mike Owergreen Administrator
Sorry! The Author has not filled his profile.
follow me
Adblock
detector