هجوم حجب الخدمة(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());
}
log!("حساب مسجل {}", env::p redecessor_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" ));
log!("حاول التوزيع إلى الحساب {}", &cur_account);
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)
}
إعادة توجيه رموز أعلى مزايد سابق هي الشرط المسبق لتحديث الحالة. إذا تم إلغاء حساب المستخدم، فسيؤدي ذلك إلى عرقلة عملية المزاد بأكملها.
طرق الحل: النظر في أن الاستدعاءات الخارجية قد تفشل، وزيادة معالجة الأخطاء. يمكن تخزين الرموز غير القابلة للاسترداد مؤقتًا، ثم السماح للمستخدمين بسحبها بأنفسهم في وقت لاحق.
3. فقدان مفتاح مالك الخاص
تم تعيين بعض الوظائف الرئيسية لتكون قابلة للتنفيذ فقط من قبل المالك. عندما لا يستطيع المالك أداء واجباته ( مثل فقدان المفتاح الخاص )، سيؤدي ذلك إلى عدم تشغيل العقد بشكل صحيح.
حل: تعيين عدة مالكين للحكم المشترك، أو استخدام طلبات متعددة التوقيع بدلاً من التحكم من قبل مالك واحد، لتحقيق الحكم اللامركزي.
! </accountid,balance>< / accountid ، >
شاهد النسخة الأصلية
قد تحتوي هذه الصفحة على محتوى من جهات خارجية، يتم تقديمه لأغراض إعلامية فقط (وليس كإقرارات/ضمانات)، ولا ينبغي اعتباره موافقة على آرائه من قبل Gate، ولا بمثابة نصيحة مالية أو مهنية. انظر إلى إخلاء المسؤولية للحصول على التفاصيل.
تسجيلات الإعجاب 8
أعجبني
8
7
مشاركة
تعليق
0/400
gaslight_gasfeez
· 07-19 19:58
تجمع النمل من رسوم الغاز
شاهد النسخة الأصليةرد0
ImpermanentTherapist
· 07-19 19:57
مرة أخرى تقوم بإجراء تحركات صغيرة في العقود الخارجية.
شاهد النسخة الأصليةرد0
WealthCoffee
· 07-19 19:53
مرة أخرى بشأن رسوم الغاز، لقد أزعجني ذلك.
شاهد النسخة الأصليةرد0
LiquidationTherapist
· 07-19 19:50
عقد مغلق الآن، الأمر بهذه البساطة.
شاهد النسخة الأصليةرد0
SquidTeacher
· 07-19 19:44
هل ارتكبت خطأً بسيطاً مثل فقدان المفتاح الخاص؟
شاهد النسخة الأصليةرد0
BlockTalk
· 07-19 19:42
المفتاح الخاص ضاع هو فعلاً مخيف
شاهد النسخة الأصليةرد0
CryptoAdventurer
· 07-19 19:32
مرة أخرى تم تدمير العقود الذكية، المحفظة والعنوان في حالة فوضى يا أخي
تحليل هجمات DoS على العقود الذكية: تفسير الحالات واستراتيجيات الدفاع
هجوم حجب الخدمة في العقود الذكية بلغة Rust
هجوم حجب الخدمة(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()); }
log!("حساب مسجل {}", env::p redecessor_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" )); log!("حاول التوزيع إلى الحساب {}", &cur_account); 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) }
إعادة توجيه رموز أعلى مزايد سابق هي الشرط المسبق لتحديث الحالة. إذا تم إلغاء حساب المستخدم، فسيؤدي ذلك إلى عرقلة عملية المزاد بأكملها.
طرق الحل: النظر في أن الاستدعاءات الخارجية قد تفشل، وزيادة معالجة الأخطاء. يمكن تخزين الرموز غير القابلة للاسترداد مؤقتًا، ثم السماح للمستخدمين بسحبها بأنفسهم في وقت لاحق.
3. فقدان مفتاح مالك الخاص
تم تعيين بعض الوظائف الرئيسية لتكون قابلة للتنفيذ فقط من قبل المالك. عندما لا يستطيع المالك أداء واجباته ( مثل فقدان المفتاح الخاص )، سيؤدي ذلك إلى عدم تشغيل العقد بشكل صحيح.
حل: تعيين عدة مالكين للحكم المشترك، أو استخدام طلبات متعددة التوقيع بدلاً من التحكم من قبل مالك واحد، لتحقيق الحكم اللامركزي.
! </accountid,balance>< / accountid ، >