Атаки повторного входа представляют собой одну из самых значительных угроз безопасности в разработке смарт-контрактов. Этот технический анализ объясняет механизмы, стоящие за уязвимостями повторного входа, и предоставляет всесторонние стратегии защиты для защиты ваших контрактов.
Что такое атака повторного входа?
Рекурсия происходит, когда функция в смарт-контракте может быть прервана во время своего выполнения и вызвана снова до завершения первого вызова. В техническом смысле, рекурсия использует контекст выполнения смарт-контракта, манипулируя потоком управления через внешние вызовы.
Когда Контракт A взаимодействует с Контрактом B, уязвимость возникает потому, что Контракт B может вызвать обратный вызов к Контракту A, пока выполнение Контракта A все еще продолжается. Этот рекурсивный шаблон вызовов может быть использован для манипуляции состоянием контракта и извлечения средств.
Механика атак: Как работает повторный вход
Рассмотрим сценарий с двумя контрактами:
Контракт A: Уязвимый контракт, хранящий 10 ETH
Контракт B: Зловредный контракт с 1 ETH, внесенным в Контракт A
Поток атаки следует этой схеме:
Контракт B вызывает функцию withdraw() в Контракте A
Контракт A проверяет, что баланс Контракта B больше 0 (прошел проверку)
Контракт A отправляет 1 ETH на контракт B перед обновлением своей записи баланса
Перевод ETH вызывает функцию обратного вызова Контракта B
Внутри функции резервирования Контракт B снова вызывает функцию вывода Контракта A ()
Поскольку Контракт A еще не обновил баланс Контракта B, проверка проходит снова
Контракт A отправляет еще один ETH в Контракт B
Этот цикл повторяется, пока Контракт A не будет исчерпан средств.
Критическая уязвимость заключается в порядке выполнения Контракта A: он выполняет внешний вызов (, отправляя ETH) до обновления своего внутреннего состояния (, устанавливая баланс равным нулю ).
Три техники защиты от повторного входа
1. Защита на уровне функции с модификатором noReentrant
Модификатор noReentrant реализует механизм блокировки, который предотвращает рекурсивный вызов функции:
солидность
// Переменная состояния для отслеживания повторного входа
bool private locked = false;
// Защищенная функция
функция withdraw() публичная noReentrant {
// Логика функции здесь
}
Этот подход блокирует попытки повторного входа, поддерживая переменную состояния на уровне контракта, которая предотвращает одновременное выполнение защищенных функций.
2. Паттерн проверки-эффекта-взаимодействия
Эта структура перерабатывает код, чтобы следовать определенной последовательности операций:
Проверьте: Проверьте условия (, например, баланс > 0)
Эффект: Обновить переменные состояния (, например, установить баланс = 0)
Взаимодействие: Выполняйте внешние вызовы (, например, переводите ETH )
Сравнение уязвимого и защищенного кода:
Уязвимый:
солидность
функция withdraw() внешний {
uint bal = balances[msg.sender];
require(bal > 0);
// Взаимодействие перед Эффектом (уязвимый)
(bool отправлено, ) = msg.sender.call{value: bal}("");
require(sent, "Не удалось отправить Эфир");
balances[msg.sender] = 0; // Может никогда не быть достигнуто, если произойдет повторный вход
}
Защищено:
солидность
функция withdraw() внешний {
uint bal = balances[msg.sender];
require(bal > 0);
// Эффект перед взаимодействием (secure)
balances[msg.sender] = 0;
(bool отправлено, ) = msg.sender.call{value: bal}("");
require(отправлено, "Не удалось отправить Эфир");
}
Обновляя состояние перед внешними взаимодействиями, контракт остается безопасным, даже если внешний вызов инициирует повторный вызов функции.
3. Защита между контрактами с GlobalReentrancyGuard
Для проектов с несколькими взаимодействующими контрактами общий защитник от повторного входа обеспечивает всестороннюю защиту:
солидность
// Центральный контракт для защиты от повторных вызовов
контракт GlobalReentrancyGuard {
mapping(address => bool) частный _status;
// Использование охранника в контракте
контракт ProtectedContract is GlobalReentrancyGuard {
функция protectedFunction() внешняя {
_beforeNonReentrant();
// Защищенная логика функции здесь
_afterNonReentrant();
}
}
Эта техника предотвращает повторный вход через контракты, поддерживая глобальный реестр состояния, который отслеживает статус выполнения по нескольким контрактам в вашей экосистеме.
Лучшие практики безопасности
Чтобы обеспечить комплексную защиту от атак повторного входа:
Примените несколько слоев защиты: Сочетайте шаблон проверки-эффекта-взаимодействия с защитой от повторного входа для максимальной безопасности
Проведите тщательное тестирование: Используйте специализированные инструменты, такие как Mythril, для обнаружения потенциальных уязвимостей повторного входа.
Следуйте установленным шаблонам: Последовательно внедряйте меры безопасности во всех контрактах вашего проекта
На этой странице может содержаться сторонний контент, который предоставляется исключительно в информационных целях (не в качестве заявлений/гарантий) и не должен рассматриваться как поддержка взглядов компании Gate или как финансовый или профессиональный совет. Подробности смотрите в разделе «Отказ от ответственности» .
Смарт-контракт Безопасность: Понимание и предотвращение уязвимостей повторного входа
Атаки повторного входа представляют собой одну из самых значительных угроз безопасности в разработке смарт-контрактов. Этот технический анализ объясняет механизмы, стоящие за уязвимостями повторного входа, и предоставляет всесторонние стратегии защиты для защиты ваших контрактов.
Что такое атака повторного входа?
Рекурсия происходит, когда функция в смарт-контракте может быть прервана во время своего выполнения и вызвана снова до завершения первого вызова. В техническом смысле, рекурсия использует контекст выполнения смарт-контракта, манипулируя потоком управления через внешние вызовы.
Когда Контракт A взаимодействует с Контрактом B, уязвимость возникает потому, что Контракт B может вызвать обратный вызов к Контракту A, пока выполнение Контракта A все еще продолжается. Этот рекурсивный шаблон вызовов может быть использован для манипуляции состоянием контракта и извлечения средств.
Механика атак: Как работает повторный вход
Рассмотрим сценарий с двумя контрактами:
Поток атаки следует этой схеме:
Критическая уязвимость заключается в порядке выполнения Контракта A: он выполняет внешний вызов (, отправляя ETH) до обновления своего внутреннего состояния (, устанавливая баланс равным нулю ).
Три техники защиты от повторного входа
1. Защита на уровне функции с модификатором noReentrant
Модификатор noReentrant реализует механизм блокировки, который предотвращает рекурсивный вызов функции:
солидность // Переменная состояния для отслеживания повторного входа bool private locked = false;
// Модификатор для предотвращения повторного входа модификатор noReentrant() { require(!locked, "Повторный звонок"); заблокирован = true; _; заблокировано = ложь; }
// Защищенная функция функция withdraw() публичная noReentrant { // Логика функции здесь }
Этот подход блокирует попытки повторного входа, поддерживая переменную состояния на уровне контракта, которая предотвращает одновременное выполнение защищенных функций.
2. Паттерн проверки-эффекта-взаимодействия
Эта структура перерабатывает код, чтобы следовать определенной последовательности операций:
Сравнение уязвимого и защищенного кода:
Уязвимый: солидность функция withdraw() внешний { uint bal = balances[msg.sender]; require(bal > 0);
}
Защищено: солидность функция withdraw() внешний { uint bal = balances[msg.sender]; require(bal > 0);
}
Обновляя состояние перед внешними взаимодействиями, контракт остается безопасным, даже если внешний вызов инициирует повторный вызов функции.
3. Защита между контрактами с GlobalReentrancyGuard
Для проектов с несколькими взаимодействующими контрактами общий защитник от повторного входа обеспечивает всестороннюю защиту:
солидность // Центральный контракт для защиты от повторных вызовов контракт GlobalReentrancyGuard { mapping(address => bool) частный _status;
}
// Использование охранника в контракте контракт ProtectedContract is GlobalReentrancyGuard { функция protectedFunction() внешняя { _beforeNonReentrant();
}
Эта техника предотвращает повторный вход через контракты, поддерживая глобальный реестр состояния, который отслеживает статус выполнения по нескольким контрактам в вашей экосистеме.
Лучшие практики безопасности
Чтобы обеспечить комплексную защиту от атак повторного входа:
Внедрив эти механизмы защиты, вы можете эффективно защитить свои смарт-контракты от одного из самых опасных векторов атак в безопасности блокчейна.