امنیت قرارداد هوشمند؛ پول کجا واقعا از دست می رود

به روزرسانی:
۷ دقیقه مطالعه


۲۵۸بازدید



۰اشتراک



دارای مجوزهای رسمی
انتشار:

برای ثبت سفارش به حساب نیاز دارید. ثبت نام رایگان است.

قرارداد هوشمند یک وعده ساده دارد: کد به جای اعتماد. مشکل اینجاست که کد هم اشتباه می کند و برخلاف یک سرور، این اشتباه را نمی شود شب بعد وصله کرد.

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

این نوشته درباره همان چیزهاست: چه چیزی واقعا خراب می شود، آدیت چه چیزی را ثابت می کند و چه چیزی را نه، و کاربر عادی قبل از گذاشتن پول در یک قرارداد چه می تواند ببیند.

چرا امنیت اینجا با امنیت نرم افزار فرق دارد

سه تفاوت، و هر سه به ضرر شما کار می کنند.

کد بعد از استقرار ثابت است. در یک برنامه معمولی، فاصله بین کشف باگ و رفع آن ساعت هاست. اینجا این فاصله وجود ندارد. باگ تا وقتی که قرارداد پول دارد قابل بهره برداری می ماند.

مهاجم زودتر از شما کد را می خواند. قرارداد شما عمومی است. کسانی هستند که تمام وقتشان همین است.

خطا برگشت پذیر نیست. بانک تراکنش را برمی گرداند. زنجیره برنمی گرداند.

اتریومقیمت اتریوم به دلار و تومان ۰.۶۹٪تومانی
۵۸۰,۲۰۳,۲۰۴ تومان
$2,479.46 ▼ ۱.۷۴٪دلاری نرخ جهانی
تغییر ۲۴ ساعته، تومانی و دلاری - بروزرسانی ۰۲:۰۲ مشاهده بازار

آسیب پذیری هایی که واقعا پول برده اند

فراخوانی بازگشتی

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

راه حلش قدیمی و ساده است و در مستندات رسمی سالیدیتی اولین توصیه است: اول شرط ها را چک کن، بعد وضعیت داخلی را به روز کن، و تماس با بیرون را آخر بگذار.

این همان چیزی است که در سال ۲۰۱۶ اتفاق افتاد و اتریوم را دو تکه کرد. ماجرا را در پرونده هک دائو کامل نوشته ایم.

سرریز عددی، که دیگر مسئله قبلی نیست

این را باید تصحیح کرد، چون هنوز در آموزش های فارسی به عنوان خطر اصلی معرفی می شود.

در نسخه های قدیمی سالیدیتی، عبور یک عدد از سقف نوعش باعث می شد بچرخد و از صفر شروع کند. از نسخه ۰.۸ به بعد این رفتار عوض شده و طبق یادداشت تغییرات همان نسخه، عملیات حسابی در چنین حالتی تراکنش را برمی گرداند.

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

کنترل دسترسی

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

این باگ پیچیده نیست. فراموشی است. و دقیقا به همین دلیل زیاد اتفاق می افتد.

دستکاری اوراکل

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

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

پیش دستی و ترتیب تراکنش ها

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

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

آدیت: چه چیزی می گوید و چه چیزی نمی گوید

آدیت یعنی گروهی برای مدت مشخصی کد را خوانده اند و آنچه پیدا کرده اند را نوشته اند. سه محدودیت جدی دارد:

  • گزارش مربوط به یک نسخه مشخص از کد است. اگر بعدش چیزی عوض شده باشد، گزارش درباره کد فعلی حرفی نمی زند.
  • بخشی از یافته ها معمولا «برطرف نشده» می ماند و توسعه دهنده آن را پذیرفته است. این ها در گزارش هستند و کسی نمی خواندشان.
  • آدیت درباره منطق اقتصادی پروژه چیزی نمی گوید. قراردادی می تواند بی نقص باشد و همچنان طوری طراحی شده باشد که پول شما را ببرد.

قراردادهای آدیت شده هم از دست رفته اند. آدیت احتمال را کم می کند، صفر نمی کند.

لایه انسانی، که در فهرست آسیب پذیری ها نمی آید

بخش قابل توجهی از حادثه هایی که «هک قرارداد هوشمند» خوانده می شوند، اصلا در قرارداد اتفاق نیفتاده اند.

کلید خصوصی حساب مالک لو رفته است. یا یک نفر از تیم فریب خورده و تراکنشی را امضا کرده که فکر می کرده چیز دیگری است. قرارداد در این حالت دقیقا همان کاری را کرده که برایش نوشته شده بود: به مالک اجازه داده.

دفاع در برابر این دسته فنی نیست، سازمانی است. کلید مالک باید روی کیف پول چندامضایی باشد نه روی یک لپ تاپ، و تغییرات حساس باید تاخیر زمانی داشته باشند تا اگر کسی کلید را به دست آورد، فرصت واکنش بماند.

برای پروژه ها راه سومی هم هست که کم استفاده می شود: باز گذاشتن مسیر گزارش آسیب پذیری و پرداخت جایزه به کسی که پیدایش می کند. جایزه گزارش آسیب پذیری در اکوسیستم اتریوم نشان می دهد این مسیر چطور کار می کند و چقدر ارزان تر از حادثه است.

بعد از حادثه چه اتفاقی می افتد

معمولا هیچ. این را باید صادقانه گفت.

گاهی مهاجم بخشی از پول را در ازای مصونیت برمی گرداند. گاهی پروژه از موجودی خودش بخشی از ضرر را جبران می کند. اما هیچ سازوکار پیش فرضی برای برگرداندن پول وجود ندارد و انتظار داشتن از آن، برداشت اشتباهی از این فناوری است.

تنها استثنای بزرگ تاریخ، فورک اتریوم بعد از هک دائو بود و همان استثنا آنقدر بحث برانگیز شد که زنجیره را دو تکه کرد. تکرار نشده است و انتظارش را هم نداشته باشید.

اگر کد نمی نویسید، چه چیزی را می توانید چک کنید

این بخش برای اکثر خوانندگان این نوشته کاربردی تر از بقیه است. برای دیدن این موارد لازم نیست سالیدیتی بلد باشید، فقط باید بدانید کجا را نگاه کنید:

  • آیا کد قرارداد اصلا منتشر شده است؟ قراردادی که سورسش تایید نشده، یعنی هیچ کس نمی داند داخلش چیست.
  • آیا کسی اجازه ضرب نامحدود دارد؟ وجود تابع ضرب با دسترسی مالک، یعنی عرضه هر لحظه می تواند چند برابر شود.
  • آیا مالک می تواند انتقال را متوقف کند یا آدرسی را مسدود کند؟ این در بسیاری از قراردادها هست و همیشه هم بد نیست، اما باید بدانید که هست.
  • پروکسی هست یا نه؟ اگر قرارداد قابل ارتقا باشد، کدی که امروز خوانده اید تضمینی برای فردا نیست.

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

اگر خودتان می نویسید

سه عادت که بیشترین اثر را دارند و هیچ کدام هزینه ندارند:

از قراردادهای استاندارد و بازبینی شده ارث ببرید به جای نوشتن از صفر. مسیر عملی اش در راهنمای ساخت قرارداد روی اتریوم هست.

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

و قبل از هر چیز، فرض کنید هر آدرسی که با آن تماس می گیرید یک قرارداد مخرب است. اگر کد شما با این فرض هم درست کار کند، بیشتر مسیر را رفته اید.

سوال های پرتکرار

آیا قرارداد هوشمند قابل هک شدن است

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

آدیت شدن یعنی قرارداد امن است

نه. یعنی گروهی نسخه مشخصی از کد را در زمان مشخصی خوانده اند. اگر کد بعد از آن عوض شده باشد یا یافته های گزارش برطرف نشده باشند، گزارش تضمینی نمی دهد.

حمله بازگشتی هنوز اتفاق می افتد

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

چطور بفهمم یک توکن قابل ضرب نامحدود است

سورس تاییدشده قرارداد را در کاوشگر شبکه باز کنید و دنبال تابع ضرب و سطح دسترسی آن بگردید. اگر سورس اصلا منتشر نشده باشد، همین به تنهایی یک علامت هشدار است.