امنیت قرارداد هوشمند
آخرین ویرایش: @mahdigachloo33(opens in a new tab), ۲۵ دی ۱۴۰۳
قراردادهای هوشمند بسیار انعطافپذیر هستند و می توانند مقادیر زیادی از ارزش و داده را کنترل کنند، در حالی که منطق تغییرناپذیر مبتنی بر کد مستقر در بلاک چین را اجرا می کنند. این یک اکوسیستم پر جنب و جوش از برنامه های کاربردی بی نیاز از اعتماد و غیرمتمرکز ایجاد کرده است که مزایای زیادی را نسبت به سیستم های قدیمی ارائه می دهد. آنها همچنین فرصتهایی را برای مهاجمانی که به دنبال سودجویی از طریق سوءاستفاده از آسیبپذیریها در قراردادهای هوشمند هستند، نشان میدهند.
بلاک چین های عمومی، مانند اتریوم، مسئله ایمنسازی قراردادهای هوشمند را پیچیدهتر و سختتر می کند. معمولا پس از استقرار کد قرارداد در شبکه، نمیتوان آن را به منظور رفع نقص های امنیتی را تغییر داد، در حالی که ردیابی دارایی های دزدیده شده از قراردادهای هوشمند بسیار دشوار است و عمدتاً به دلیل تغییر ناپذیری قابل بازیابی نیستند.
اگرچه اعداد و ارقام متفاوت است، تخمین زده می شود که کل ارزش سرقت شده یا از دست رفته به دلیل نقص امنیتی در قراردادهای هوشمند به راحتی بیش از یک میلیارد دلار است. این شامل حوادث پرمخاطب، مانند هک DAO(opens in a new tab) (3.6M اتریوم دزدیده شده، به ارزش بیش از 1 میلیارد دلار در قیمت های امروزی)، هک کیف پول چند علامتی Parity(opens in a new tab) (30 میلیون دلار از دست هکرها) و مشکل کیف پول منجمد شده(opens in a new tab) (بیش از 300 میلیون دلار ETH برای همیشه قفل شده است).
مسائل ذکر شده، توسعه دهندگان را مجبور میکند تا تلاش کنند قراردادهای هوشمند ایمن، نبوغ آمیز و منعطف بسازند. امنیت قراردادهای هوشمند یک تجارت جدی است و هر توسعهدهندهای باید آن را یاد بگیرد. این راهنما ملاحظات امنیتی برای توسعه دهندگان اتریوم را پوشش می دهد و منابعی را برای بهبود امنیت قراردادهای هوشمند بررسی می کند.
پیشنیازها
قبل از پرداختن به امنیت، مطمئن شوید که با مبانی توسعه قرارداد هوشمند آشنا هستید.
دستورالعمل هایی برای ساخت قراردادهای هوشمند ایمن در اتریوم
1. کنترل های دسترسی طراحی مناسب
در قراردادهای هوشمند، عملکردهایی که public
یا external
علامتگذاری شدهاند، میتوانند توسط هر حساب تحت مالکیت خارجی (EOA) یا حساب قراردادی فراخوانی شوند. اگر میخواهید دیگران با قرارداد شما در تعامل باشند، مشخص کردن نمای عمومی برای عملکردها ضروری است. با این حال، عملکردهایی که با private
علامتگذاری شدهاند، فقط توسط توابع داخل قرارداد هوشمند فراخوانی میشوند و در حسابهای خارجی مورد استفاده قرار نمی گیرند. دادن دسترسی به هر یک از شرکتکنندگان شبکه به توابع قرارداد میتواند باعث ایجاد مشکلاتی شود، بهویژه اگر به این معنی باشد که هر کسی بتواند عملیات حساس را انجام دهد (به عنوان مثال، استخراج توکنهای جدید).
برای جلوگیری از استفاده غیرمجاز از توابع قرارداد هوشمند، لازم است کنترل های دسترسی ایمن را اجرا کنید. مکانیسمهای کنترل دسترسی، توانایی استفاده از عملکردهای خاص در یک قرارداد هوشمند را به نهادهای تایید شده، مانند حسابهای مسئول مدیریت قرارداد، محدود میکند. الگوی مالکیت و کنترل مبتنی بر نقش دو الگوی مفید برای اجرای کنترل دسترسی در قراردادهای هوشمند هستند:
الگوی قابل مالکیت
در الگویل قابل مالکیت، یک آدرس به عنوان "مالک" قرارداد در طول فرآیند ایجاد قرارداد تنظیم می شود. به توابع محافظت شده یک اصلاحکننده OnlyOwner
اختصاص داده میشود، که تضمین میکند قرارداد قبل از اجرای تابع، هویت آدرس تماس را تأیید میکند. تماسهای توابع محافظتشده از آدرسهای دیگر به غیر از مالک قرارداد، همیشه برمیگردند و از دسترسی ناخواسته جلوگیری میکنند.
کنترل دسترسی مبتنی بر نقش
ثبت یک آدرس واحد بهعنوان Owner
در یک قرارداد هوشمند، خطر تمرکز را معرفی میکند و نشاندهنده یک نقطه شکست واحد است. اگر کلیدهای حساب مالک به خطر بیفتد، مهاجمان می توانند به قرارداد مالکیت حمله کنند. به همین دلیل است که استفاده از الگوی کنترل دسترسی مبتنی بر نقش با چندین حساب اداری ممکن است گزینه بهتری باشد.
در کنترل دسترسی مبتنی بر نقش، دسترسی به عملکردهای حساس بین مجموعه ای از شرکت کنندگان قابل اعتماد توزیع می شود. به عنوان مثال، یک حساب ممکن است مسئول ضرب توکن ها باشد، در حالی که حساب دیگری ارتقاء داده یا قرارداد را متوقف می کند. غیرمتمرکز کردن کنترل دسترسی به این روش، نقاط منفرد شکست را از بین می برد و مفروضات اعتماد را برای کاربران کاهش می دهد.
استفاده از کیف پولهای چند امضایی
روش دیگر برای اجرای کنترل دسترسی ایمن استفاده از حساب چند امضایی برای مدیریت قرارداد است. برخلاف یک EOA معمولی، حسابهای چند امضایی متعلق به چندین نهاد هستند و برای انجام تراکنشها به امضای حداقل تعداد حسابها (مثلاً 3 از 5) نیاز دارند.
استفاده از مالتی سیگ برای کنترل دسترسی، یک لایه امنیتی اضافی را معرفی میکند زیرا اقدامات روی قرارداد هدف مستلزم رضایت چندین طرف است. این مورد به ویژه در صورتی مفید است که استفاده از الگوی اونبل (Ownable) ضروری باشد، زیرا دستکاری عملکردهای حساس قرارداد برای اهداف مخرب را برای مهاجم دشوارتر میکند.
2. برای محافظت از عملیات قرارداد از عبارات require() و assert() و revert() استفاده کنید
همانطور که گفته شد، هر کسی میتواند توابع عمومی را در قرارداد هوشمند شما پس از استقرار در بلاکچین فراخوانی کند. از آنجایی که نمیتوانید از قبل بدانید حسابهای خارجی چگونه با یک قرارداد تعامل خواهند داشت، بهتراست که قبل از استقرار، حفاظتهای داخلی در برابر عملیات مشکلساز را اجرا کنید. میتوانید با استفاده از دستورات require()
، assert()
و revert()
رفتار صحیح را در قراردادهای هوشمند برای راهاندازی استثناها و برگرداندن تغییرات حالت اعمال کنید، در صورتی که اجرا نتواند الزامات خاصی را برآورده کند.
require()
: دستورها require
در شروع توابع تعریف میشوند و اطمینان میدهند که شرایط از پیش تعریف شده قبل از اجرای تابع فراخوانی شده برآورده میشوند. یک عبارت require
را میتوان برای اعتبارسنجی ورودی های کاربر، بررسی متغیرهای حالت، یا احراز هویت حساب فراخوان قبل از پیشرفت با یک تابع استفاده کرد.
assert()
: دستور assert()
برای شناسایی خطاهای داخلی و بررسی نقض "invariants" در کد شما استفاده می شود. یک invariant یک ادعای منطقی در مورد وضعیت قرارداد است که باید برای اجرای همه توابع صادق باشد. یک مثال ثابت، حداکثر عرضه یا موجودی یک قرارداد توکن است. استفاده از assert()
تضمین میکند که قرارداد شما هرگز به یک وضعیت آسیبپذیر نمیرسد، و در صورت رسیدن، همه تغییرات در متغیرهای حالت برگردانده میشوند.
revert()
: دستور revert()
را می توان در یک عبارت if-else استفاده کرد که در صورت عدم رعایت شرایط مورد نیاز، یک استثنا ایجاد می کند. قرارداد نمونه زیر از revert()
برای محافظت از اجرای توابع استفاده می کند:
1pragma solidity ^0.8.4;23contract VendingMachine {4 address owner;5 error Unauthorized();6 function buy(uint amount) public payable {7 if (amount > msg.value / 2 ether)8 revert("Not enough Ether provided.");9 // Perform the purchase.10 }11 function withdraw() public {12 if (msg.sender != owner)13 revert Unauthorized();1415 payable(msg.sender).transfer(address(this).balance);16 }17}نمایش همه
3. قراردادهای هوشمند را تست کنید و صحت کد را تأیید کنید
تغییرناپذیری کدهای در حال اجرا در ماشین مجازی اتریوم به این معنی است که قراردادهای هوشمند سطح بالاتری از ارزیابی کیفیت را در مرحله توسعه می طلبد. تست قرارداد خود به طور گسترده و مشاهده آن برای نتایج غیرمنتظره امنیت را تا حد زیادی بهبود میبخشد و در دراز مدت از کاربران شما محافظت میکند.
روش معمول نوشتن تستهای واحد کوچک با استفاده از دادههای ساختگی است که انتظار میرود قرارداد را از کاربران دریافت کند. آزمایش Unit برای آزمایش عملکرد عملکردهای خاص و اطمینان از اینکه قرارداد هوشمند مطابق انتظار عمل می کند خوب است.
متأسفانه، تست واحد برای بهبود امنیت قراردادهای هوشمند زمانی که به صورت مجزا مورد استفاده قرار میگیرد، حداقل مؤثر است. یک تست واحد ممکن است ثابت کند که یک تابع برای دادههای ساختگی به درستی اجرا میشود، اما تستهای واحد فقط به اندازه تستهای نوشته شده مؤثر هستند. این امر تشخیص موارد لبه از دست رفته و آسیب پذیری هایی را که می تواند ایمنی قرارداد هوشمند شما را به هم بزند، دشوار می کند.
یک رویکرد بهتر ترکیب آزمایش واحد با آزمایش مبتنی بر ویژگی است که با استفاده از تحلیل استاتیک و پویا انجام میشود. تجزیه و تحلیل استاتیک بر نمایشهای سطح پایین، مانند گرافهای جریان کنترل(opens in a new tab) ودرختهای نحو انتزاعی(opens in a new tab) برای تجزیه و تحلیل وضعیتهای قابل دسترسی برنامه و مسیرهای اجرا. در همین حال، تکنیکهای تحلیل پویا، مانند فازی قرارداد هوشمند(opens in a new tab)، قرارداد را اجرا میکنند. کد با مقادیر ورودی تصادفی برای شناسایی عملیاتی که ویژگیهای امنیتی را نقض میکند.
تأیید رسمی تکنیک دیگری برای تأیید ویژگیهای امنیتی در قراردادهای هوشمند است. برخلاف تستهای معمولی، تأیید رسمی میتواند به طور قطعی عدم وجود خطا در یک قرارداد هوشمند را ثابت کند. این امر با ایجاد یک مشخصات رسمی که ویژگیهای امنیتی مورد نظر را نشان میدهد و اثبات اینکه مدل رسمی قراردادها به این مشخصات پایبند است، به دست میآید.
4. درخواست بررسی مستقل کد خود را داشته باشید
پس از تست قرارداد خود، بهتر است از دیگران بخواهید که کد منبع را برای هرگونه مشکل امنیتی بررسی کنند. تست تمام ایرادات یک قرارداد هوشمند را آشکار نمیکند، اما دریافت یک بررسی مستقل امکان شناسایی آسیب پذیریها را افزایش میدهد.
حسابرسیهای امنیتی
راهاندازی آدیت قرارداد هوشمند یکی از راههای انجام بررسی مستقل کد است. حسابرسان یا آدیتورها نقش مهمی در حصول اطمینان از ایمن بودن قراردادهای هوشمند و عاری از نقص کیفی و خطاهای طراحی دارند.
با وجود همهی این موارد، شما نباید با حسابرسی امنیتی مانند پاسخی برای تمام مشکلات برخورد کنید. آدیت قراردادهای هوشمند هر اشکالی را شناسایی نمیکند و عمدتاً برای ارائه یک سری بررسی اضافی طراحی شده است که میتواند به شناسایی مشکلاتی که توسعه دهندگان در طول توسعه و تست اولیه از قلم انداختهاند کمک کند. همچنین باید بهترین روشها را برای کار با حسابرسان، مانند مستندسازی کد به درستی و افزودن نظرات درون خطی، دنبال کنید تا از مزایای حسابرسی قرارداد هوشمند به حداکثر برسانید.
- نکات حسابرسی قرارداد هوشمند و amp; ترفندها(opens in a new tab) - @tinchoabbate
- از حسابرسی خود حداکثر استفاده را ببرید(opens in a new tab)
پاداشهای باگ
راه اندازی یک برنامه باگ بانتی روش دیگری برای اجرای بررسی کدهای خارجی است. جایزه باگ یک پاداش مالی است که به افرادی (معمولاً هکرهای کلاه سفید) که آسیبپذیریهای یک برنامه را کشف میکنند، داده میشود.
هنگامی که به درستی استفاده میشود، پاداشهای باگ به اعضای جامعه هکر انگیزه میدهد تا کد شما را از نظر نقصهای مهم بررسی کنند. یک مثال واقعی "باگ پول بینهایت" است که به مهاجم اجازه میدهد مقدار نامحدودی اتر را در آپتیمیزم(opens in a new tab) ایجاد کند، یک < یک پروتکل لایه که روی اتریوم اجرا میشود. خوشبختانه، یک هکر whitehat این نقص را کشف کرد(opens in a new tab) و به تیم اطلاع داد، کسب پرداختی بزرگ در این فرآیند انجام شد(opens in a new tab) بحرانی-اشکال-.
یک استراتژی مفید این است که پرداخت برنامه پاداش اشکال را متناسب با مقدار وجوه مورد نظر تنظیم کنید. این رویکرد بهعنوان «اشکال مقیاسگذاری(opens in a new tab) توصیف میشود. انگیزههای مالی برای افراد برای افشای مسئولانه آسیب پذیریها به جای سوء استفاده از آنها را ایجاد میکند.
5. در هنگام توسعه قراردادهای هوشمند بهترین رویه های موجود را دنبال کنید
وجود آدیت و پاداش باگ مسئولیت شما را برای نوشتن کد با کیفیت بالا توجیه نمیکند. امنیت قرارداد هوشمند خوب با فرآیندهای طراحی و توسعه مناسب زیر شروع میشود:
همه کدها را در یک سیستم کنترل نسخه مانند git ذخیره کنید
تمام تغییرات کد را از طریق درخواستهای pull انجام دهید
اطمینان حاصل کنید که درخواستهای pull حداقل یک بازبین مستقل دارند—اگر به تنهایی روی پروژهای کار میکنید، توسعهدهندگان دیگر و بررسیهای کد تجاری را پیدا کنید
از یک محیط توسعه برای آزمایش، کامپایل، استقرار قراردادهای هوشمند استفاده کنید
کد خود را از طریق ابزارهای اصلی تجزیه و تحلیل کد، مانند Cyfrin Aaderyn(opens in a new tab)، Mythril و Slither اجرا کنید. در حالت ایدهآل، باید این کار را قبل از ادغام هر درخواست pull انجام دهید و تفاوتها را در خروجی مقایسه کنید
مطمئن شوید که کد شما بدون خطا کامپایل شده است و کامپایلر سالیدیتی هیچ هشداری صادر نمیکند
کد خود را به درستی مستند کنید (با استفاده از NatSpec(opens in a new tab)) و جزئیات مربوط به معماری قرارداد را به آسانی شرح دهید. این کار بررسی و بازبینی کد شما را برای دیگران آسانتر میکند.
6. اجرای طرحهای قوی بازیابی حوادث
طراحی کنترلهای دسترسی ایمن، اجرای اصلاحکنندههای عملکرد و سایر پیشنهادها میتواند امنیت قرارداد هوشمند را بهبود بخشد، اما نمیتواند احتمال سوء استفادههای مخرب را رد کند. ایجاد قراردادهای هوشمند ایمن مستلزم «آماده شدن برای شکست» و داشتن یک برنامه بازگشتی برای پاسخگویی مؤثر به حملات است. یک طرح مناسب برای بازیابی حوادث شامل برخی یا همه اجزای زیر است:
ارتقاهای قرارداد
در حالی که قراردادهای هوشمند اتریوم به طور پیش فرض تغییر ناپذیر هستند، میتوان با استفاده از الگوهای ارتقا به درجاتی از تغییرپذیری دست یافت. به روز رسانی قراردادها در مواردی ضروری است که یک نقص مهم قرارداد قدیمی شما را غیرقابل استفاده میکند و به کارگیری منطق جدید امکان پذیرترین گزینه است.
مکانیسمهای ارتقای قرارداد متفاوت عمل میکنند، اما «الگوی پروکسی» یکی از محبوبترین رویکردها برای ارتقای قراردادهای هوشمند است. الگوهای پراکسی(opens in a new tab) منطق اجرائی و فضای ذخیرهسازی دادهها را بین دو قرارداد تقسیم میکند. قرارداد اول (که "قرارداد پراکسی" نامیده میشود) متغیرهای حالت را ذخیره میکند (به عنوان مثال، موجودی کاربر)، در حالی که قرارداد دوم (که "منطق قرارداد" نامیده میشود) کد اجرای توابع قرارداد را نگه میدارد.
حسابها با قرارداد پروکسی تعامل دارند، که همه فراخوانیهای تابع را با استفاده از delegatecall()
(opens in a new tab) به قرارداد منطقی ارسال میکند. تماس سطح پایین. برخلاف یک تماس پیامی معمولی، delegatecall()
تضمین میکند که کد در حال اجرا در آدرس قرارداد منطقی در متن قرارداد فراخوانی اجرا میشود. یک تماس پیامی معمولی، delegatecall()
تضمین میکند که کد در حال اجرا در آدرس قرارداد منطقی در متن قرارداد فراخوانی اجرا میشود.
واگذاری تماسها به قرارداد منطقی مستلزم ذخیره آدرس آن در فضای ذخیرهسازی قرارداد پروکسی است. از این رو، ارتقاء منطق قرارداد فقط به استقرار یک قرارداد منطقی دیگر و ذخیره آدرس جدید در قرارداد پروکسی بستگی دارد. از آنجایی که فراخوانی یا تماسهای بعدی به قرارداد پروکسی به طور خودکار به قرارداد منطقی جدید هدایت میشوند، میتوانید قرارداد را بدون تغییر واقعی کد «ارتقاء» میدادید.
اطلاعات بیشتر در مورد ارتقاء قراردادها.
توقفهای اضطراری
همانطور که گفته شد، آدیت و آزمایش گسترده نمیتواند تمام اشکالات یک قرارداد هوشمند را کشف کند. اگر پس از استقرار یک آسیبپذیری در کد شما ظاهر شد، اصلاح آن غیرممکن است، زیرا نمیتوانید کد در حال اجرا در آدرس قرارداد را تغییر دهید. همچنین، مکانیسمهای ارتقا (مثلاً الگوهای پروکسی) ممکن است برای پیادهسازی زمان ببرد (اغلب به تأیید طرفهای مختلف نیاز دارند)، که تنها به مهاجمان زمان بیشتری برای ایجاد آسیب بیشتر میدهد.
گزینه هستهای اجرای یک تابع "توقف اضطراری" است که تماسهای عملکردهای آسیب پذیر را در یک قرارداد مسدود میکند. توقفهای اضطراری معمولاً شامل اجزای زیر است:
یک متغیر جهانی بولی (Boolean) که نشان میدهد قرارداد هوشمند در حالت توقف است یا خیر. این متغیر هنگام تنظیم قرارداد روی
false
تنظیم میشود، اما پس از توقف قرارداد بهtrue
برمیگردد.توابعی که در اجرای خود به متغیر بولی (Boolean) اشاره میکنند. زمانی که قرارداد هوشمند متوقف نشده باشد، چنین عملکردهایی قابل دسترسی هستند و با فعال شدن ویژگی توقف اضطراری، غیرقابل دسترس میشوند.
موجودی که به تابع توقف اضطراری دسترسی دارد، که متغیر Boolean را روی
true
تنظیم میکند. برای جلوگیری از اعمال مخرب، تماسهای این تابع را میتوان به یک آدرس مطمئن محدود کرد (به عنوان مثال، مالک قرارداد).
هنگامی که قرارداد توقف اضطراری را فعال کرد، عملکردهای خاصی قابل فراخوانی نخواهند بود. این مورد با قرار دادن توابع انتخابی در یک اصلاح کننده که به متغیر سراسری ارجاع میدهد، به دست میآید. در زیر نمونهای(opens in a new tab) وجود دارد که اجرای این الگو را در قراردادها شرح میدهد:
1// This code has not been professionally audited and makes no promises about safety or correctness. Use at your own risk.23contract EmergencyStop {45 bool isStopped = false;67 modifier stoppedInEmergency {8 require(!isStopped);9 _;10 }1112 modifier onlyWhenStopped {13 require(isStopped);14 _;15 }1617 modifier onlyAuthorized {18 // Check for authorization of msg.sender here19 _;20 }2122 function stopContract() public onlyAuthorized {23 isStopped = true;24 }2526 function resumeContract() public onlyAuthorized {27 isStopped = false;28 }2930 function deposit() public payable stoppedInEmergency {31 // Deposit logic happening here32 }3334 function emergencyWithdraw() public onlyWhenStopped {35 // Emergency withdraw happening here36 }37}نمایش همهکپی
این مثال ویژگیهای اساسی توقفهای اضطراری را نشان میدهد:
isStopped
یک بولین است که در ابتدا بهfalse
و هنگامی که قرارداد وارد حالت اضطراری میشودtrue
ارزیابی میشود.تغییردهنده تابع
onlyWhenStopped
وstoppedInEmergency
متغیرisStopped
را بررسی میکنند.stoppedInEmergency
برای کنترل توابعی استفاده میشود که در صورت آسیبپذیر بودن قرارداد، غیرقابل دسترسی هستند (به عنوان مثال،deposit()
). تماسهای این توابع به سادگی برمیگردند.
onlyWhenStopped
برای توابعی استفاده میشود که باید در مواقع اضطراری قابل فراخوانی باشند (مانند emergencyWithdraw()
). چنین توابعی میتوانند به حل وضعیت کمک کنند، از این رو آنها را از لیست "عملکردهای محدود" حذف میکنند.
استفاده از عملکرد توقف اضطراری یک توقف مؤثر برای مقابله با آسیب پذیریهای جدی در قرارداد هوشمند شما فراهم میکند. با این حال، نیاز کاربران به اعتماد به توسعهدهندگان را افزایش میدهد تا آن را به دلایل خود خدمتی فعال نکنند. برای این منظور، غیرمتمرکز کردن کنترل توقف اضطراری یا با قرار دادن آن در معرض مکانیزم رایگیری زنجیرهای، قفل زمانی یا تایید از یک کیف پول مالتی سیگ راهحلهای ممکن است.
نظارت بر رویداد
رویدادها(opens in a new tab) به شما امکان میدهد تماسهای مربوط به عملکردهای قرارداد هوشمند را ردیابی و تغییرات متغیرهای حالت را نظارت کنید. بهتر است که قرارداد هوشمند خود را طوری برنامهریزی کنید که هر زمان که یکی از طرفین یک اقدام مهم ایمنی (مثلاً برداشت وجه) انجام میدهد، رویدادی را منتشر کند.
ثبت رویدادها و نظارت بر آنها به صورت غیر زنجیرهای بینشهایی در مورد عملیات قرارداد ارائه میدهد و به کشف سریعتر اقدامات مخرب کمک میکند. این بدان معناست که تیم شما میتواند سریعتر به هکها پاسخ دهد و برای کاهش تأثیر روی کاربران، مانند توقف موقت عملکردها یا انجام ارتقا، اقدام کند.
همچنین میتوانید ابزار نظارتی خارج از قفسه را انتخاب کنید که به طور خودکار هشدارها را هر زمان که کسی با قراردادهای شما تعامل دارد، ارسال میکند. این ابزارها به شما این امکان را میدهند که بر اساس محرکهای مختلف، مانند حجم تراکنش، فرکانس فراخوانی عملکرد، یا عملکردهای خاص، هشدارهای سفارشی ایجاد کنید. برای مثال، میتوانید هشداری را برنامهریزی کنید که زمانی که مبلغ برداشت شده در یک تراکنش از یک آستانه خاص عبور میکند، وارد میشود.
7. طراحی سیستمهای حاکمیت ایمن
ممکن است بخواهید با سپردن کنترل قراردادهای هوشمند اصلی به اعضای جامعه، برنامه خود را غیرمتمرکز کنید. در این مورد، سیستم قرارداد هوشمند شامل یک ماژول حاکمیتی خواهد بود – مکانیزمی که به اعضای جامعه اجازه میدهد تا اقدامات اداری را از طریق یک سیستم حاکمیت زنجیرهای تأیید کنند. برای مثال، پیشنهادی برای ارتقاء قرارداد پروکسی به یک پیادهسازی جدید ممکن است توسط دارندگان توکن به رأی گذاشته شود.
حاکمیت غیرمتمرکز می تواند سودمند باشد، به ویژه به این دلیل که منافع توسعه دهندگان و کاربران نهایی را همسو می کند. با این وجود، مکانیسمهای حکمرانی قراردادهای هوشمند ممکن است در صورت اجرای نادرست، خطرات جدیدی را ایجاد کنند. یک سناریوی قابل قبول این است که مهاجم با گرفتن وام فوری قدرت رای عظیمی (که بر حسب تعداد توکنهای نگهداری شده اندازهگیری میشود) به دستآورد و یک پیشنهاد مخرب را انجام دهد.
یکی از راه های جلوگیری از مشکلات مربوط به حاکمیت زنجیره ای، استفاده از قفل زمانی(opens in a new tab) است. قفل زمانی مانع از اجرای یک قرارداد هوشمند تا زمان مشخصی می شود. راهبردهای دیگر عبارتند از اختصاص یک "وزن رای" به هر توکن بر اساس مدت زمانی که قفل شده است، یا اندازه گیری قدرت رای دادن یک آدرس در یک دوره تاریخی (مثلاً 2-3 بلوک در گذشته) به جای بلوک فعلی. هر دو روش امکان جمعآوری سریع قدرت رای برای تغییر آرای زنجیره ای را کاهش می دهند.
اطلاعات بیشتر در مورد طراحی سیستمهای حاکمیت ایمن(opens in a new tab)، مکانیسمهای رایگیری مختلف در DAOها(opens in a new tab)، و بردارهای رایج حمله DAO با استفاده از دیفای(opens in a new tab) در لینکهای مشترک.
8. کاهش پیچیدگی کد به حداقل
توسعه دهندگان نرمافزار سنتی با اصل KISS ("ساده نگهش دار، احمقانه") آشنا هستند، که توصیه می کند از وارد کردن پیچیدگی های غیر ضروری در طراحی نرمافزار خودداری کنید. این امر متعاقب این تفکر دیرینه است که "سیستم های پیچیده به روش های پیچیده شکست می خورند" و بیشتر مستعد خطاهای پرهزینه هستند.
با توجه به اینکه قراردادهای هوشمند به طور بالقوه مقادیر زیادی از ارزش را کنترل می کنند، ساده نگه داشتن چیزها هنگام نوشتن قراردادهای هوشمند از اهمیت ویژه ای برخوردار است. نکته ای برای دستیابی به سادگی هنگام نوشتن قراردادهای هوشمند، استفاده مجدد از کتابخانه های موجود، مانند قراردادهای OpenZeppelin(opens in a new tab)، در صورت امکان است. از آنجایی که این کتابخانه ها به طور گسترده توسط توسعه دهندگان ممیزی و آزمایش شده اند، استفاده از آنها با نوشتن عملکردهای جدید از ابتدا، شانس معرفی اشکالات را کاهش می دهد.
توصیه رایج دیگر نوشتن توابع کوچک و مدولار نگه داشتن قراردادها با تقسیم منطق تجاری در چندین قرارداد است. نه تنها نوشتن کد سادهتر سطح حمله را در یک قرارداد هوشمند کاهش میدهد، بلکه استدلال درباره درستی سیستم کلی و تشخیص زودهنگام خطاهای احتمالی طراحی را آسانتر میکند.
9. دفاع در برابر آسیبپذیریهای رایج قرارداد هوشمند
ورود دوباره
EVM اجازه همزمانی را نمی دهد، به این معنی که دو قرارداد درگیر در یک تماس پیام نمی توانند به طور همزمان اجرا شوند. یک فراخوانی خارجی، اجرای قرارداد و حافظه فراخوان را تا زمانی که تماس برگردد، متوقف میکند، در این مرحله اجرا به طور معمول ادامه مییابد. این فرآیند را می توان به طور رسمی به عنوان انتقال جریان کنترل(opens in a new tab) به قرارداد دیگری توصیف کرد.
اگرچه اغلب بی ضرر هستند، اما انتقال جریان کنترل به قراردادهای غیرقابل اعتماد می تواند مشکلاتی مانند ورود دوباره ایجاد کند. یک حمله ورود دوباره زمانی اتفاق میافتد که یک قرارداد مخرب قبل از تکمیل فراخوانی عملکرد اصلی، یک قرارداد آسیبپذیر را دوباره فراخوانی کند. این نوع حمله به بهترین شکل با یک مثال توضیح داده می شود.
یک قرارداد هوشمند ساده ("قربانی") را در نظر بگیرید که به هر کسی اجازه می دهد اتر را واریز و برداشت کند:
1// This contract is vulnerable. Do not use in production23contract Victim {4 mapping (address => uint256) public balances;56 function deposit() external payable {7 balances[msg.sender] += msg.value;8 }910 function withdraw() external {11 uint256 amount = balances[msg.sender];12 (bool success, ) = msg.sender.call.value(amount)("");13 require(success);14 balances[msg.sender] = 0;15 }16}نمایش همهکپی
این قرارداد یک تابع withdraw()
را نشان میدهد تا به کاربران امکان میدهد ETH را که قبلاً در قرارداد سپرده شده برداشت کنند. هنگام پردازش یک برداشت، قرارداد عملیات زیر را انجام میدهد:
- تعادل اتر کاربر را بررسی میکند
- وجوه را به آدرس تماس ارسال میکند
- موجودی آنها را به 0 بازنشانی میکند و از برداشت اضافی از کاربر جلوگیری میکند
تابع withdraw()
در قرارداد قربانی
از الگوی "بررسی-تعامل-اثرات" پیروی می کند. که بررسی میکند آیا شرایط لازم برای اجرا برآورده شده است (یعنی کاربر دارای موجودی ETH مثبت است) و قبل از اعمال اثرات تراکنش (یعنی کاهش موجودی کاربر) تعامل را با ارسال ETH به آدرس تماسگیرنده انجام میدهد.
اگر withdraw()
از یک حساب تحت مالکیت خارجی (EOA) فراخوانی شود، تابع همانطور که انتظار می رود اجرا می شود: msg.sender.call.value()
ETH را برای تماس گیرنده ارسال می کند. با این حال، اگر msg.sender
یک حساب قرارداد هوشمند باشد، withdraw()
را فراخوانی میکند، ارسال وجوه با استفاده از msg.sender.call.value()
انجام میشود. همچنین کدهای ذخیره شده در آن آدرس را برای اجرا راه اندازی کنید.
تصور کنید این کدی است که در آدرس قرارداد مستقر شده است:
1 contract Attacker {2 function beginAttack() external payable {3 Victim(victim_address).deposit.value(1 ether)();4 Victim(victim_address).withdraw();5 }67 function() external payable {8 if (gasleft() > 40000) {9 Victim(victim_address).withdraw();10 }11 }12}نمایش همهکپی
این قرارداد برای انجام سه کار طراحی شده است:
- پذیرش سپرده از حساب دیگری (احتمالاً EOA مهاجم)
- واریز یک سکه ETH به قرارداد قربانی
- برداشت یک سکه ETH ذخیره شده در قرارداد هوشمند
هیچ مشکلی در اینجا وجود ندارد، به جز اینکه مهاجم
تابع دیگری دارد که اگر گس باقی مانده از msg.sender.call.value
ورودی بیش از 40،000 باشد.ده باشد، تابع دیگری دارد که withdraw()
را در قربانی
دوباره فراخوانی میکند. این به مهاجم
این امکان را میدهد تا قربانی
را دوباره وارد کرده و وجوه بیشتری را قبل از تکمیل اولین فراخوان خروج
برداشت کند. چرخه به این صورت است:
1- Attacker's EOA calls `Attacker.beginAttack()` with 1 ETH2- `Attacker.beginAttack()` deposits 1 ETH into `Victim`3- `Attacker` calls `withdraw() in `Victim`4- `Victim` checks `Attacker`’s balance (1 ETH)5- `Victim` sends 1 ETH to `Attacker` (which triggers the default function)6- `Attacker` calls `Victim.withdraw()` again (note that `Victim` hasn’t reduced `Attacker`’s balance from the first withdrawal)7- `Victim` checks `Attacker`’s balance (which is still 1 ETH because it hasn’t applied the effects of the first call)8- `Victim` sends 1 ETH to `Attacker` (which triggers the default function and allows `Attacker` to reenter the `withdraw` function)9- The process repeats until `Attacker` runs out of gas, at which point `msg.sender.call.value` returns without triggering additional withdrawals10- `Victim` finally applies the results of the first transaction (and subsequent ones) to its state, so `Attacker`’s balance is set to 0نمایش همهکپی
خلاصه موضوع این است که چون موجودی تماسگیرنده تا زمانی که اجرای تابع کامل نشود روی 0 تنظیم نمیشود، فراخوانیهای بعدی موفق خواهند شد و به تماسگیرنده اجازه میدهند تا موجودی خود را چندین بار برداشت کند. از این نوع حمله می توان برای تخلیه یک قرارداد هوشمند از وجوه آن استفاده کرد، مانند آنچه در هک DAO سال 2016(opens in a new tab) اتفاق افتاد. همانطور که فهرستهای عمومی اکسپلویتهای reentrancy(opens in a new tab) نشان میدهند، حملات reentrancy امروزه همچنان یک موضوع حیاتی برای قراردادهای هوشمند است.
چگونه از حملات بازگشت مجدد جلوگیری کنیم
یک رویکرد برای مقابله با reentrancy، پیروی از الگوی بررسی-اثرات-تعامل(opens in a new tab) است. این الگو دستور اجرای توابع را میدهد به گونهای که کدی که بررسیهای لازم را قبل از پیشرفت در اجرا انجام میدهد، ابتدا میآید، به دنبال آن کدی که وضعیت قرارداد را دستکاری میکند، کدی که با قراردادهای دیگر تعامل دارد یا EOAها در آخر میآیند.
الگوی بررسی-اثرات-تعامل در نسخه اصلاح شده قرارداد قربانی
که در زیر نشان داده شده است استفاده می شود:
1contract NoLongerAVictim {2 function withdraw() external {3 uint256 amount = balances[msg.sender];4 balances[msg.sender] = 0;5 (bool success, ) = msg.sender.call.value(amount)("");6 require(success);7 }8}کپی
این قرارداد یک بررسی در موجودی کاربر انجام می دهد، اثرات تابع withdraw()
را اعمال می کند (با تنظیم مجدد موجودی کاربر به 0)، و به انجام تعامل (ارسال ETH به آدرس کاربر) ادامه می دهد. این مورد تضمین میکند که قرارداد قبل از تماس خارجی، فضای ذخیرهسازی خود را بهروزرسانی میکند و شرایط ورود مجدد را که اولین حمله را فعال میکرد، حذف میکند. قرارداد مهاجم
همچنان میتواند به NoLongerAVictim
برگردد، اما از آنجایی که balances[msg.sender]
روی 0 تنظیم شده است، برداشتهای اضافی با خطا مواجه میشوند.
گزینه دیگر استفاده از یک قفل محرومیت متقابل (که معمولاً به عنوان "mutex" توصیف می شود) است که بخشی از وضعیت قرارداد را تا زمانی که فراخوانی عملکرد کامل شود قفل می کند. این امر با استفاده از یک متغیر بولین که قبل از اجرای تابع روی true
تنظیم شده است و پس از انجام فراخوانی به false
برمیگردد پیادهسازی میشود. همانطور که در مثال زیر مشاهده میشود، استفاده از میوتکس از یک تابع در برابر تماسهای بازگشتی محافظت میکند در حالی که فراخوان اصلی هنوز در حال پردازش است، و به طور مؤثر ورود مجدد را متوقف میکند.
1pragma solidity ^0.7.0;23contract MutexPattern {4 bool locked = false;5 mapping(address => uint256) public balances;67 modifier noReentrancy() {8 require(!locked, "Blocked from reentrancy.");9 locked = true;10 _;11 locked = false;12 }13 // This function is protected by a mutex, so reentrant calls from within `msg.sender.call` cannot call `withdraw` again.14 // The `return` statement evaluates to `true` but still evaluates the `locked = false` statement in the modifier15 function withdraw(uint _amount) public payable noReentrancy returns(bool) {16 require(balances[msg.sender] >= _amount, "No balance to withdraw.");1718 balances[msg.sender] -= _amount;19 bool (success, ) = msg.sender.call{value: _amount}("");20 require(success);2122 return true;23 }24}نمایش همهکپی
همچنین میتوانید به جای سیستم «پرداخت فشاری» که وجوه را به حسابها ارسال میکند، از سیستم برگشت پرداختها(opens in a new tab) استفاده کنید که کاربران را ملزم به برداشت وجه از قراردادهای هوشمند میکند. با این کار امکان راهاندازی ناخواسته کد در آدرسهای ناشناس حذف میشود (و همچنین میتواند از برخی حملات انکار سرویس جلوگیری کند).
پاریز و سرریز اعداد صحیح
سرریز یا اورفلو اعداد صحیح زمانی اتفاق میافتد که نتایج یک عملیات حسابی خارج از محدوده قابل قبول مقادیر قرار میگیرد و باعث میشود که آن را به پایینترین مقدار قابل نمایش تبدیل کند. برای مثال، یک uint8
فقط میتواند مقادیر تا 2^8-1=255 را ذخیره کند. عملیات حسابی که به مقادیر بالاتر از 255
منجر میشود، سرریز یا اورفلو میشوند و uint
را به 0
بازنشانی میکنند، مشابه اینکه کیلومترشمار ماشین بعد از به حداکثر رسیدن مسافت پیموده شده (999999) به 0 بازنشانی شود.
جریانهای آندرفلو صحیح به دلایل مشابهی اتفاق میافتد: نتایج یک عملیات حسابی کمتر از محدوده قابل قبول است. فرض کنید سعی کردهاید 0
را در uint8
کاهش دهید، نتیجه به سادگی به حداکثر مقدار قابل نمایش (255
) میرسد.
هم اورفلو و هم آندرفلو اعداد صحیح میتواند منجر به تغییرات غیرمنتظره در متغیرهای حالت قرارداد شود و منجر به اجرای برنامه ریزی نشده شود. در زیر مثالی وجود دارد که نشان میدهد چگونه یک مهاجم میتواند از سرریز حسابی در یک قرارداد هوشمند برای انجام یک عملیات نامعتبر سوء استفاده کند:
1pragma solidity ^0.7.6;23// This contract is designed to act as a time vault.4// User can deposit into this contract but cannot withdraw for at least a week.5// User can also extend the wait time beyond the 1 week waiting period.67/*81. Deploy TimeLock92. Deploy Attack with address of TimeLock103. Call Attack.attack sending 1 ether. You will immediately be able to11 withdraw your ether.1213What happened?14Attack caused the TimeLock.lockTime to overflow and was able to withdraw15before the 1 week waiting period.16*/1718contract TimeLock {19 mapping(address => uint) public balances;20 mapping(address => uint) public lockTime;2122 function deposit() external payable {23 balances[msg.sender] += msg.value;24 lockTime[msg.sender] = block.timestamp + 1 weeks;25 }2627 function increaseLockTime(uint _secondsToIncrease) public {28 lockTime[msg.sender] += _secondsToIncrease;29 }3031 function withdraw() public {32 require(balances[msg.sender] > 0, "Insufficient funds");33 require(block.timestamp > lockTime[msg.sender], "Lock time not expired");3435 uint amount = balances[msg.sender];36 balances[msg.sender] = 0;3738 (bool sent, ) = msg.sender.call{value: amount}("");39 require(sent, "Failed to send Ether");40 }41}4243contract Attack {44 TimeLock timeLock;4546 constructor(TimeLock _timeLock) {47 timeLock = TimeLock(_timeLock);48 }4950 fallback() external payable {}5152 function attack() public payable {53 timeLock.deposit{value: msg.value}();54 /*55 if t = current lock time then we need to find x such that56 x + t = 2**256 = 057 so x = -t58 2**256 = type(uint).max + 159 so x = type(uint).max + 1 - t60 */61 timeLock.increaseLockTime(62 type(uint).max + 1 - timeLock.lockTime(address(this))63 );64 timeLock.withdraw();65 }66}نمایش همه
چگونه از سرریز و آندرفلو اعداد صحیح جلوگیری کنیم
از نسخه 0.8.0، کامپایلر سالیدیتی کدهایی را که منجر به سرریز و زیر جریان یا همان آندر فلو اعداد صحیح میشود، رد میکند. با این حال، قراردادهایی که با یک نسخه کامپایلر پایینتر کامپایل میشوند باید یا باید توابع مربوط به عملیات حسابی را بررسی یا از یک کتابخانه استفاده کنند (به عنوان مثال، SafeMath(opens in a new tab)) که اورفلو یا آندرفلو را بررسی میکند.
دستکاری اوراکل
اوراکلها اطلاعات خارج از زنجیره را منبع قرار میدهند و آنها را به صورت زنجیرهای برای استفاده از قراردادهای هوشمند ارسال میکند. با اوراکلها، میتوانید قراردادهای هوشمندی را طراحی کنید که با سیستمهای خارج از زنجیره، مانند بازارهای سرمایه، همکاری میکنند و کاربرد آنها را تا حد زیادی گسترش میدهند.
اما اگر اوراکل خراب شود و اطلاعات نادرست را روی زنجیره ارسال کند، قراردادهای هوشمند بر اساس ورودیهای اشتباه اجرا میشوند که میتواند مشکلاتی را ایجاد کند. این اساس "مشکل اوراکل" است که به وظیفه اطمینان از دقیق، به روز و به موقع بودن اطلاعات یک اوراکل بلاک چین مربوط میشود.
یک نگرانی امنیتی مرتبط، استفاده از یک اوراکل زنجیرهای، مانند یک صرافی غیرمتمرکز، برای دریافت قیمت ای یک دارایی است. پلتفرمهای وامدهی در صنعت مالی غیرمتمرکز (DeFi) اغلب این کار را برای تعیین ارزش وثیقه کاربر انجام میدهند تا تعیین کنند چقدر میتوانند وام بگیرند.
قیمتهای صرافیهای غیرمتمرکز اغلب دقیق هستند، که عمدتاً به دلیل بازیابی برابری توسط آربیتراژها در بازارها است. با این حال، آنها در معرض دستکاری هستند، به ویژه اگر اوراکل روی زنجیره قیمت داراییها را بر اساس الگوهای معاملاتی تاریخی محاسبه کند (همانطور که معمولاً اتفاق میافتد).
به عنوان مثال، یک مهاجم میتواند بهطور مصنوعی قیمت نقدی یک دارایی را با گرفتن وام فوری یا همان فلش لون درست قبل از تعامل با قرارداد وام شما، افزایش دهد. پرس و جو از دکس برای قیمت دارایی، ارزشی بالاتر از حد معمول را به دست میآورد (به دلیل تقاضای انحرافی «سفارش خرید» مهاجم برای دارایی)، به آنها اجازه میدهد بیشتر از آنچه باید وام بگیرند. چنین "حملات وام فلش یا همان فلش لون" برای بهرهبرداری از اتکا به اوراکلهای قیمت در میان برنامههای کاربردی دیفای استفاده شده است که میلیونها وجوه از دست رفته پروتکلها ایجاد کرده است.
چگونه از دستکاری اوراکل جلوگیری کنیم؟
حداقل نیاز برای جلوگیری از دستکاری اوراکل(opens in a new tab) استفاده از یک شبکه اوراکل غیرمتمرکز است که پرس و جو یا اطلاعات از چندین منبع برای جلوگیری از نقاط شکست کوئری میکند. در بیشتر موارد، اوراکلهای غیرمتمرکز دارای انگیزههای اقتصادی رمزارزی شدهاند تا نود یا گرههای اوراکل را تشویق کرده تا اطلاعات صحیح را گزارش کنند و آنها را از اوراکلهای متمرکز ایمنتر میکند.
اگر قصد دارید از یک اوراکل زنجیرهای یا آنچین برای قیمت داراییها پرس و جو کنید، از یکی استفاده کنید که مکانیزم قیمت میانگین وزن شده با زمان (TWAP) را پیادهسازی میکند. یک اوراکل TWAP(opens in a new tab) قیمت یک دارایی را در دو مقطع زمانی مختلف (که شما میتوانید اصلاح کنید) و قیمت لحظهای را بر اساس میانگین به دست آمده محاسبه میکند. انتخاب دورههای زمانی طولانیتر از پروتکل شما در برابر دستکاری قیمت محافظت میکند، زیرا سفارشهای بزرگی که اخیراً اجرا شدهاند نمیتوانند بر قیمت دارایی تأثیر بگذارند.
منابع امنیتی قرارداد هوشمند برای توسعهدهندگان
ابزارهایی برای تجزیه و تحلیل قراردادهای هوشمند و تأیید صحت کد
ابزارها و کتابخانههای تست - مجموعه ای از ابزارها و کتابخانههای استاندارد صنعتی برای انجام تستهای واحد، تجزیه و تحلیل استاتیک و تجزیه و تحلیل پویا در قراردادهای هوشمند است
ابزارهای تأیید رسمی - ابزارهایی برای تأیید صحت عملکرد در قراردادهای هوشمند و بررسی متغیرها هستند.
خدمات حسابرسی قراردادهای هوشمند - فهرست هایی که خدمات حسابرسی قرارداد هوشمند برای پروژههای توسعه اتریوم ارائه میکنند.
پلتفرمهای پاداش باگ - پلتفرمهایی برای هماهنگی پاداشهای اشکال و پاداش افشای مسئولانه آسیبپذیریهای مهم در قراردادهای هوشمند هستند
فورک چکر(opens in a new tab) - رایگان بوده و ابزار آنلاین برای بررسی تمام اطلاعات موجود در مورد قرارداد منشعب شده است.
رمزگذار ABI(opens in a new tab) - یک رمزگذار رایگان سرویس آنلاین برای رمزگذاری توابع قرارداد سالیدیتی و آرگومانهای سازنده (constructor) شما است.
آدرین(opens in a new tab) - تحلیلگر استاتیک سالیدیتی ، از درختان نحو انتزاعی (AST) عبور میکند تا آسیبپذیریهای مشکوک را مشخص کرده و مسائل را در قالب علامتگذاری آسان برای مصرف چاپ کند.
ابزارهای نظارت بر قراردادهای هوشمند
OpenZeppelin Defender Sentinels(opens in a new tab) - ابزاری برای نظارت و پاسخگویی خودکار به رویدادها، عملکردها و پارامترهای تراکنش در قراردادهای هوشمند شما است.
هشدار همزمان با ملایمت(opens in a new tab) - ابزاری برای دریافت اعلانهای همزمان هنگامی که رویدادهای غیرمنتظره در قراردادهای هوشمند یا کیف پولهای شما اتفاق میافتد.
ابزارهایی برای مدیریت امن قراردادهای هوشمند
OpenZeppelin Defender Admin(opens in a new tab) - رابطی برای مدیریت قراردادهای هوشمند، از جمله کنترلهای دسترسی، ارتقاء و توقف است.
ایمن(opens in a new tab) - کیف پول قرارداد هوشمند در حال اجرا اتریوم که به حداقل تعداد افراد نیاز دارد تا تراکنش را قبل از انجام آن تأیید کنند (M-of-N).
قراردادهای اوپن زپلین(opens in a new tab) - کتابخانهها را برای اجرای ویژگیهای اداری، از جمله مالکیت قرارداد، ارتقاء، کنترلهای دسترسی، حاکمیت، قابلیت توقف موقت و موارد دیگر مدیریت میکند.
خدمات حسابرسی قرارداد هوشمند
ConsenSys Diligence(opens in a new tab) - خدمات آدیت قرارداد هوشمند که به پروژهها در سراسر اکوسیستم بلاک چین کمک میکند مطمئن شوند که پروتکلهای آنها برای راهاندازی آماده هستند و برای محافظت از کاربران ساخته شدهاند.
CertiK(opens in a new tab) - شرکت امنیت بلاک چین پیشگام در استفاده از فناوری تایید رسمی پیشرفته در قراردادهای هوشمند و شبکههای بلاک چین است.
رد بیت(opens in a new tab) - امنیت سایبری شرکتی که تحقیقات امنیتی را با ذهنیت مهاجم برای کاهش ریسک و تقویت کد ترکیب میکند.
PeckShield(opens in a new tab) - شرکت امنیت بلاک چین که محصولات و خدماتی برای امنیت، حریم خصوصی و قابلیت استفاده کل اکوسیستم بلاک چین ارائه میکند.
QuantStamp(opens in a new tab) - سرویس حسابرسی تسهیل کننده جریان اصلی پذیرش فناوری بلاک چین از طریق خدمات امنیت و ارزیابی ریسک است.
اوپن زپلین(opens in a new tab) - شرکت امنیتی قرارداد هوشمند که حسابرسیهای امنیتی سیستمهای توزیع شده را ارائه میدهد.
تأیید زمان اجرا(opens in a new tab) - شرکت امنیتی متخصص در مدل سازی رسمی و تأیید قراردادهای هوشمند است
هک(opens in a new tab) - حسابرس امنیت سایبری Web3 که ارائه دهنده 360 رویکرد درجه به امنیت بلاک چین است.
Nethermind(opens in a new tab) - خدمات حسابرسی سالیدیتی و کایرو، تضمین یکپارچگی قراردادهای هوشمند و ایمنی کاربران در سراسر اتریوم و استارک نت را ارائه میدهد.
HashEx(opens in a new tab) - _HashEx بر روی بلاکین و حسابرسی قراردادهای هوشمند برای اطمینان از امنیت ارزهای دیجیتال، ارائه خدماتی مانند توسعه قرارداد هوشمند، تست نفوذ، مشاوره بلاکچین تمرکز دارد.
Code4rena(opens in a new tab) - پلتفرم حسابرسی رقابتی که کارشناسان امنیت قراردادهای هوشمند را تشویق میکند تا آسیبپذیریها را بیابند و به ایمنتر شدن Web3 کمک کنند.
CodeHawks(opens in a new tab) - پلتفرم حسابرسی رقابتی میزبان مسابقات حسابرسی قراردادهای هوشمند برای محققان امنیتی.
Cyfrin(opens in a new tab) - نیروگاه امنیتی وب3، انکوباتور امنیت رمزارز از طریق محصولات و خدمات حسابرسی قرارداد هوشمند.
ImmuneBytes(opens in a new tab) - شرکت امنیتی وب3 که ممیزی های امنیتی سیستم های بلاکچین را از طریق تیمی از حسابرسان مجرب و بهترین ابزارها ارائه می کند.
Oxorio(opens in a new tab) - ممیزی قراردادهای هوشمند و خدمات امنیتی بلاکین با تخصص در EVM، سالیدیتی، ZK، فناوری زنجیرهای متقابل برای شرکتهای رمزنگاری و پروژههای دیفای.
Inference(opens in a new tab) - شرکت حسابرسی امنیتی، متخصص در حسابرسی قراردادهای هوشمند برای بلاکچینهای مبتنی بر EVM. با تشکر از حسابرسان متخصص آن، آنها مشکلات بالقوه را شناسایی کرده و راهحلهای عملی را برای رفع آنها قبل از استقرار پیشنهاد میکنند.
پلتفرمهای باگبانتی
Immunefi(opens in a new tab) - پلتفرم باگبانتی برای قراردادهای هوشمند و پروژههای دیفای، که در آن محققان امنیتی کد را بررسی میکنند، آسیبپذیریها را فاش میکنند، پاداش دریافت میکنند و دنیای رمزارز را ایمنتر میکنند.
HackerOne(opens in a new tab) - پلتفرم هماهنگی آسیبپذیری و باگبانتی که کسبوکارها را با کارشناسان تست نفوذ و محققان امنیت سایبری مرتبط میکند.
HackenProof(opens in a new tab) - پلتفرم باگبانتی متخصص برای پروژههای رمزارزی (دیفای، قراردادهای هوشمند، کیف پولها، CEX و موارد دیگر)، جایی که متخصصان امنیتی خدمات تریاژ را ارائه می دهند و محققان برای گزارش های مربوط به باگ هایتأیید شده پاداش دریافت می کنند.
Sherlock(opens in a new tab) - عریضهنویس در وب3 برای امنیت قراردادهای هوشمند، با پرداختهایی برای حسابرسان که از طریق قراردادهای هوشمند مدیریت میشوند تا از پرداخت عادلانه باگ های مربوطه اطمینان حاصل شود.
CodeHawks(opens in a new tab) - پلتفرم باگبانتی رقابتی که در آن حسابرسان در مسابقات و چالشهای امنیتی و (به زودی) در ممیزیهای خصوصی خودشان شرکت میکنند.
رسانه های آسیب پذیری ها و اکسپلویت های شناخته شده قرارداد هوشمند
قماله کانسنسیس: حملات شناخته شده قرارداد هوشمند(opens in a new tab) - توضیحات مبتدی مهم ترین آسیب پذیری های قرارداد، با کد نمونه برای اکثر موارد.
SWC Registry(opens in a new tab) - فهرست تنظیمشده از موارد سرشماری ضعف مشترک (CWE) که در قراردادهای هوشمند اتریوم اعمال میشود.
Rekt(opens in a new tab) - انتشار منظم هکها و سوء استفادههای رمزنگاری با مشخصات بالا، همراه با کالبدشکافی.
چالشهای یادگیری امنیت قراردادهای هوشمند
Awesome BlockSec CTF (opens in a new tab) - فهرست تنظیمشده بازیهای امنیتی بلاکچین، چالشها و مسابقات Capture The Flag(opens in a new tab) و نوشتههای راهحل.
DeFi آسیب پذیر لعنتی(opens in a new tab) - بازی برای یادگیری امنیت تهاجمی قراردادهای هوشمند دیفای و ایجاد مهارت در شکار باگ و ممیزی امنیتی.
Ethernaut(opens in a new tab) - بازی جنگی مبتنی بر وب3/سالیدیتی که در آن هر سطح یک قرارداد هوشمند است که باید "هک" شود.
HackenProof x HackTheBox(opens in a new tab) - چالش هک قرارداد هوشمند، در یک ماجراجویی فانتزی. تکمیل موفقیتآمیز چالش به یک برنامه باگبانتی خصوصی نیز دسترسی پیدا میکند.
بهترین روش ها برای ایمن سازی قراردادهای هوشمند
کانسنسیس: بهترین روشهای امنیتی قراردادهای هوشمند اتریوم(opens in a new tab) - فهرست جامع دستورالعملها برای ایمن کردن قراردادهای هوشمند اتریوم.
Nascent: ابزار ساده امنیتی(opens in a new tab) - مجموعه راهنماها و چک لیست های عملی مبتنی بر امنیت برای توسعه قراردادهای هوشمند.
Solidity Patterns(opens in a new tab) - تلفیقی مفید از الگوهای امن و بهترین شیوه ها برای زبان برنامه نویسی قرارداد هوشمند سالیدیتی.
اسناد سالیدیتی: ملاحظات امنیتی(opens in a new tab) - دستورالعملهایی برای نوشتن قراردادهای هوشمند ایمن با سالیدیتی.
استاندارد تأیید امنیت قراردادهای هوشمند(opens in a new tab) - چک لیست چهارده قسمتی ایجاد شده برای استانداردسازی امنیت قراردادهای هوشمند برای توسعه دهندگان، معماران، بازبینان امنیتی و فروشندگان.
**امنیت و حسابرسی قرارداد هوشمند را بیاموزید(opens in a new tab) - دوره ممیزی و امنیت قراردادهای هوشمند نهایی، ایجاد شده برای توسعه دهندگان قراردادهای هوشمند که به دنبال ارتقای بهترین شیوه های امنیتی خود و تبدیل شدن به محققین امنیتی هستند.