Глубина анализа уязвимостей DoS-атак в смарт-контрактах и стратегии их предотвращения

Анализ атаки типа «отказ в обслуживании» в смарт-контрактах

атака типа «отказ в обслуживании»(DoS)может привести к тому, что смарт-контракты в течение некоторого времени или даже навсегда не смогут нормально функционировать. Основные причины включают:

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

  2. Зависимость от состояния выполнения внешнего контракта при межконтрактных вызовах, ненадежное выполнение внешнего контракта может блокировать нормальную работу данного контракта.

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

Ниже через конкретные примеры анализируются уязвимости атак типа «отказ в обслуживании» в смарт-контрактах.

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

Вот простой контракт для "распределения дивидендов" зарегистрированным пользователям:

ржавчина #[near_bindgen] #[derive(BorshDeserialize, BorshSerialize)] pub struct Контракт { pub зарегистрированные: Vec\u003caccountid\u003e, аккаунты пабов: 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::предшествующий_id_аккаунта()); }

pub fn distribute_token(&mut self, сумма: u128) { assert_eq!(env::p redecessor_account_id(),ДИСТРИБЬЮТОР,'ERR_NOT_ALLOWED'); для cur_account в 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.клон(), сумма, &FTTOKEN, 0, GAS_FOR_SINGLE_CALL ); } }

Проблема этого контракта заключается в том, что размер массива self.registered не ограничен, что может быть использовано злонамеренными пользователями для его чрезмерного увеличения, что приводит к превышению лимита потребления газа при выполнении функции distribute_token.

Рекомендуемое решение:

  1. Ограничить максимальную длину массива self.registered
  2. Использовать режим вывода, не активно распределяя награды, а позволяя пользователям самостоятельно вызывать функцию вывода.

!

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

Рассмотрим контракт на "торги":

ржавчина #[near_bindgen] #[derive(BorshDeserialize, BorshSerialize)] pub struct Contract { pub зарегистрированные: Vec\u003caccountid\u003e, паб bid_price: UnorderedMap<accountid,balance>, pub current_leader: AccountId, highest_bid паб: U128, Возврат средств в пабе: Bool }

pub fn bid(&mut self, sender_id: AccountId, amount: u128) -> PromiseOrValue { assert!(amount > self.highest_bid); если self.current_leader == DEFAULT_ACCOUNT { self.current_leader = sender_id; self.highest_bid = сумма; } else { ext_ft_token::account_exist( self.current_leader.клон(), &FTTOKEN, 0, env::предоплаченный_газ() - ГАЗ_ДЛЯ_ОДИНОЧНОГО_ЗОВА * 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) }

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

Проблема с этим смарт-контрактом заключается в том, что если учетная запись пользователя с текущей самой высокой ставкой аннулируется в внешнем токен-контракте, новая более высокая ставка не сможет вернуть токены предыдущему пользователю, что приведет к блокировке процесса аукциона.

Решение:

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

3. Потеря приватного ключа владельца смарт-контракта

В смарт-контрактах часто существуют привилегированные функции, которые могут выполняться только владельцем. Если приватный ключ владельца будет утерян, эти функции не смогут быть вызваны, что может привести к неправильной работе контракта.

Способ решения:

  1. Установить совместное управление несколькими владельцами смарт-контрактов
  2. Использование механизма мультиподписей вместо контроля прав единственного владельца
  3. Реализация децентрализованной схемы управления контрактами

! </accountid,balance></accountid,>

Посмотреть Оригинал
На этой странице может содержаться сторонний контент, который предоставляется исключительно в информационных целях (не в качестве заявлений/гарантий) и не должен рассматриваться как поддержка взглядов компании Gate или как финансовый или профессиональный совет. Подробности смотрите в разделе «Отказ от ответственности» .
  • Награда
  • 7
  • Поделиться
комментарий
0/400
consensus_whisperervip
· 07-31 14:18
Кого ты имеешь в виду, говоря о контракте, который одновременно и неумелый, и увлекательный?
Посмотреть ОригиналОтветить0
RumbleValidatorvip
· 07-30 19:13
Снова простая уязвимость бесконечного цикла, перед дампом контракта необходимо провести нагрузочное тестирование узла до предела.
Посмотреть ОригиналОтветить0
GasGuzzlervip
· 07-30 19:12
Мастер по отговорке от GAS-расходов! Прямо взрывается
Посмотреть ОригиналОтветить0
BtcDailyResearchervip
· 07-30 19:10
Снова кто-то попался на DoS, умираю со смеху
Посмотреть ОригиналОтветить0
SignatureDeniedvip
· 07-30 19:05
Снова атаковали? Кто еще осмелится хранить Закрытый ключ наугад?
Посмотреть ОригиналОтветить0
DefiOldTrickstervip
· 07-30 19:02
Старый белый медведь, играя на медвежьем рынке, стал хозяином, но его контракт был заблокирован из-за потерянного закрытого ключа, хрустящий.
Посмотреть ОригиналОтветить0
RuntimeErrorvip
· 07-30 18:53
Эм? Контракт может быть уничтожен из-за потери Закрытого ключа? Это действительно срочно.
Посмотреть ОригиналОтветить0
  • Закрепить