Давайте разбираться с очередным видом атак.
При грифинг атаке злоумышленник намерен нарушить работу или помешать законным пользователям выполнять желаемые действия в контракте. Злоумышленник часто несет расходы (например, комиссию за газ), не получая прямой финансовой выгоды от своих действий.
Термин «грифинг» (griefing), вероятно, происходит из сообществ онлайн-игр, где он описывает игроков, которые намеренно раздражают и донимают других, часто нарушая предполагаемый ход игры ради собственного развлечения, а не стратегического преимущества. Точно так же в контексте смарт контрактов грифинг атаки ставят в основу создание неудобств, а не извлечение прибыли.
Стоит отметить, что в сфере безопасности web3 термины «грифинг» и «отказ в обслуживании (DoS)» иногда используются как взаимозаменяемые, что может вызывать путаницу. Однако понимание их различий может прояснить цель каждой из атак.
Атака типа «отказ в обслуживании» (DoS) — это термин, укоренившийся в общей безопасности сетей и компьютеров. Ее цель — сделать сервис или сеть недоступными для всех пользователей на время или на неопределенный срок. Это может включать в себя перегрузку системы трафиком или эксплуатацию уязвимостей, которые предотвращают законный доступ для всех. Целью, как правило, является широкомасштабный срыв работы всего сервиса.
Масштаб и намерение являются основными различиями между этими двумя типами атак. Однако грань иногда может быть размытой, а это означает, что некоторые уязвимости могут относиться к любой из категорий. Крупная грифинг атака потенциально может привести к сценарию DoS для части пользователей или функций.
В конечном счете, точная категоризация менее важна, чем выявление уязвимости, понимание ее воздействия и внедрение эффективных мер по ее устранению.
Существует ли внешняя функция, которая зависит от состояний, которые могут быть изменены другими?
Тут злоумышленники могут предотвратить выполнение транзакций обычными пользователями, внося незначительные изменения в состояния в блокчейне.
Меры по устранению: Убедитесь, что обычные действия пользователей, особенно важные, такие как withdrawal (вывод средств) и repayment (погашение), не могут быть нарушены другими участниками.
Эта проверка направлена на предотвращение ситуаций, в которых злоумышленник может заблокировать важные действия жертвы, изменив общие переменные состояния, которые использует функция жертвы.
Если контракт позволяет любому изменять переменную состояния, от которой зависит выполнение критической операции другого пользователя (например, условие вывода, флаг или временная метка), злоумышленник может злонамеренно изменить это состояние, чтобы заблокировать жертву. Злоумышленник специально нацеливается на способность жертвы исполнять последующие транзакции, часто тратя на это собственный газ. то особенно практично в блокчейнах с низкой комиссией за транзакции.
Рассмотрим контракт VulnerableVault с отсроченным выводом.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract VulnerableVault {
uint256 public delay = 60 minutes;
mapping(address => uint256) public lastDeposit;
mapping(address => uint256) public balances;
function deposit(address _for) public payable {
lastDeposit[_for] = block.timestamp;
balances[_for] += msg.value;
}
function withdraw(uint256 _amount) public {
require(block.timestamp >= lastDeposit[msg.sender] + delay,
"Wait period not over");
require(balances[msg.sender] >= _amount, "Insufficient funds");
balances[msg.sender] -= _amount;
(bool success,) = payable(msg.sender).call{value: _amount}("");
require(success, "Transfer failed");
}
}
Функция deposit(address _for) является слабым местом. Она позволяет вызывающему (msg.sender) указать любой адрес _for. При вызове этой функции обновляется lastDeposit[_for]. Злоумышленник может вызвать эту функцию, указав адрес своей жертвы в качестве _for, и отправить минимальную сумму (например, 1 вей). Это действие сбрасывает временную метку lastDeposit жертвы.