Rust akıllı sözleşmeler güvenliği: 3 büyük anahtar strateji DoS saldırılarına karşı savunma

Rust akıllı sözleşmeler güvenliği: hizmet reddi saldırısına karşı savunma

hizmet reddi saldırısı(DoS) saldırıları, akıllı sözleşmelerin bir süre boyunca normal bir şekilde kullanılamamasına veya hatta kalıcı olarak devre dışı kalmasına neden olabilir. Başlıca nedenler şunlardır:

  1. Sözleşme mantığında hesaplama karmaşıklığına bağlı bir hata var, bu da Gas tüketiminin sınırları aşmasına neden oluyor.

  2. Diğer akıllı sözleşmelerin çağrılması sırasında dış akıllı sözleşmelerin yürütme durumu üzerinde bağımlılık, dış akıllı sözleşmeler tarafından engellenebilir.

  3. Sözleşme sahibi özel anahtarını kaybederse, kritik ayrıcalık işlevlerini yerine getiremez.

Aşağıda somut örneklerle analiz yapılacaktır.

1. Dışarıdan kontrol edilebilen büyük veri yapılarında gezinmekten kaçının

Aşağıda bir "temettü" akıllı sözleşmesi bulunmaktadır, DoS riski mevcuttur:

pas #[near_bindgen] #[derive(BorshDeserialize, BorshSerialize)] pub struct Sözleşme { pub kayıtlı: Vec, pub accounts: UnorderedMap<accountid, balance="">, }

pub fn register_account(&mut self) { eğer self.accounts.insert(&env::predecessor_account_id(), &0).is_some() { env::panic("Hesap zaten kayıtlı".to_string().as_bytes()); } else { self.registered.push(env::predecessor_account_id()); } log!("Kayıtlı hesap {}", env::önceki_hesap_id()); }

pub fn distribute_token(&mut self, amount: u128) { assert_eq!(env::predecessor_account_id(), DAĞITICI, "ERR_NOT_ALLOWED");

for cur_account in 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!("Hesaba {} dağıtmaya çalışın", &cur_account);
    
    ext_ft_token::ft_transfer(
        cur_account.clone(),
        miktar,
        &FTTOKEN,
        0,
        TEKÇAĞRI İÇİN GAZ
    );
}

}

Bu sözleşmenin sorunu, registered dizisinin boyutunun bir sınırı olmaması, kötü niyetli kullanıcılar tarafından kontrol edilerek çok büyük hale getirilebilir, bu da distribute_token fonksiyonunun Gas tüketiminin sınırı aşmasına neden olur.

Önerilen çözüm "çekim" modunu benimsemektir:

pas pub fn distribute_token(&mut self, amount: u128) { assert_eq!(env::predecessor_account_id(), DAĞITICI, "ERR_NOT_ALLOWED");

for account in self.registered.iter() {
    let balance = self.accounts.get(&account).unwrap();
    self.accounts.insert(&account, &(bakiye + miktar));
}

}

pub fn withdraw(&mut self) { let account = env::predecessor_account_id(); let amount = self.accounts.get(&account).unwrap(); self.accounts.insert(&account, &0);

ext_ft_token::ft_transfer(hesap, miktar, &FTTOKEN, 0, GAS_FOR_SINGLE_CALL);

}

2. Diğer sözleşmelere bağlı durum çağrılarından kaçının

Aşağıda bir "ihale" akıllı sözleşme örneği bulunmaktadır:

pas #[near_bindgen] #[derive(BorshDeserialize, BorshSerialize)] pub struct Sözleşme { pub kayıtlı: Vec, pub bid_price: UnorderedMap\u003caccountid,balance\u003e, mevcut_lider: HesapId, en yüksek teklif: u128, }

PromiseOrValue { assert!(miktar > self.en yüksek teklif);

eğer self.current_leader == DEFAULT_ACCOUNT {
    self.current_leader = sender_id;
    self.highest_bid = amount;
} else {
    ext_ft_token::account_exist(
        self.current_leader.clone)(,
        &FTTOKEN,
        0,
        env::önceden ödenmiş_gas() - TEK_CALL_IÇIN_GAS * 4,
    (.then)ext_self::account_resolve)
        gönderici_id,
        miktar,
        &env::current_account_id((,
        0,
        GAS_FOR_SINGLE_CALL * 3,
    ();
}

PromiseOrValue::Value)0)

}

#( pub fn account_resolve)&mut self, sender_id: AccountId, amount: u128[private] { match env::promise_result(0) { PromiseResult::Başarılı(_) => { 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 = amount; } PromiseResult::Başarısız => { ext_ft_token::ft_transfer) sender_id.clone)(, miktar, &FTTOKEN, 0, GAS_FOR_SINGLE_CALL * 2, (; log!)"Şimdi Geri Dön"); } PromiseResult::NotReady => unreachable!(), }; }

Bu sözleşmenin sorunlarından biri, önceki en yüksek teklif sahibinin hesabını iptal etmesi durumunda, yeni teklif verenlerin durumu başarılı bir şekilde güncelleyememesidir.

Çözüm, makul bir hata yönetimi uygulamaktır; örneğin, geri alınamayan tokenleri geçici olarak depolamak, daha sonra kullanıcı tarafından alınmasını sağlamak.

pas pub struct Sözleşme { // ... pub kayıp_bulunan: UnorderedMap<accountid, balance="">, }

pub fn account_resolve(&mut self, sender_id: AccountId, amount: u128) { eşleşme env::promise_result(0) { PromiseResult::Successful(_) => { // Normal iade mantığı } PromiseResult::Başarısız => { // Geri alınamayacak tokenler geçici olarak saklanacak let lost_amount = self.lost_found.get(&self.current_leader).unwrap_or(0); self.lost_found.insert(&self.current_leader, &)kayıp_miktar + self.highest_bid((;

        // Durumu güncelle
        self.current_leader = sender_id;
        self.en yüksek teklif = amount;
    }
    PromiseResult::NotReady => ulaşılamaz!)),
}

}

pub fn withdraw_lost_found(&mut self) { let account = env::predecessor_account_id(); let amount = self.lost_found.get(&account).unwrap_or(0); eğer miktar > 0 { self.lost_found.insert(&account, &0); ext_ft_token::ft_transfer(hesap, miktar, &FTTOKEN, 0, GAS_FOR_SINGLE_CALL); } }

3. Tek nokta arızasından kaçınma

Sözleşme sahibinin özel anahtarının kaybolması, kritik ayrıcalık işlevlerinin kullanılamamasına neden olur. Çözüm, çoklu imza mekanizmasının benimsenmesidir:

pas pub struct Sözleşme { pub sahipleri: Vec\u003caccountid\u003e, gerekli_onaylar: u64, pub işlemler: Vec, }

pub fn propose_transaction(&mut self, transaction: Transaction) { assert!(self.owners.contains)&env::predecessor_account_id(((, "Sahip değil"); self.transactions.push)transaction); }

pub fn confirm_transaction(&mut self, transaction_id: u64) { assert!(self.owners.contains)&env::predecessor_account_id(((, "Sahip değil");

let transaction = &mut self.transactions[transaction_id as usize];
transaction.onaylar += 1;

eğer işlem.onayları >= self.gerekli_onaylar {
    self.execute_transaction)transaction_id);
}

}

fn execute_transaction(&mut self, transaction_id: u64) { let transaction = self.transactions.remove(transaction_id as usize); // İşlem mantığını yürüt }

Çoklu imza mekanizması sayesinde, tek bir sahibi anahtarının kaybolmasının neden olduğu sözleşme çökmesini önleyebilir, sözleşmenin merkeziyetsizliğini ve güvenliğini artırır.

</accountid,></accountid,balance></accountid,>

View Original
This page may contain third-party content, which is provided for information purposes only (not representations/warranties) and should not be considered as an endorsement of its views by Gate, nor as financial or professional advice. See Disclaimer for details.
  • Reward
  • 6
  • Share
Comment
0/400
TokenomicsTherapistvip
· 19h ago
Özel Anahtar'ı kaybetmek çok gerçekçi haha
View OriginalReply0
GasFeeNightmarevip
· 08-04 04:49
不愧是Gas Büyük Yatırımcılar
View OriginalReply0
PretendingToReadDocsvip
· 08-04 04:49
DoS'dan kaçış yok, başka hangi güvenlikten bahsedebiliriz?
View OriginalReply0
HashRatePhilosophervip
· 08-04 04:32
rust ordusu geliyor, rakip titresin.
View OriginalReply0
TestnetFreeloadervip
· 08-04 04:28
防dos sen burada bu tuzak teorisini mi kullanıyorsun
View OriginalReply0
MevShadowrangervip
· 08-04 04:26
Gas ücreti patladı, ben mahvoldum.
View OriginalReply0
  • Pin
Trade Crypto Anywhere Anytime
qrCode
Scan to download Gate app
Community
  • 简体中文
  • English
  • Tiếng Việt
  • 繁體中文
  • Español
  • Русский
  • Français (Afrique)
  • Português (Portugal)
  • Bahasa Indonesia
  • 日本語
  • بالعربية
  • Українська
  • Português (Brasil)