Пока я обучаюсь линейной алгебре и работаю над своим ассистентом для аудита, подумал, что будет здорово разобрать несколько популярных атак в блокчейне: и для начинающих аудиторов это будет полезно и интересно, и я сам, возможно, найду новые нюансы, на которые стоит обращать внимание.
В блоге Cyfrin мне попался прекрасный цикл статей от крутого аудитора и судьи Hans, который разбирает уязвимости из "Solodit Checklist". Давайте вместе изучим их.
Итак, первая уязвимость, которую мы рассмотрим это "DoS".
Почему нам стоит беспокоиться о DoS-атаках?
Разве DoS-атаки — это проблема только для традиционных централизованных серверов? Что-то, о чем должны переживать только крупные корпорации, верно? Нет!
На самом деле, в децентрализованных финансах (DeFi) DoS-атаки могут быть разрушительными. Представьте себе этот кошмарный сценарий: ваш тщательно разработанный стейкинг-контракт, созданный для щедрого вознаграждения пользователей, внезапно… перестает работать.
Он встает колом, потому что какой-то злоумышленник забрасывает его транзакциями. Пользователи не могут вывести свои средства, и вся система становится безнадежно неработоспособной. А что насчет вашей репутации? Она падает быстрее, чем цена мемкоина после rug pull'а (а мы все знаем, каково это).
DoS-атаки используют уязвимости в вашем коде, делая смарт-контракт бесполезным — либо для конкретных пользователей, либо для всех. Они как цифровые баррикады, мешающие честным людям получить доступ к услугам вашего протокола! В сфере, где доверие решает все, успешная DoS-атака может стать полной катастрофой.
Для наглядности представьте: вы вложили душу в создание прекрасной кофейни. Это лучшая кофейня в мире. Но тут кто-то приходит и начинает заказывать тысячи пустых чашек кофе, забивая всю систему и не давая реальным клиентам получить свой кофеин. Бесит, правда?
Denial-of-Service (DoS) атака: общий обзор
DoS-атаки обычно используют недостатки в логике вашего смарт-контракта, а не грубую силу. Это тонкая манипуляция, которая вас побеждает.
Вот как это работает:
1. Эксплуатация логики — злоумышленники находят хитрые (или, точнее, вредоносные) способы вызвать изменения состояния, которые приводят к откату транзакций или бесконечным циклам, фактически замораживая контракт. Это происходит чаще, чем кажется.
2. Исчерпание ресурсов — представьте себе это как трагедию общего достояния, но с комиссиями за газ. Атакующий заваливает контракт запросами, сжигая огромное количество газа и делая его использование невыгодным для обычных пользователей. Помните: каждое действие в блокчейне требует газа, а лавина транзакций может взвинтить эти расходы.
Теперь, когда мы кратко разобрали основы (и, надеюсь, убедили вас, что DoS-атаки — реальная угроза), давайте углубимся в конкретные способы защиты.
SOL-AM-DOSA-1: Используется ли паттерн вывода средств для защиты от DoS?
Иными словами: Вы применяете "pull" вместо "push" подход для вывода средств?
Классическая ошибка (которую я видел слишком много раз в конкурсах по аудиту) — это передача ETH пользователям в функции вывода средств. Кажется, все просто, правда? Совершенно не так! Давайте посмотрим на код:
// Anti-pattern: Pushing ETH
function batchWithdraw() public {
address[] memory users = getUsers(); // imaginary function to get users
for (uint i = 0; i < users.length; i++) {
uint amount = balances[users[i]];
if (amount > 0) {
balances[users[i]] = 0;
(bool success, ) = users[i].call{value: amount}(""); // Potential DoS!
require(success, "Transfer failed"); // If any transfer fails, the entire batch reverts
}
}
}
Почему это плохо?
Если msg.sender — это контракт, который ревертится при получении ETH (по любой причине — возможно, из-за злонамеренных действий), то вся функция вывода средств будет ревертиться также для всех! Это создает реальную ситуацию DoS, поскольку легитимные пользователи не могут вывести средства из-за одного неработающего адреса. Представьте себе хаос!
Решение: модель pull