لقد رأينا للتو كيف أن ثغرة صغيرة تؤدي إلى خسارة مالية (بأحجام متفاوتة) ، بنفس الطريقة التي تكون بها العقود الذكية المطورة عبر Solidity عرضة لهجمات مختلفة معروفة وغير معروفة. يستغل المستغلون الأخطاء والثغرات لإلقاء نظرة خاطفة على العقود الذكية والتلاعب بها لتنفيذ الهجمات. نقدم هنا قائمة شاملة لأهم 5 أخطاء شائعة في لغة برمجة Solidity.
في QuillAudits ، نتبع المنهجية التكيفية للحصول على جوهر كل اختراق وتنفيذ ما تعلمته على العقود الذكية المستقبلية لتجنب أي تهديد محتمل.
أخطاء في لغة برمجة الصلابة
1. مكالمة خارجية غير محددة
نحن نتعامل مع هذه المشكلة في المقام الأول لأنها واحدة من أكثر عيوب Solidity شيوعًا. بشكل عام ، يتم إرسال الأثير إلى أي حساب خارجي من خلال نقل() وظيفة. بصرف النظر عن هذا ، فإن الوظيفتين الأكثر استخدامًا لإجراء مكالمة خارجية هما ؛ يتصل()و أرسل ()، هنا بشكل رئيسي يتصل() يتم استخدام الوظيفة على نطاق واسع لإجراء مكالمات خارجية متعددة الاستخدامات من قبل المطورين.
رغم ذلك يتصل() و أرسل () تعيد الدوال قيمة منطقية تحدد ما إذا كانت المكالمة ناجحة أم لا. وهكذا في هذه الحالة ، إذا كان أي من الوظائف يتصل() or أرسل () فشل في أداء المهمة ، فسيعودون بامتداد خاطئة. ومن ثم ، إذا لم يقم المطور بالتحقق من القيمة المرتجعة ، فسيصبح ذلك مشكلة.
الضعف
ضع في اعتبارك المثال أدناه:
عقد لوتو {
boolpublic payedOut = خطأ ؛
العنوان العام الفائز؛
الفوز العلني بالمبلغ ؛
//… وظائف إضافية هنا
وظيفة sendToWinner () عامة {
تتطلب (! payedOut) ؛
الفائز.إرسال (winAmount) ؛
payedOut = صحيح ؛
}
وظيفة pullLeftOver () عامة {
تتطلب (payedOut) ؛
msg.sender.send (this.balance) ؛
}
}
في العقد الشبيه بـ Lotto أعلاه ، يمكننا ملاحظة أن أ الفائز يتلقى winAmount من الأثير ترك القليل من المتبقي ليتم سحبه من أي وكيل خارجي.
هنا ، يوجد مأزق العقد في السطر [11] ، حيث أ إرسال يستخدم دون التحقق من صحة الاستجابة. في المثال أعلاه ، أ الفائز الذي فشلت معاملته (إما بسبب نقص الغاز أو إذا كان عقدًا يلقي عمدًا بوظيفة احتياطية) ، يأذن دفع ليتم ضبطها على صحيح بغض النظر عما إذا كانت معاملة الأثير ناجحة أم لا. في هذه الحالة ، يمكن لأي مستغل سحب ملف الفائز المكاسب عبر الانسحاب إلى اليسار وظيفة.
نهج QuillAudit
يتعامل فريق المطورين الداخليين لدينا مع هذا الخطأ باستخدام [نقل] تعمل بدلا من [إرسال] الوظيفة ، حيث ستعود [التحويل] إذا عادت المعاملة الخارجية. وإذا كنت تستخدم [إرسال] ، فتأكد دائمًا من قيمة الإرجاع.
أحد الأساليب القوية التي نتبعها هو استخدام [نمط الانسحاب]. هنا ، نقوم منطقيًا بعزل وظيفة الإرسال الخارجية عن باقي قاعدة التعليمات البرمجية ، ونضع ضغط المعاملات التي يُحتمل أن تكون فاشلة على المستخدم النهائي ، حيث إنه الشخص الذي يستدعي وظيفة السحب.
2. إعادة الدخول
تستدعي عقود Ethereum الذكية رموزًا من عقود خارجية أخرى وتستخدمها ، ولإجراء ذلك ، فإن العقود مطلوبة لإرسال مكالمات خارجية. هذه المكالمات الخارجية ضعيفة وعرضة للهجمات ، وقد حدث أحد هذه الهجمات مؤخرًا في حالة اختراق DAO.
الضعف
ينفذ المهاجمون مثل هذه الهجمات عندما يرسل العقد الأثير إلى عنوان غير معروف. في هذه الحالة ، يمكن للمهاجم إنشاء عقد على عنوان خارجي يمتلك رمزًا ضارًا في الوظيفة الاحتياطية ، وسيتم استدعاء هذا الرمز الضار عندما يرسل العقد الأثير إلى هذا العنوان.
حقيقة: تمت صياغة مصطلح "Reentrancy" من حقيقة أنه عندما يستدعي عقد ضار خارجي وظيفة على العقد الضعيف ثم مسار تنفيذ الكود "يعيد إدخاله".
ضع في اعتبارك المثال أدناه ، إنه قبو Ethereum يسمح للمودعين بسحب إيثر واحد فقط في الأسبوع.
عقد EtherStore {
سحب عام uint256Limit = 1 إيثر ؛
تعيين (العنوان => uint256) public lastWithdrawTime ؛
رسم الخرائط (العنوان => uint256) الأرصدة العامة ؛
الودائع الوظيفية الأموال () الدائنة الخارجية {
أرصدة [msg.sender] + = msg.value ؛
}
دالة pullFunds (uint256 _weiToWithdraw) عامة {
تتطلب (أرصدة [msg.sender]> = _weiToWithdraw) ؛
// الحد من الانسحاب
تتطلب (_weiToWithdraw <= pullLimit) ؛
// تحديد الوقت المسموح به للانسحاب
تتطلب (الآن> = lastWithdrawTime [msg.sender] + 1 أسبوع) ؛
تتطلب (msg.sender.call.value (_weiToWithdraw) ()) ؛
أرصدة [msg.sender] - = _weiToWithdraw ؛
lastWithdrawTime [msg.sender] = الآن ؛
}
}
في العقد أعلاه ، لدينا وظيفتان عامتان ، [إيداع الأموال] و [الأموال المسحوبة]. تُستخدم [DepositFunds] لزيادة رصيد المرسل ، بينما تحدد [pullFunds] المبلغ المراد سحبه. في هذه الحالة ، سيكون ناجحًا إذا كان المبلغ المراد سحبه أقل من 1 إيثر.
يكمن المأزق هنا في الخط [17] حيث يتم نقل الأثير. يمكن للمهاجم إنشاء عقد ضار مع عنوان عقد [EtherStores] باعتباره معلمة المنشئ الوحيدة. هذا من شأنه أن يجعل [etherStore] متغيرًا عامًا ، وبالتالي أكثر عرضة للهجوم.
نهج QuilllAudit
نحن نتبع تقنيات مختلفة لتجنب نقاط الضعف المحتملة في إعادة الدخول في العقود الذكية. الطريقة الأولى وأفضل طريقة ممكنة هي استخدام وظيفة [النقل] المدمجة عند نقل الأثير إلى أي عقد خارجي.
ثانيًا ، من المهم التأكد من أن جميع التغييرات المنطقية في متغيرات الحالة يجب أن تتم قبل إرسال الأثير من العقد. في مثال [EtherStore] ، يجب وضع الأسطر [18] و [19] قبل السطر [17].
يمكن أيضًا استخدام تقنية ثالثة لمنع المكالمات المتكررة ؛ من خلال إدخال كائن المزامنة (mutex). إنها إضافة لمتغير الحالة الذي سيغلق العقد أثناء تنفيذ الكود.
3. الرؤى الافتراضية
هناك محددات رؤية للوظائف التي نستخدمها في Solidity ، وهي تحدد الطريقة التي يمكن تسميتها بها. إن الرؤية هي التي تحدد استدعاء الوظائف ؛ خارجيًا بواسطة المستخدمين ، بموجب عقود مشتقة أخرى ، داخليًا فقط أو خارجيًا فقط. دعونا نلقي نظرة على كيف أن الاستخدام الخاطئ لمحددات الرؤية يمكن أن يتسبب في ضعف كبير في العقود الذكية.
الضعف
بشكل افتراضي ، تكون رؤية الوظيفة [عامة] ، وبالتالي يمكن للمستخدمين الخارجيين استدعاء الوظائف بدون رؤية محددة. ينشأ الخطأ عندما ينسى المطورون تحديد رؤية الوظائف التي يجب أن تكون خاصة (أو يمكن استدعاؤها ضمن العقد نفسه). على سبيل المثال؛
عقد HashForEther {
وظيفة pullWinnings () {
// الفائز إذا كانت آخر 8 أحرف سداسية عشرية من العنوان تساوي 0
تتطلب (uint32 (msg.sender) == 0) ؛
_sendWinnings () ،
}
الوظيفة _sendWinnings () {
msg.sender.transfer (this.balance) ؛
}
}
العقد أعلاه عبارة عن لعبة مكافأة بسيطة للتخمين في العناوين. في هذا ، يمكننا أن نرى أن رؤية الوظائف غير محددة ، خاصةً وظيفة [_sendWinnings] هي [عامة] (افتراضيًا) ، وبالتالي يمكن استدعاء هذا من خلال أي عنوان لسرقة المكافأة.
نهج QuillAudit
يتكون فريقنا الداخلي من مطورين متمرسين يتبعون دائمًا أفضل ممارسات التدقيق ، وهنا يجب تحديد رؤية الوظائف بشكل صريح ، حتى لو تم إبقائها عامة ، يجب ذكرها.
4. حماية استخدام المنشئين
بشكل عام ، يُطلق على المُنشئين وظائف خاصة تُستخدم لأداء المهام الحرجة والمتميزة أثناء تهيئة العقود. قبل سوليديتي [v0.4.22] ، كان المصممون يحملون نفس الاسم المستخدم في العقد الذي يتضمنهم. الآن ، ضع في اعتبارك حالة تم فيها تغيير اسم العقد أثناء مرحلة التطوير ولكن يظل اسم المُنشئ كما هو ، يمكن أن توفر هذه الثغرة أيضًا للمهاجمين مدخلًا سهلاً إلى عقدك الذكي.
الضعف
يمكن أن يؤدي إلى عواقب وخيمة إذا تم تعديل اسم العقد ولكن اسم المنشئ لم يتغير. على سبيل المثال:
مالك العقد
العنوان العام للمالك؛
// البناء
function ownerWallet (address _ ownerer) public {
المالك = _المالك ؛
}
// تراجع. جمع الأثير.
دالة () مستحقة الدفع {}
وظيفة سحب () عامة {
يتطلب (msg.sender == مالك) ؛
msg.sender.transfer (this.balance) ؛
}
}
في العقد أعلاه ، يمكننا أن نرى أنه يمكن للمالك فقط سحب الأثير من خلال استدعاء وظيفة [سحب]. هنا ، تحدث الثغرة الأمنية عندما يتم تسمية المنشئ بشكل مختلف عن العقد (الحرف الأول مختلف!). وبالتالي يمكن للمستغل استدعاء وظيفة [ownerWallet] وتفويض نفسه كمالك ، ثم يسحب كل الأثير في العقد عن طريق استدعاء [سحب].
نهج QuillAudit
نحن نلتزم بالإصدار [0.4.22] من مترجم Solidity. قدم هذا الإصدار كلمة أساسية ؛ [المُنشئ] الذي يتطلب أن يتطابق اسم الوظيفة مع اسم العقد.
5. مصادقة أصل TX
هنا ، [Tx.Origin] هو المتغير العالمي لـ Solidity ، ويحتوي على عنوان الحساب الذي نفذ المكالمة أو المعاملة في الأصل. لا يمكن استخدام هذا المتغير للمصادقة ، لأن القيام بذلك يجعل العقد عرضة لهجمات التصيد الاحتيالي.
الضعف
تتعرض العقود التي تسمح للمستخدمين من خلال متغير [tx.origin] لهجمات خارجية تدفع المستخدمين إلى تنفيذ إجراءات مصادقة على العقد الخاطئ. ضع في اعتبارك المثال أدناه:
عقد phishable {
العنوان العام للمالك؛
المُنشئ (العنوان _المالك) {
المالك = _المالك ؛
}
الدالة () الدفع الخارجي {} // جمع الأثير
دالة pullAll (عنوان _recipient) عام {
تتطلب (tx.origin == مالك) ؛
_recipient.transfer (this.balance) ؛
}
}
هنا في السطر [11] ، يصرح العقد بوظيفة [pullAll] بمساعدة [tx.origin].
نهج QuillAudit
نتجنب عمومًا استخدام [tx.origin] للحصول على تفويض في العقود الذكية. على الرغم من أن استخدام [tx.origin] ليس محظورًا تمامًا ، إلا أنه يحتوي على بعض حالات الاستخدام المحددة. يمكننا استخدام [tx.origin] لرفض استدعاء العقود الخارجية للعقد الحالي ، ويمكن تنفيذه باستخدام [يتطلب] النموذج [يتطلب (tx.origin == msg.sender)]. يتم ذلك لتجنب استدعاء العقود الوسيطة لاستدعاء العقد الحالي الذي يقصر العقد على عناوين عادية بدون تشفير.
الختام النهائي
لقد غطينا بشكل شامل المزالق الخمسة الشائعة في لغة Solidity. أثناء تطوير العقود الذكية ، يجب ألا ننسى أنها غير قابلة للتغيير حسب التصميم ، مما يعني أنه بمجرد إنشائها ، لا توجد طريقة لتصحيح الكود المصدري.
يمثل هذا تحديًا كبيرًا للمطورين للاستفادة من أدوات اختبار الأمان والتدقيق المتاحة قبل النشر.
اكتشاف التهديدات الخبيثة المحتملة للعقود الذكية ، والمخاطر التي ذكرنا بعضها أعلاه يتم تنفيذها بطريقة فريدة وقوية للغاية من قبل فريق خبراء التدقيق الداخلي لدينا. نحن في QuillAudits نبذل قصارى جهدنا في البحث الأمني للحفاظ على عقدك محدثًا بجميع ممارسات أمان البرامج للحفاظ على عقدك آمنًا وآمنًا.
تواصل مع QuillHash
مع وجود الصناعة لسنوات ، ريشة قدمت حلول المؤسسات في جميع أنحاء العالم. QuillHash مع فريق من الخبراء هي شركة رائدة في تطوير blockchain تقدم حلول صناعية مختلفة بما في ذلك DeFi enterprise ، إذا كنت بحاجة إلى أي مساعدة في تدقيق العقود الذكية ، فلا تتردد في التواصل مع خبرائنا هنا!
اتبع QuillHash لمزيد من التحديثات
المصدر: https://blog.quillhash.com/2021/06/04/top-5-common-errors-in-solidity-programming-language/
- 11
- حسابي
- مميزات
- الكل
- التدقيق
- التحقّق من المُستخدم
- ترخيص
- أفضل
- سلسلة كتلة
- علة
- البق
- دعوة
- الحالات
- سبب
- تحدى
- الكود
- مشترك
- حول الشركة
- عقد
- عقود
- حالياًّ
- DAO
- الصدمة
- تصميم
- المطور
- المطورين
- التطوير التجاري
- مشروع
- الأثير
- ethereum
- الحدث/الفعالية
- خبرائنا
- فيسبوك
- مالي
- الاسم الأول
- اتباع
- النموذج المرفق
- مجانًا
- وظيفة
- مستقبل
- لعبة
- GAS
- العالمية
- عظيم
- الإختراق
- هنا
- كيفية
- HTTPS
- ضخم
- بما فيه
- العالمية
- IT
- لغة
- قيادة
- قيادة
- خط
- لينكدين:
- قائمة
- مباراة
- أخرى
- كاتوا ديلز
- بقعة
- نمط
- التصيد
- هجمات التصيد
- يصف
- يقدم
- خاص
- برمجة وتطوير
- جمهور
- سحب
- بحث
- استجابة
- REST
- خزنة
- أمن
- خدماتنا
- طقم
- الاشارات
- صغير
- سمارت
- عقد الذكية
- العقود الذكية
- So
- تطبيقات الكمبيوتر
- صلابة
- الحلول
- الولايه او المحافظه
- تحقيق النجاح
- الاختبار
- المصدر
- التهديدات
- الوقت
- تيشرت
- 5 الأعلى
- صفقة
- المعاملات
- us
- المستخدمين
- قيمنا
- قبو
- رؤية
- نقاط الضعف
- الضعف
- الضعيفة
- أسبوع
- من الذى
- في غضون
- سنوات