Hướng dẫn thực chiến phòng chống tấn công DoS trong hợp đồng thông minh Rust

Các cuộc tấn công từ chối dịch vụ trong hợp đồng thông minh Rust

Một cuộc tấn công từ chối (DoS) dịch vụ có thể khiến hợp đồng thông minh không thể sử dụng được trong một khoảng thời gian. Có một số lý do cho điều này:

  1. Có một khiếm khuyết trong logic hợp đồng là độ phức tạp tính toán quá cao, dẫn đến mức tiêu thụ gas vượt quá giới hạn.

  2. Khi gọi hợp đồng chéo, việc thực thi hợp đồng phụ thuộc vào trạng thái hợp đồng bên ngoài không đáng tin cậy, gây ra tình trạng tắc nghẽn.

  3. Chủ sở hữu hợp đồng mất khóa riêng tư, dẫn đến không thể thực hiện các chức năng đặc quyền chính.

Sau đây là phân tích các lỗ hổng DoS này với các ví dụ cụ thể.

1. Duyệt qua các cấu trúc dữ liệu lớn có thể thay đổi bên ngoài

Dưới đây là một hợp đồng "chia cổ tức" đơn giản, có rủi ro tấn công từ chối dịch vụ:

rỉ sét #[near_bindgen] #[derive(BorshDeserialize, BorshSerialize)] pub struct Hợp đồng { pub registered: Vec\u003caccountid\u003e, pub accounts: UnorderedMap<accountid, balance="">, }

pub fn register_account(&mut self) { nếu self.accounts.insert(&env::predecessor_account_id(), &0).is_some() { env::p anic("Tài khoản đã được đăng ký".to_string().as_ bytes()); } else { self.registered.push(env::p redecessor_account_id()); } log!("Tài khoản đã đăng ký {}", env::predecessor_account_id()); }

pub fn distribute_token(&mut self, amount: u128) { assert_eq!(env::p redecessor_account_id(), NHÀ PHÂN PHỐI, "ERR_NOT_ALLOWED");

cho cur_account trong 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!("Cố gắng phân phối đến tài khoản {}", &cur_account);
    
    ext_ft_token::ft_transfer(
        cur_account.clone(),
        số tiền,
        &FTTOKEN,
        0,
        GAS_FOR_SINGLE_CALL  
    );
}

}

Ở đây self.registered có thể được mở rộng vô hạn, dẫn đến việc duyệt khi thiếu Gas.

Nên chuyển sang chế độ "rút tiền", để người dùng chủ động rút thưởng:

rỉ sét pub fn withdraw(&mut self) { let account_id = env::predecessor_account_id(); let amount = self.accounts.get(&account_id).expect("Không có phần thưởng");

self.accounts.insert(&account_id, &0);

ext_ft_token::ft_transfer(
    account_id,
    lượng 
    &FTTOKEN,
    0,
    GAS_FOR_SINGLE_CALL
);

}

2. Phụ thuộc trạng thái hợp đồng chéo dẫn đến chặn

Đây là hợp đồng "Đấu giá":

rỉ sét #[near_bindgen] #[derive(BorshDeserialize, BorshSerialize)] pub struct Hợp đồng { quán rượu đã đăng ký: Vec, pub bid_price: UnorderedMap\u003caccountid, balance=""\u003e, pub current_leader: AccountId, pub highest_bid: u128, pub refund: bool }

pub fn bid(&mut self, sender_id: AccountId, amount: u128) -> PromiseOrValue { assert!(amount > self.highest_bid);

nếu 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::p rereturned_gas() - GAS_FOR_SINGLE_CALL * 4,
    ).then(ext_self::account_resolve(
        sender_id,
        lượng
        &env::current_account_id(),
        0,
        GAS_FOR_SINGLE_CALL * 3,
    ));
}

nhật ký!(
    "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) { match env::promise_result(0) { PromiseResult::NotReady => unreachable!(), 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(), số lượng, &FTTOKEN, 0, GAS_FOR_SINGLE_CALL * 2, ); log!("quay lại ngay bây giờ"); } }; }

Nếu tài khoản của người đặt giá trước đó bị xóa, giá thầu mới sẽ bị chặn.

Xem xét sự thất bại của các cuộc gọi bên ngoài, các token không thể trả lại có thể được dàn dựng để rút tiếp theo:

gỉ pub fn withdraw_lost_funds(&mut self) { let account_id = env::p redecessor_account_id(); let amount = self.lost_funds.get(&account_id).expect("Không có quỹ bị mất");

self.lost_funds.remove(&account_id);

ext_ft_token::ft_transfer(
    account_id,
    lượng
    &FTTOKEN,
    0,
    GAS_FOR_SINGLE_CALL
);

}

3. Mất khóa riêng của chủ sở hữu

Một số chức năng chính chỉ có thể được gọi bởi chủ sở hữu hợp đồng. Nếu chủ sở hữu mất khóa riêng tư, các chức năng này sẽ không được thực thi.

Nên áp dụng giải pháp ký nhiều để quản lý hợp đồng, tránh điểm lỗi đơn.

gỉ pub struct MultiSigContract { chủ sở hữu: Vec\u003caccountid\u003e, required_confirmations: u32, }

pub fn submit_transaction(&mut self, giao dịch: Transaction) { assert!(self.owners.contains(&env::p redecessor_account_ id())); Thêm giao dịch vào danh sách đang chờ xử lý }

pub fn xác nhận_giao_dịch(&mut self, transaction_id: u64) { assert!(self.owners.contains(&env::p redecessor_account_ id())); Tăng số lần xác nhận Nếu đạt đến số lượng xác nhận cần thiết, giao dịch sẽ được thực hiện }

Thông qua các phương pháp trên, nguy cơ tấn công DoS trong hợp đồng thông minh có thể được ngăn chặn một cách hiệu quả.

</accountid,></accountid,>

Xem bản gốc
Trang này có thể chứa nội dung của bên thứ ba, được cung cấp chỉ nhằm mục đích thông tin (không phải là tuyên bố/bảo đảm) và không được coi là sự chứng thực cho quan điểm của Gate hoặc là lời khuyên về tài chính hoặc chuyên môn. Xem Tuyên bố từ chối trách nhiệm để biết chi tiết.
  • Phần thưởng
  • 7
  • Chia sẻ
Bình luận
0/400
ConsensusDissentervip
· 07-19 04:59
hiểu biết có giá trị值得收藏学习
Xem bản gốcTrả lời0
MEVHunterZhangvip
· 07-18 23:52
Không hổ danh là lời khuyên kinh nghiệm
Xem bản gốcTrả lời0
PumpBeforeRugvip
· 07-18 15:28
Ai sẽ chi trả phí Gas? Hãy tìm hiểu.
Xem bản gốcTrả lời0
GmGnSleepervip
· 07-17 00:43
An toàn là trên hết, không có gì sai cả.
Xem bản gốcTrả lời0
ImpermanentPhilosophervip
· 07-17 00:41
Khởi động lại cưỡng bức là xong.
Xem bản gốcTrả lời0
GasFeePhobiavip
· 07-17 00:23
Phí Gas là một vấn đề lớn
Xem bản gốcTrả lời0
AllInAlicevip
· 07-17 00:21
Tối ưu hóa Gas rất quan trọng
Xem bản gốcTrả lời0
Giao dịch tiền điện tử mọi lúc mọi nơi
qrCode
Quét để tải xuống ứng dụng Gate
Cộng đồng
Tiếng Việt
  • 简体中文
  • English
  • Tiếng Việt
  • 繁體中文
  • Español
  • Русский
  • Français (Afrique)
  • Português (Portugal)
  • Bahasa Indonesia
  • 日本語
  • بالعربية
  • Українська
  • Português (Brasil)