Analyse des vulnérabilités des attaques DoS sur les smart contracts Rust et solutions

Attaque par déni de service dans les smart contracts Rust

attaque par déni de service(DoS) peut entraîner des smart contracts étant incapables de fonctionner correctement pendant une période de temps ou même de manière permanente. Les principales raisons incluent :

  1. La logique du contrat présente des défauts, comme une complexité de calcul trop élevée pour certaines fonctions, entraînant une consommation de Gas dépassant la limite.

  2. Dans les appels inter-contrats, l'exécution du contrat dépend de l'état des contrats externes et peut être bloquée par des contrats externes.

  3. Facteurs humains, tels que la perte de la clé privée par le propriétaire du contrat, entraînant l'incapacité d'appeler les fonctions privilégiées.

Voici une analyse des vulnérabilités d'attaque par déni de service dans les smart contracts à travers des exemples concrets.

1. Parcourir de manière itérative de grandes structures de données modifiables par des sources externes

Voici un simple contrat pour distribuer des dividendes aux utilisateurs inscrits :

rouille #[near_bindgen] #[derive(BorshDeserialize, BorshSerialize)] pub struct Contract { pub registered: Vec, pub accounts: UnorderedMap\u003caccountid, balance=""\u003e, }

impl Contrat { pub fn register_account(&mut self) { if self.accounts.insert(&env::predecessor_account_id(), &0).is_some() { env::panic("Le compte est déjà enregistré".to_string().as_bytes()); } else { self.registered.push(env::predecessor_account_id()); } log!("enregistrer le compte {}", env::predecessor_account_id()); }

pub fn distribute_token(&mut self, amount: u128) {
    assert_eq!(env::predecessor_account_id(), DISTRIBUTOR, "Pas de droit d'opérer");
    pour compte dans self.registered.iter() {
        let balance = self.accounts.get(&account).expect("获取失败");
        self.accounts.insert(\u0026account, \u0026balance.checked_add(amount).expect("加法溢出")); 
        log!("Essayer de distribuer au compte {}", &account);
        ext_ft_token::ft_transfer(
            account.clone(),
            montant,
            &FTTOKEN,
            0,
            GAS_FOR_SINGLE_CALL
        );
    }
}

}

Le problème de ce contrat est que la taille du tableau registered n'est pas limitée, ce qui permet à des utilisateurs malveillants de le manipuler pour qu'il devienne trop grand, entraînant une consommation de Gas excessive pour la fonction distribute_token.

Solutions recommandées:

Reconcevoir le contrat en mode de retrait. Permettre aux utilisateurs d'appeler activement la fonction de retrait pour obtenir des récompenses, le contrat n'a besoin que d'enregistrer le montant des récompenses que l'utilisateur peut retirer.

2. La dépendance d'état entre contrats entraîne un blocage

Considérez un contrat d'enchères :

rouille #[near_bindgen] #[derive(BorshDeserialize, BorshSerialize)] pub struct Contract { pub registered: Vec\u003caccountid\u003e, pub bid_price: UnorderedMap\u003caccountid,balance\u003e, pub current_leader: AccountId, pub highest_bid: u128, pub refund: bool }

impl Contrat { PromiseOrValue { assert!(amount > self.highest_bid); if 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::prepaid_gas() - GAS_FOR_SINGLE_CALL * 4, (.then)ext_self::account_resolve) sender_id, montant, &env::current_account_id((, 0, GAS_FOR_SINGLE_CALL * 3, (); } log!) "Enchérisseur actuel: {} Meilleure enchère: {}", self.current_leader, self.highest_bid ); PromiseOrValue::Value(0) }

#(
pub fn account_resolve)&mut self, sender_id: AccountId, amount: u128[private] {
    match env::promise_result(0) {
        PromiseResult::NotReady => inaccessible!(),
        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 = amount;
        }
        PromiseResult::Failed => {
            ext_ft_token::ft_transfer)
                sender_id.clone)(,
                montant,
                &FTTOKEN,
                0,
                GAS_FOR_SINGLE_CALL * 2,
            (;
            log!)"retourner l'offre actuelle");
        }
    };
}

}

Le problème du contrat est le suivant : il est nécessaire de retourner avec succès les jetons de l'enchérisseur précédent pour pouvoir mettre à jour l'enchère la plus élevée. Si l'enchérisseur précédent a annulé son compte, le contrat ne pourra pas effectuer le remboursement et sera bloqué.

Solution :

Considérer les cas où les appels de contrats externes peuvent échouer et mettre en œuvre un traitement des erreurs raisonnable. Il est possible de garder temporairement les jetons non remboursables dans le contrat, puis de permettre aux utilisateurs de les retirer activement par la suite.

3. Perte de la clé privée du propriétaire du contrat

Certaines fonctions de contrat sont définies comme uniquement exécutables par le propriétaire, pour modifier des variables système critiques. Si la clé privée du propriétaire est perdue, ces fonctions ne pourront pas être appelées, ce qui pourrait entraîner un dysfonctionnement du contrat.

Solution :

Mettre en place plusieurs propriétaires de contrat pour une gouvernance conjointe, ou adopter un mécanisme de multi-signatures pour remplacer le contrôle des permissions d'un seul propriétaire, afin de réaliser une gouvernance décentralisée.

</accountid,balance><accountid,>

Voir l'original
Cette page peut inclure du contenu de tiers fourni à des fins d'information uniquement. Gate ne garantit ni l'exactitude ni la validité de ces contenus, n’endosse pas les opinions exprimées, et ne fournit aucun conseil financier ou professionnel à travers ces informations. Voir la section Avertissement pour plus de détails.
  • Récompense
  • 8
  • Partager
Commentaire
0/400
WhaleWatchervip
· 07-20 17:14
Un contrat est une passoire, n'est-ce pas ?
Voir l'originalRépondre0
CryptoSourGrapevip
· 07-20 17:08
Si j'avais su cette faille plus tôt, pourquoi devrais-je tomber à vendre ma misère tous les jours maintenant.
Voir l'originalRépondre0
PancakeFlippavip
· 07-18 18:19
Les contrats ont aussi des seuils, n'est-ce pas ? Qui vous a dit que vos compétences étaient faibles ?
Voir l'originalRépondre0
LazyDevMinervip
· 07-17 19:29
On parlera de coder dans la prochaine vie 8
Voir l'originalRépondre0
NftPhilanthropistvip
· 07-17 19:28
en fait... *boit du thé* un autre contrat peu efficace en gas qui pourrait être optimisé pour un impact social. quand les développeurs comprendront-ils l'importance des pratiques de codage réfléchies smh
Voir l'originalRépondre0
just_another_walletvip
· 07-17 19:20
Les frères doivent vraiment prendre au sérieux les problèmes de sécurité.
Voir l'originalRépondre0
NFTragedyvip
· 07-17 19:16
Ce problème, eh bien, le code n'est même pas terminé...
Voir l'originalRépondre0
HalfBuddhaMoneyvip
· 07-17 19:01
Je suis désolé, je dois encore combler des lacunes dans ce contrat poubelle.
Voir l'originalRépondre0
Trader les cryptos partout et à tout moment
qrCode
Scan pour télécharger Gate app
Communauté
Français (Afrique)
  • 简体中文
  • English
  • Tiếng Việt
  • 繁體中文
  • Español
  • Русский
  • Français (Afrique)
  • Português (Portugal)
  • Bahasa Indonesia
  • 日本語
  • بالعربية
  • Українська
  • Português (Brasil)