# Rustスマートコントラクト中的サービス拒否攻撃サービス拒否(DoS)攻撃はスマートコントラクトを一定期間正常に使用できなくします。主に以下のような理由があります:1. コントラクトのロジックに計算の複雑さに関する欠陥が存在し、Gasの消費が制限を超えています。2. クロスコントラクト呼び出し時、コントラクトの実行は信頼できない外部コントラクトの状態に依存し、ブロックが発生します。3. 契約所有者が秘密鍵を紛失したため、鍵の特権機能を実行できなくなります。以下の具体例を通じて、これらのサービス拒否攻撃の脆弱性を分析します。## 1. 外部から変更可能な大規模データ構造を遍歴する以下はシンプルな"分配"スマートコントラクトで、DoSリスクがあります:錆#[near_bindgen]#[derive(BorshDeserialize、BorshSerialize)]pub struct コントラクト { パブ登録:Vec<accountid>、 パブアカウント: 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(), ディストリビューター, "ERR_NOT_ALLOWED"); for cur_account in self.registered.iter() { バランス= 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を無期限に拡張できるため、トラバーサル中にガスが不足する可能性があります。"引き出し"モードに変更し、ユーザーが報酬を積極的に引き出すようにするべきです:錆pub fn withdraw(&mut self) { let account_id = env::p redecessor_account_id(); let amount = self.accounts.get(&account_id).expect("報酬なし"); self.accounts.insert(&account_id, &0); ext_ft_token::ft_transfer( account_id、 量 &FTTOKENや 0, シングルコール用GAS );}## 2. クロスコントラクト状態の依存関係はブロッキングにつながります以下は"入札"スマートコントラクトです:錆#[near_bindgen]#[derive(BorshDeserialize、BorshSerialize)]pub struct コントラクト { パブ登録:Vec<accountid>、 pub bid_price: UnorderedMap<accountid, balance="">, 公開current_leader: AccountId, パブhighest_bid:U128、 パブの払い戻し:ブール}pub fn bid(&mut self, sender_id: AccountId, amount: u128) -> PromiseOrValue<u128> { アサート!(amount > self.highest_bid); if self.current_leader == 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.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::失敗 => { ext_ft_token::ft_transfer( sender_id.clone()、 量 &FTTOKENや 0, GAS_FOR_SINGLE_CALL*2、 ); ログ!("今すぐ戻る"); } };}前の入札者のアカウントが破棄された場合、新しい入札はブロックされます。外部呼び出しの失敗を考慮すると、返せないトークンはその後の引き出しのためにステージングできます。錆pub fn withdraw_lost_funds(&mut self) { let account_id = env::p redecessor_account_id(); let amount = self.lost_funds.get(&account_id).expect("失われた資金はありません"); self.lost_funds.remove(&account_id); ext_ft_token::ft_transfer( account_id、 量 &FTTOKENや 0, GAS_FOR_SINGLE_CALL );}! [](https://img-cdn.gateio.im/social/moments-b7bbfcf4423b1cf19db56a3af95a7486)## 3. オーナーのプライベートキーの喪失特定の重要な関数は、契約の所有者のみが呼び出すことができます。所有者が秘密鍵を失った場合、これらの関数は実行できなくなります。契約を管理するためにマルチシグネチャソリューションを採用し、シングルポイント障害を回避する必要があります。錆公開構造体MultiSigContract { 所有者:Vec<accountid>、 required_confirmations:U32、}pub fn submit_transaction(&mut self, transaction: Transaction) { assert!(self.owners.contains(&env::p redecessor_account_ id())); // 確認待ちリストに取引を追加する}pub fn confirm_transaction(&mut self, transaction_id: u64) { assert!(self.owners.contains(&env::p redecessor_account_ id())); // 確認数を増やす // 確認数が要求を満たす場合、取引を実行する}上記の方法により、スマートコントラクトにおけるDoS攻撃のリスクを効果的に防ぐことができます。! [](https://img-cdn.gateio.im/social/moments-7076cf1226a2276d1e4cd994d259841f)</accountid></u128></accountid,></accountid></accountid,></accountid>
Rustスマートコントラクト防御DoS攻撃実戦ガイド
Rustスマートコントラクト中的サービス拒否攻撃
サービス拒否(DoS)攻撃はスマートコントラクトを一定期間正常に使用できなくします。主に以下のような理由があります:
コントラクトのロジックに計算の複雑さに関する欠陥が存在し、Gasの消費が制限を超えています。
クロスコントラクト呼び出し時、コントラクトの実行は信頼できない外部コントラクトの状態に依存し、ブロックが発生します。
契約所有者が秘密鍵を紛失したため、鍵の特権機能を実行できなくなります。
以下の具体例を通じて、これらのサービス拒否攻撃の脆弱性を分析します。
1. 外部から変更可能な大規模データ構造を遍歴する
以下はシンプルな"分配"スマートコントラクトで、DoSリスクがあります:
錆 #[near_bindgen] #[derive(BorshDeserialize、BorshSerialize)] pub struct コントラクト { パブ登録:Vec、 パブアカウント: 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(), ディストリビューター, "ERR_NOT_ALLOWED");
}
ここでは、self.registeredを無期限に拡張できるため、トラバーサル中にガスが不足する可能性があります。
"引き出し"モードに変更し、ユーザーが報酬を積極的に引き出すようにするべきです:
錆 pub fn withdraw(&mut self) { let account_id = env::p redecessor_account_id(); let amount = self.accounts.get(&account_id).expect("報酬なし");
}
2. クロスコントラクト状態の依存関係はブロッキングにつながります
以下は"入札"スマートコントラクトです:
錆 #[near_bindgen] #[derive(BorshDeserialize、BorshSerialize)] pub struct コントラクト { パブ登録:Vec、 pub bid_price: UnorderedMap<accountid, balance="">, 公開current_leader: AccountId, パブhighest_bid:U128、 パブの払い戻し:ブール }
pub fn bid(&mut self, sender_id: AccountId, amount: u128) -> PromiseOrValue { アサート!(amount > self.highest_bid);
}
#[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_CALL2、 ); self.current_leader = sender_id; self.highest_bid = 金額; } PromiseResult::失敗 => { ext_ft_token::ft_transfer( sender_id.clone()、 量 &FTTOKENや 0, GAS_FOR_SINGLE_CALL2、 ); ログ!("今すぐ戻る"); } }; }
前の入札者のアカウントが破棄された場合、新しい入札はブロックされます。
外部呼び出しの失敗を考慮すると、返せないトークンはその後の引き出しのためにステージングできます。
錆 pub fn withdraw_lost_funds(&mut self) { let account_id = env::p redecessor_account_id(); let amount = self.lost_funds.get(&account_id).expect("失われた資金はありません");
}
!
3. オーナーのプライベートキーの喪失
特定の重要な関数は、契約の所有者のみが呼び出すことができます。所有者が秘密鍵を失った場合、これらの関数は実行できなくなります。
契約を管理するためにマルチシグネチャソリューションを採用し、シングルポイント障害を回避する必要があります。
錆 公開構造体MultiSigContract { 所有者:Vec、 required_confirmations:U32、 }
pub fn submit_transaction(&mut self, transaction: Transaction) { assert!(self.owners.contains(&env::p redecessor_account_ id())); // 確認待ちリストに取引を追加する }
pub fn confirm_transaction(&mut self, transaction_id: u64) { assert!(self.owners.contains(&env::p redecessor_account_ id())); // 確認数を増やす // 確認数が要求を満たす場合、取引を実行する }
上記の方法により、スマートコントラクトにおけるDoS攻撃のリスクを効果的に防ぐことができます。
! </accountid,></accountid,>