# スマートコントラクト中的サービス拒否攻撃分析サービス拒否攻撃(DoS)は、スマートコントラクトが一定期間、場合によっては永続的に正常に使用できなくなる可能性があります。主な原因は次の通りです:1. コントラクトのロジックにおける欠陥、例えば特定の公開関数の計算の複雑さが高すぎるため、Gas消費が制限を超えること。2. 外部コントラクトの実行状態への依存は、コントラクト間の呼び出し時において、外部コントラクトの実行が信頼できない場合、本コントラクトの正常な運用を阻害する可能性があります。3. 人為的要因、例えば契約所有者が秘密鍵を紛失したために特権関数が呼び出せない。以下に具体例を通じてスマートコントラクトにおけるDoS攻撃の脆弱性を分析します。## 1. 外部から変更可能な大規模データ構造をループで遍歴する以下は、登録ユーザーに「分配利益」を与えるためのシンプルなスマートコントラクトです。さび#[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()); }エルス{ 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(){ let balance = self.accounts.get(&cur_account).expect('ERR_GET'); self.accounts.insert(&cur_account,&balance.checked_add(amount).expect('ERR_ 追加')); log!('アカウント{}に配布を試みる',&cur_account); ext_ft_token::ft_transfer( cur_account.clone()、 量 &FTTOKENや 0, GAS_FOR_SINGLE_CALL ); }}この契約の問題は、self.registered配列のサイズに制限がなく、悪意のあるユーザーによって操作されて過大になる可能性があり、その結果、distribute_token関数の実行時にGas消費が制限を超えることです。推奨ソリューション:1. self.registered 配列の最大長を制限する2. 出金モードを採用し、報酬を自発的に配布するのではなく、ユーザーが自ら出金関数を呼び出すようにします。! [](https://img-cdn.gateio.im/social/moments-b7bbfcf4423b1cf19db56a3af95a7486)## 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、 ); log!('今すぐ戻る'); } };}この契約の問題は、現在の最高入札者のアカウントが外部トークン契約で無効化された場合、新しいより高い入札が前者のトークンを返却できず、オークションプロセスがブロックされることです。ソリューション:外部コントラクト呼び出しが失敗する可能性を考慮し、合理的なエラーハンドリングを実装します。例えば、返却できないトークンをコントラクトに一時保管し、後でユーザーが自分で引き出すことを許可します。## 3. コントラクト所有者の秘密鍵の喪失スマートコントラクト中往往存在只有所有者可执行の特権関数。もし所有者の秘密鍵が失われた場合、これらの関数は呼び出せなくなり、契約が正常に機能しなくなる可能性があります。ソリューション:1. 複数の契約所有者による共同ガバナンスを設定する2. 単一の所有者の権限管理の代わりにマルチシグネチャメカニズムを採用する3. 分散型の契約ガバナンスソリューションの実現! [](https://img-cdn.gateio.im/social/moments-7076cf1226a2276d1e4cd994d259841f)</u128></accountid,balance></accountid></accountid,></accountid>
デプス剖析スマートコントラクト中的DoS攻击漏洞及防范策略
スマートコントラクト中的サービス拒否攻撃分析
サービス拒否攻撃(DoS)は、スマートコントラクトが一定期間、場合によっては永続的に正常に使用できなくなる可能性があります。主な原因は次の通りです:
コントラクトのロジックにおける欠陥、例えば特定の公開関数の計算の複雑さが高すぎるため、Gas消費が制限を超えること。
外部コントラクトの実行状態への依存は、コントラクト間の呼び出し時において、外部コントラクトの実行が信頼できない場合、本コントラクトの正常な運用を阻害する可能性があります。
人為的要因、例えば契約所有者が秘密鍵を紛失したために特権関数が呼び出せない。
以下に具体例を通じてスマートコントラクトにおけるDoS攻撃の脆弱性を分析します。
1. 外部から変更可能な大規模データ構造をループで遍歴する
以下は、登録ユーザーに「分配利益」を与えるためのシンプルなスマートコントラクトです。
さび #[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()); }エルス{ 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(){ let balance = self.accounts.get(&cur_account).expect('ERR_GET'); self.accounts.insert(&cur_account,&balance.checked_add(amount).expect('ERR_ 追加')); log!('アカウント{}に配布を試みる',&cur_account); ext_ft_token::ft_transfer( cur_account.clone()、 量 &FTTOKENや 0, GAS_FOR_SINGLE_CALL ); } }
この契約の問題は、self.registered配列のサイズに制限がなく、悪意のあるユーザーによって操作されて過大になる可能性があり、その結果、distribute_token関数の実行時にGas消費が制限を超えることです。
推奨ソリューション:
!
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); 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_CALL2、 ); self.current_leader = sender_id; self.highest_bid = 金額; } PromiseResult::失敗 => { ext_ft_token::ft_transfer( sender_id.clone()、 量 &FTTOKENや 0, GAS_FOR_SINGLE_CALL2、 ); log!('今すぐ戻る'); } }; }
この契約の問題は、現在の最高入札者のアカウントが外部トークン契約で無効化された場合、新しいより高い入札が前者のトークンを返却できず、オークションプロセスがブロックされることです。
ソリューション:
外部コントラクト呼び出しが失敗する可能性を考慮し、合理的なエラーハンドリングを実装します。例えば、返却できないトークンをコントラクトに一時保管し、後でユーザーが自分で引き出すことを許可します。
3. コントラクト所有者の秘密鍵の喪失
スマートコントラクト中往往存在只有所有者可执行の特権関数。もし所有者の秘密鍵が失われた場合、これらの関数は呼び出せなくなり、契約が正常に機能しなくなる可能性があります。
ソリューション:
! </accountid,balance></accountid,>