هجوم حجب الخدمة(DoS)قد يؤدي إلى عدم قدرة العقود الذكية على العمل بشكل صحيح لفترة من الوقت أو حتى بشكل دائم. تشمل الأسباب الرئيسية ما يلي:
عيوب في منطق العقد، مثل ارتفاع التعقيد الحسابي لبعض الدوال العامة، مما يؤدي إلى استهلاك الغاز يتجاوز الحدود.
الاعتماد على حالة تنفيذ العقود الخارجية عند استدعاء العقود المتعددة، قد يؤدي عدم موثوقية تنفيذ العقود الخارجية إلى عرقلة التشغيل الطبيعي لهذا العقد.
العوامل البشرية، مثل فقدان مالك العقد للمفتاح الخاص مما يمنع استدعاء بعض الدوال المميزة.
سوف نقوم بتحليل ثغرات هجوم حجب الخدمة في العقود الذكية من خلال أمثلة محددة.
1. التكرار عبر الهياكل البيانات الكبيرة القابلة للتعديل من الخارج
以下 هو عقد بسيط لتوزيع "الأرباح" على المستخدمين المسجلين:
صدأ
#[near_bindgen]
#[derive(BorshDeserialize ، BorshSerialize)]
عقد بنية pub {
الحانة المسجلة: Vec ،
حسابات pub: UnorderedMap<accountid, balance="">,
}
pub fn register_account(&mut self) {
إذا كان self.accounts.insert(&env::p redecessor_account_id(), &0).is_ some() {
env::panic('تم تسجيل الحساب بالفعل'.to_string().as_bytes());
}else{
self.registered.push(env::p redecessor_account_id());
}
سجل!('الحساب المسجل{}',env::predecessor_account_id());
}
pub fn distribute_token(& mut self, amount: u128) {
assert_eq!(env::p redecessor_account_id(),DISTRIBUTOR,'ERR_NOT_ALLOWED');
ل cur_account في self.registered.iter(){
Let balance = self.accounts.get(&cur_account).expect('ERR_GET');
self.accounts.insert(&cur_account,&balance.checked_add(amount).expect('ERR_ ADD'));
سجل!('حاول توزيع إلى الحساب{}',&الحساب_الحالي);
ext_ft_token::ft_transfer(
cur_account.clone(),
المبلغ,
و FTTOKEN ،
0,
GAS_FOR_SINGLE_CALL
);
}
}
تكمن المشكلة في العقد في عدم وجود حد لحجم مصفوفة self.registered، مما يمكن المستخدمين الخبيثين من التلاعب بها بحيث تصبح كبيرة جدًا، مما يؤدي إلى استهلاك غاز يتجاوز الحد عند تنفيذ دالة distribute_token.
التوصيات للحلول:
تحديد الحد الأقصى لطول مصفوفة self.registered
استخدام وضع السحب، دون توزيع المكافآت بشكل نشط، بل السماح للمستخدمين باستدعاء دالة السحب بأنفسهم
!
2. اعتماد حالة العقد المتقاطع يؤدي إلى حظر العقد
اعتبر "عقد مزايدة":
صدأ
#[near_bindgen]
#[derive(BorshDeserialize ، BorshSerialize)]
عقد بنية pub {
الحانة المسجلة: Vec ،
pub bid_price: UnorderedMap<accountid,balance>,
pub current_leader: AccountId ،
حانة highest_bid: u128 ،
استرداد الحانة: بول
}
pub fn bid(&mut self, sender_id: AccountId, amount: u128) -> PromiseOrValue {
أكد!(amount > self.highest_bid);
إذا كانت القيادة الحالية هي DEFAULT_ACCOUNT {
self.current_leader = sender_id ؛
self.highest_bid = المبلغ ؛
} else {
ext_ft_token::account_exist(
self.current_leader.clone(),
و FTTOKEN ،
0,
env::p repaid_gas() - GAS_FOR_SINGLE_CALL * 4,
).then(ext_self::account_resolve(
sender_id،
المبلغ,
&env::current_account_id(),
0,
GAS_FOR_SINGLE_CALL * 3 ،
));
}
سجل!(
'current_leader: {} highest_bid: {}',
القائد الحالي الخاص به،
self.highest_bid
);
PromiseOrValue::Value(0)
}
تتمثل المشكلة في العقد في أنه إذا تم إلغاء حساب المستخدم الذي لديه أعلى عرض حالي في عقد الرموز الخارجية، فلن يتمكن العرض الجديد الأعلى من إعادة رموز السابق، مما يؤدي إلى تعطيل عملية المزايدة.
طريقة الحل:
يجب مراعاة الحالات التي قد تفشل فيها استدعاءات العقود الخارجية ، وتنفيذ معالجة أخطاء معقولة. على سبيل المثال ، يمكن الاحتفاظ بالرموز التي لا يمكن إرجاعها مؤقتًا في العقد ، مع السماح للمستخدمين بسحبها بأنفسهم في وقت لاحق.
3. فقدان المفتاح الخاص لمالك العقد
غالبًا ما توجد وظائف مميزة يمكن تنفيذها فقط من قبل المالك في العقود الذكية. إذا فقد مفتاح المالك الخاص، فلن يمكن استدعاء هذه الوظائف، مما قد يؤدي إلى عدم تشغيل العقد بشكل صحيح.
حلول:
إعداد عدة مالكين للعقود للحكم المشترك
اعتماد آلية التوقيع المتعدد بدلاً من التحكم في صلاحيات المالك الوحيد
تنفيذ خطة إدارة العقود الذكية اللامركزية
! </accountid,balance>< / accountid ، >
شاهد النسخة الأصلية
قد تحتوي هذه الصفحة على محتوى من جهات خارجية، يتم تقديمه لأغراض إعلامية فقط (وليس كإقرارات/ضمانات)، ولا ينبغي اعتباره موافقة على آرائه من قبل Gate، ولا بمثابة نصيحة مالية أو مهنية. انظر إلى إخلاء المسؤولية للحصول على التفاصيل.
تسجيلات الإعجاب 15
أعجبني
15
7
مشاركة
تعليق
0/400
consensus_whisperer
· منذ 23 س
أتحدث عن العقد الذي يجمع بين القليل من المهارة ومتعة اللعب.
شاهد النسخة الأصليةرد0
RumbleValidator
· 07-30 19:13
لقد رأيت مرة أخرى ثغرة حلقة ميتة بسيطة ، يجب أن تكون اختبارات الضغط للتحقق من العقدة قبل تصريف العقد في أقصى حد.
شاهد النسخة الأصليةرد0
GasGuzzler
· 07-30 19:12
خبير قمع رسوم الغاز! ينفجر مباشرة
شاهد النسخة الأصليةرد0
BtcDailyResearcher
· 07-30 19:10
مرة أخرى، وقع شخص ما ضحية لهجوم DoS، أضحكني ذلك.
شاهد النسخة الأصليةرد0
SignatureDenied
· 07-30 19:05
تم الهجوم مرة أخرى؟ من يجرؤ على تخزين المفتاح الخاص بشكل عشوائي؟
شاهد النسخة الأصليةرد0
DefiOldTrickster
· 07-30 19:02
العملاق الأبيض الذي لعب في سوق الدببة انتهى به الأمر إلى أن تم قفل عقده بواسطة مفتاح خاص مفقود، هش.
شاهد النسخة الأصليةرد0
RuntimeError
· 07-30 18:53
هم؟ هل يمكن أن يتم تدمير العقد بسبب فقدان المفتاح الخاص؟ حقاً إنه أمر عاجل!
العمق تحليل في العقود الذكية لثغرات هجوم DoS واستراتيجيات الوقاية
تحليل هجوم حجب الخدمة في العقود الذكية
هجوم حجب الخدمة(DoS)قد يؤدي إلى عدم قدرة العقود الذكية على العمل بشكل صحيح لفترة من الوقت أو حتى بشكل دائم. تشمل الأسباب الرئيسية ما يلي:
عيوب في منطق العقد، مثل ارتفاع التعقيد الحسابي لبعض الدوال العامة، مما يؤدي إلى استهلاك الغاز يتجاوز الحدود.
الاعتماد على حالة تنفيذ العقود الخارجية عند استدعاء العقود المتعددة، قد يؤدي عدم موثوقية تنفيذ العقود الخارجية إلى عرقلة التشغيل الطبيعي لهذا العقد.
العوامل البشرية، مثل فقدان مالك العقد للمفتاح الخاص مما يمنع استدعاء بعض الدوال المميزة.
سوف نقوم بتحليل ثغرات هجوم حجب الخدمة في العقود الذكية من خلال أمثلة محددة.
1. التكرار عبر الهياكل البيانات الكبيرة القابلة للتعديل من الخارج
以下 هو عقد بسيط لتوزيع "الأرباح" على المستخدمين المسجلين:
صدأ #[near_bindgen] #[derive(BorshDeserialize ، BorshSerialize)] عقد بنية pub { الحانة المسجلة: Vec ، حسابات pub: UnorderedMap<accountid, balance="">, }
pub fn register_account(&mut self) { إذا كان self.accounts.insert(&env::p redecessor_account_id(), &0).is_ some() { env::panic('تم تسجيل الحساب بالفعل'.to_string().as_bytes()); }else{ self.registered.push(env::p redecessor_account_id()); } سجل!('الحساب المسجل{}',env::predecessor_account_id()); }
pub fn distribute_token(& mut self, amount: u128) { assert_eq!(env::p redecessor_account_id(),DISTRIBUTOR,'ERR_NOT_ALLOWED'); ل cur_account في self.registered.iter(){ Let balance = self.accounts.get(&cur_account).expect('ERR_GET'); self.accounts.insert(&cur_account,&balance.checked_add(amount).expect('ERR_ ADD')); سجل!('حاول توزيع إلى الحساب{}',&الحساب_الحالي); ext_ft_token::ft_transfer( cur_account.clone(), المبلغ, و FTTOKEN ، 0, GAS_FOR_SINGLE_CALL ); } }
تكمن المشكلة في العقد في عدم وجود حد لحجم مصفوفة self.registered، مما يمكن المستخدمين الخبيثين من التلاعب بها بحيث تصبح كبيرة جدًا، مما يؤدي إلى استهلاك غاز يتجاوز الحد عند تنفيذ دالة distribute_token.
التوصيات للحلول:
!
2. اعتماد حالة العقد المتقاطع يؤدي إلى حظر العقد
اعتبر "عقد مزايدة":
صدأ #[near_bindgen] #[derive(BorshDeserialize ، BorshSerialize)] عقد بنية pub { الحانة المسجلة: Vec ، pub bid_price: UnorderedMap<accountid,balance>, pub current_leader: AccountId ، حانة highest_bid: u128 ، استرداد الحانة: بول }
pub fn bid(&mut self, sender_id: AccountId, amount: u128) -> PromiseOrValue { أكد!(amount > self.highest_bid); إذا كانت القيادة الحالية هي DEFAULT_ACCOUNT { self.current_leader = sender_id ؛ self.highest_bid = المبلغ ؛ } else { ext_ft_token::account_exist( self.current_leader.clone(), و FTTOKEN ، 0, env::p repaid_gas() - GAS_FOR_SINGLE_CALL * 4, ).then(ext_self::account_resolve( sender_id، المبلغ, &env::current_account_id(), 0, GAS_FOR_SINGLE_CALL * 3 ، )); } سجل!( 'current_leader: {} highest_bid: {}', القائد الحالي الخاص به، self.highest_bid ); PromiseOrValue::Value(0) }
#[private] pub fn account_resolve(&mut self,sender_id: AccountId,amount: u128) { مطابقة ENV::p romise_result(0) { PromiseResult::NotReady => غير قابل للوصول!(), PromiseResult::Successful(_) => { ext_ft_token::ft_transfer( self.current_leader.clone(), self.highest_bid، و FTTOKEN ، 0, GAS_FOR_SINGLE_CALL * 2 ، ); self.current_leader = sender_id ؛ self.highest_bid = المبلغ ؛ } PromiseResult::Failed = > { ext_ft_token::ft_transfer( sender_id.clone(), المبلغ, و FTTOKEN ، 0, GAS_FOR_SINGLE_CALL * 2 ، ); log!('عودة الآن'); } }; }
تتمثل المشكلة في العقد في أنه إذا تم إلغاء حساب المستخدم الذي لديه أعلى عرض حالي في عقد الرموز الخارجية، فلن يتمكن العرض الجديد الأعلى من إعادة رموز السابق، مما يؤدي إلى تعطيل عملية المزايدة.
طريقة الحل:
يجب مراعاة الحالات التي قد تفشل فيها استدعاءات العقود الخارجية ، وتنفيذ معالجة أخطاء معقولة. على سبيل المثال ، يمكن الاحتفاظ بالرموز التي لا يمكن إرجاعها مؤقتًا في العقد ، مع السماح للمستخدمين بسحبها بأنفسهم في وقت لاحق.
3. فقدان المفتاح الخاص لمالك العقد
غالبًا ما توجد وظائف مميزة يمكن تنفيذها فقط من قبل المالك في العقود الذكية. إذا فقد مفتاح المالك الخاص، فلن يمكن استدعاء هذه الوظائف، مما قد يؤدي إلى عدم تشغيل العقد بشكل صحيح.
حلول:
! </accountid,balance>< / accountid ، >