Аналіз уразливостей DoS-атак на смартконтракти на Rust та рішення

Атака на відмову в обслуговуванні в смартконтрактах на Rust

атака на відмову в обслуговуванні(DoS) може призвести до того, що смартконтракти протягом певного часу, а іноді і назавжди, не зможуть працювати належним чином. Основні причини включають:

  1. Логіка контракту має дефекти, такі як надмірна складність обчислень деяких функцій, що призводить до перевищення ліміту споживання Gas.

  2. Під час виклику між контрактами виконання контракту залежить від стану зовнішнього контракту, що може бути заблокованим зовнішнім контрактом.

  3. Людські фактори, такі як втрата приватного ключа власником контракту, що призводить до неможливості виклику функцій привілеїв.

Нижче через конкретні приклади аналізуються вразливості атаки на відмову в обслуговуванні в смартконтрактах.

1. Циклічний перебір великих структур даних, що можуть бути змінені ззовні

Ось простий смартконтракт для розподілу дивідендів серед зареєстрованих користувачів:

іржа #[near_bindgen] #[derive(BorshDeserialize, BorshSerialize)] pub struct Contract { pub зареєстровано: Vec\u003caccountid\u003e, облікові записи pub: UnorderedMap<accountid, balance="">, }

impl Контракт { 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::predecessor_account_id()); }

pub fn distribute_token(&mut self, кількість: u128) {
    assert_eq!(env::p redecessor_account_id(), ДИСТРИБ'ЮТОР, "не має права працювати" );
    для облікового запису в self.registered.iter() {
        let balance = self.accounts.get019283746574839201&account(.expect)"Failed"(;
        self.accounts.insert)&account, &balance.checked_add(amount(.expect) "Переповнення додавання" (); 
        log!)"Спроба розподілу на рахунок {}", &account(;
        ext_ft_token::ft_transfer)
            account.clone((,
            сума,
            &FTTOKEN,
            0,
            GAS_FOR_SINGLE_CALL
        );
    }
}

}

Проблема з цим смартконтрактом полягає в тому, що розмір масиву registered не обмежений, що дозволяє зловмисним користувачам маніпулювати ним і робити його занадто великим, що призводить до надмірних витрат Gas у функції distribute_token.

Рекомендоване рішення:

Переконструюйте контракт, використовуючи режим виведення. Нехай користувачі активно викликають функцію виведення, щоб отримати винагороду, контракту потрібно лише зафіксувати суму винагороди, яку може вивести користувач.

! [])https://img-cdn.gateio.im/webp-social/moments-b7bbfcf4423b1cf19db56a3af95a7486.webp(

2. Залежність стану між контрактами призводить до блокування

Розглянемо контракт на торги:

іржа #[near_bindgen] #[derive)BorshDeserialize, BorshSerialize(] pub struct Контракт { pub зареєстровані: Vec, pub bid_price: UnorderedMap<accountid,balance>, pub current_leader: AccountId, highest_bid пабу: U128, Повернення коштів у пабі: bool }

impl Контракт { 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, )); } журналу!) "Поточний найвищий учасник торгів: {} Найвищий ставлення: {}" self.current_leader, self.highest_bid (; PromiseOrValue::Value)0( }

#)
pub fn account_resolve[private]&mut self, sender_id: AccountId, amount: u128( {
    match env::p romise_result)0( {
        PromiseResult::NotReady => недосяжний!)(,
        PromiseResult::Успішний)_( => {
            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::Failed => {
            ext_ft_token::ft_transfer)
                sender_id.clone((,
                сума,
                &FTTOKEN,
                0,
                GAS_FOR_SINGLE_CALL * 2,
            );
            log!)"Повернути поточну ставку"(;
        }
    };
}

}

Проблема цього смартконтракту полягає в тому, що для оновлення найвищої ставки необхідно успішно повернути токени попереднього учасника аукціону. Якщо попередній учасник скасує свій обліковий запис, смартконтракт не зможе виконати повернення і буде заблоковано.

Рішення:

Розгляньте ситуації, коли виклики зовнішніх смартконтрактів можуть завершитися невдачею, реалізуйте розумну обробку помилок. Можна тимчасово зберігати незворотні токени в контракті, пізніше дозволяючи користувачам ініціювати їх вилучення.

3. Втрата приватного ключа власника смартконтракту

Деякі функції смартконтракту налаштовані так, що їх можуть виконувати лише власники, для зміни ключових системних змінних. Якщо приватний ключ власника буде втрачено, ці функції не зможуть бути викликані, що може призвести до того, що контракт не зможе працювати належним чином.

Рішення:

Налаштування спільного управління кількома власниками контрактів або використання механізму мультипідпису замість контролю прав одного власника для досягнення децентралізованого управління.

! [])https://img-cdn.gateio.im/webp-social/moments-7076cf1226a2276d1e4cd994d259841f.webp(</accountid,balance></accountid,>

Переглянути оригінал
Ця сторінка може містити контент третіх осіб, який надається виключно в інформаційних цілях (не в якості запевнень/гарантій) і не повинен розглядатися як схвалення його поглядів компанією Gate, а також як фінансова або професійна консультація. Див. Застереження для отримання детальної інформації.
  • Нагородити
  • 8
  • Поділіться
Прокоментувати
0/400
WhaleWatchervip
· 9год тому
Контракт буде атакований лише якщо це решето.
Переглянути оригіналвідповісти на0
CryptoSourGrapevip
· 10год тому
Якби я раніше дізнався про цей недолік, навіщо було опускатися до того, щоб щодня жалітися.
Переглянути оригіналвідповісти на0
PancakeFlippavip
· 07-18 18:19
Контракт також має поріг, хто ж винен, що у тебе погані навички.
Переглянути оригіналвідповісти на0
LazyDevMinervip
· 07-17 19:29
Про програмування поговоримо в наступному житті 8
Переглянути оригіналвідповісти на0
NftPhilanthropistvip
· 07-17 19:28
насправді... *п'є чай* ще один газ-неефективний контракт, який можна оптимізувати для соціального впливу. коли ж розробники навчаться усвідомленим практикам кодування, смх
Переглянути оригіналвідповісти на0
just_another_walletvip
· 07-17 19:20
Проблеми безпеки, хлопці, потрібно серйозно сприймати!
Переглянути оригіналвідповісти на0
NFTragedyvip
· 07-17 19:16
Це питання, код навіть не закінчено...
Переглянути оригіналвідповісти на0
HalfBuddhaMoneyvip
· 07-17 19:01
Яка жахливість, знову потрібно заповнювати ями, сміттєвий контракт.
Переглянути оригіналвідповісти на0
  • Закріпити