Hướng dẫn thực chiến phòng ngừa tấn công DoS vào hợp đồng thông minh Rust

Nhật ký phát triển hợp đồng thông minh Rust: Phòng ngừa tấn công từ chối dịch vụ

tấn công từ chối dịch vụ(DoS) có thể dẫn đến hợp đồng thông minh không thể sử dụng bình thường trong một khoảng thời gian hoặc thậm chí vĩnh viễn. Nguyên nhân phổ biến bao gồm:

  1. Vấn đề độ phức tạp tính toán trong hợp đồng logic, dẫn đến việc tiêu thụ Gas vượt quá giới hạn.

  2. Khi gọi chéo hợp đồng, việc phụ thuộc không đúng vào trạng thái thực thi của hợp đồng bên ngoài sẽ gây ra việc hợp đồng này bị chặn.

  3. Mất khóa riêng của chủ hợp đồng, dẫn đến không thể gọi các hàm đặc quyền, trạng thái hệ thống quan trọng không thể cập nhật.

Dưới đây là một số ví dụ cụ thể để phân tích lỗ hổng tấn công từ chối dịch vụ (DoS) và các giải pháp của nó.

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

Dưới đây là một hợp đồng "chia sẻ lợi nhuận" đơn giản, có nguy cơ 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\u003caccountid, balance=""\u003e, }

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

pub fn distribute_token(&mut self, amount: u128) {
    assert_eq!(env::predecessor_account_id(), DISTRIBUTOR, "ERR_NOT_ALLOWED");
    
    cho cur_account trong self.registered.iter() {
        let balance = self.accounts.get(&cur_account).expect("ERR_GET");
        self.accounts.insert(\u0026cur_account, \u0026balance.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ố lượng,
            &FTTOKEN,
            0,
            GAS_FOR_SINGLE_CALL
        );
    }
}

}

Vấn đề là kích thước của mảng registered không có giới hạn, có thể bị người dùng ác ý thao túng trở nên quá lớn, dẫn đến việc hàm distribute_token thực thi tiêu tốn Gas vượt quá giới hạn.

Đề xuất giải pháp:

  1. Giới hạn kích thước mảng registered.

  2. Áp dụng chế độ "rút tiền", cho phép người dùng tự rút phần thưởng, thay vì hợp đồng chủ động phân phối.

2. Sự phụ thuộc trạng thái giữa các hợp đồng dẫn đến việc hợp đồng bị chặn

Dưới đây là một ví dụ về hợp đồng "đấu giá":

gỉ #[near_bindgen] #[derive(BorshDeserialize, BorshSerialize)] pub struct Hợp đồng { pub registered: Vec\u003caccountid\u003e, pub bid_price: UnorderedMap\u003caccountid,balance\u003e, pub current_leader: AccountId, pub highest_bid: u128, pub hoàn tiền: bool }

impl Hợp đồng { 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::prepaid_gas() - GAS_FOR_SINGLE_CALL * 4,
        (.then)ext_self::account_resolve)
            sender_id,
            số lượng,
            &env::current_account_id((,
            0,
            GAS_FOR_SINGLE_CALL * 3,
        ();
    }

    log!)
        "current_leader: {} highest_bid: {}", 
        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 => 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!)"Trở lại ngay bây giờ");
        }
    };
}

}

Vấn đề là trạng thái hợp đồng cập nhật phụ thuộc vào việc gọi hợp đồng bên ngoài. Nếu tài khoản của người đặt giá cao nhất trước đó đã bị hủy, người đặt giá tiếp theo sẽ không thể cập nhật trạng thái.

Đề xuất giải pháp:

Cân nhắc tình huống gọi ngoài có thể thất bại, thực hiện cơ chế xử lý lỗi hợp lý. Ví dụ, tạm giữ các token không thể hoàn lại trong hợp đồng, sau đó cho phép người dùng chủ động rút.

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

Nhiều hợp đồng tồn tại các chức năng đặc quyền chỉ có thể được thực hiện bởi chủ sở hữu. Nếu khóa riêng của chủ sở hữu bị mất, các chức năng này sẽ không thể được gọi, có thể dẫn đến hợp đồng không hoạt động bình thường.

Đề xuất giải pháp:

  1. Thiết lập nhiều chủ sở hữu hợp đồng để quản lý chung.

  2. Sử dụng cơ chế ký đa chữ ký để thay thế cho việc kiểm soát của một chủ sở hữu duy nhất.

  3. Thực hiện cơ chế quản trị hợp đồng phi tập trung.

Thông qua các biện pháp trên, có thể giảm hiệu quả rủi ro tấn công từ chối dịch vụ trong hợp đồng thông minh, nâng cao tính an toàn và độ tin cậy của hợp đồng.

</accountid,balance></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
  • 8
  • Chia sẻ
Bình luận
0/400
MEVHunterWangvip
· 7giờ trước
Chơi hỏng một hợp đồng chẳng phải là tay cầm nắm chặt.
Xem bản gốcTrả lời0
ProofOfNothingvip
· 10giờ trước
Lại là chủ nghĩa hình thức nói suông trên giấy.
Xem bản gốcTrả lời0
LuckyHashValuevip
· 14giờ trước
Tấn công không phòng ngừa được, lại sắp giảm về 0 rồi.
Xem bản gốcTrả lời0
ColdWalletGuardianvip
· 14giờ trước
Kiến thức cơ bản về Blockchain
Xem bản gốcTrả lời0
SelfSovereignStevevip
· 14giờ trước
Khóa riêng bị mất thì thảm rồi
Xem bản gốcTrả lời0
StableBoivip
· 14giờ trước
Hợp đồng này thật sự có nhiều rủi ro, tính ổn định không được tốt lắm.
Xem bản gốcTrả lời0
Ser_This_Is_A_Casinovip
· 14giờ trước
Ôi, Rust thật khó chịu, không bằng xem xét Solidity.
Xem bản gốcTrả lời0
GasFeeThundervip
· 14giờ trước
gas ăn quá nhiều lại gây rắc rối? Chẳng mấy chốc hợp đồng sẽ bị khai thác sạch sẽ.
Xem bản gốcTrả lời0
  • Ghim
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)