دليل عملي للوقاية من هجمات DoS على العقود الذكية Rust

يوميات تطوير العقود الذكية بلغة راست: الوقاية من هجوم حجب الخدمة

هجوم حجب الخدمة(DoS) قد يؤدي إلى عدم تمكن العقود الذكية من العمل بشكل طبيعي لفترة من الوقت أو حتى بشكل دائم. تشمل الأسباب الشائعة ما يلي:

  1. مشكلة تعقيد الحسابات في منطق العقد، مما يؤدي إلى استهلاك الغاز يتجاوز الحد.

  2. عند استدعاء العقود المتعددة، يعتمد بشكل غير صحيح على حالة التنفيذ للعقد الخارجي، مما يتسبب في حظر العقد الرئيسي.

  3. فقد مفتاح صاحب العقد، مما يؤدي إلى عدم القدرة على استدعاء الدوال المميزة، وعدم تحديث حالة النظام المهمة.

فيما يلي تحليل لثغرات هجوم حجب الخدمة وحلولها من خلال بعض الأمثلة المحددة.

1. التجول عبر هياكل البيانات الكبيرة القابلة للتعديل من الخارج

以下是一个简单的"分红"العقود الذكية,存在 هجوم حجب الخدمة风险:

صدأ #[near_bindgen] #[derive(BorshDeserialize ، BorshSerialize)] عقد بنية pub { الحانة المسجلة: Vec ، حسابات pub: UnorderedMap<accountid, balance="">, }

impl العقد { 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
        );
    }
}

}

المشكلة هي أن حجم مصفوفة registered غير محدود، ويمكن أن يتم التحكم به من قبل مستخدمين خبيثين ليصبح كبيرًا جدًا، مما يؤدي إلى استهلاك الغاز عند تنفيذ دالة distribute_token يتجاوز الحد.

اقتراح الحلول:

  1. تحديد حجم مصفوفة registered.

  2. اعتماد "سحب" الوضع، مما يسمح للمستخدمين بسحب المكافآت بأنفسهم، بدلاً من أن تقوم العقود الذكية بتوزيعها بشكل نشط.

!

2. الاعتماد على حالة العقود المتعددة يؤدي إلى حجب العقود

以下 هو مثال على "العقود الذكية" للمزايدة:

صدأ #[near_bindgen] #[derive(BorshDeserialize ، BorshSerialize)] عقد بنية pub { الحانة المسجلة: Vec ، pub bid_price: UnorderedMap<accountid,balance>, pub current_leader: AccountId ، حانة highest_bid: u128 ، استرداد الحانة: بول }

impl العقد { pub fn bid(&mut self, sender_id: AccountId, amount: u128) -> PromiseOrValue { أكد!(amount > self.highest_bid);

    إذا كانت القائد الحالي هو الحساب الافتراضي {
        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.current_leader،
        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. فقدان مفتاح مالك الخاص

توجد العديد من العقود التي تحتوي على وظائف خاصة يمكن تنفيذها فقط من قبل المالك. إذا فقد مفتاح المالك الخاص، فلن يمكن استدعاء هذه الوظائف، مما قد يؤدي إلى عدم عمل العقد بشكل طبيعي.

اقتراح الحلول:

  1. تعيين عدة مالكين للعقود لإدارة مشتركة.

  2. استخدام آلية التوقيع المتعدد بدلاً من السيطرة من قبل مالك واحد.

  3. تحقيق آلية حوكمة العقود اللامركزية.

من خلال الإجراءات المذكورة أعلاه، يمكن تقليل مخاطر هجوم حجب الخدمة في العقود الذكية بشكل فعال، وزيادة أمان العقد وموثوقيته.

! </accountid,balance>< / accountid ، >

شاهد النسخة الأصلية
قد تحتوي هذه الصفحة على محتوى من جهات خارجية، يتم تقديمه لأغراض إعلامية فقط (وليس كإقرارات/ضمانات)، ولا ينبغي اعتباره موافقة على آرائه من قبل Gate، ولا بمثابة نصيحة مالية أو مهنية. انظر إلى إخلاء المسؤولية للحصول على التفاصيل.
  • أعجبني
  • 8
  • مشاركة
تعليق
0/400
MEVHunterWangvip
· منذ 12 س
إنه ليس بالأمر الصعب التحكم في العقد.
شاهد النسخة الأصليةرد0
ProofOfNothingvip
· منذ 16 س
مرة أخرى ، هي مجرد كلمات على الورق بدون فعل
شاهد النسخة الأصليةرد0
LuckyHashValuevip
· منذ 19 س
الهجوم لم يُصد، وسيعود انخفاض إلى الصفر
شاهد النسخة الأصليةرد0
ColdWalletGuardianvip
· منذ 19 س
معرفة أساسية للبدء في البلوكتشين
شاهد النسخة الأصليةرد0
SelfSovereignStevevip
· منذ 19 س
المفتاح الخاص丢失就惨了
شاهد النسخة الأصليةرد0
StableBoivip
· منذ 19 س
هذه العقد تحمل مخاطر كثيرة حقًا، والاستقرار ليس جيدًا جدًا.
شاهد النسخة الأصليةرد0
Ser_This_Is_A_Casinovip
· منذ 19 س
آه ~ لغة Rust صعبة للغاية، لماذا لا نفكر في Solidity؟
شاهد النسخة الأصليةرد0
GasFeeThundervip
· منذ 19 س
تناول الكثير من الغازات والحصول على شعر؟ عاجلا أم آجلا ، سيتم القضاء على العقد
شاهد النسخة الأصليةرد0
  • تثبيت