Атака повторного входа: Понимание и предотвращение этой уязвимости смарт-контракта

Я провел бесчисленные часы, отлаживая эксплойты контрактов, и позвольте мне сказать вам: атаки повторного входа - это тихие убийцы смарт-контрактов. Они обманчиво просты, но разрушительно эффективны. Давайте погрузимся в то, что это такое и как остановить их, прежде чем они опустошат ваши средства.

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

Представьте себе: ContractA имеет 10 ETH, а ContractB внес 1 ETH в него. Когда ContractB выводит свои средства, ContractA отправляет ETH, прежде чем обновить баланс B до нуля. Эта небольшая ошибка последовательности создает огромную уязвимость безопасности.

Что происходит? Функция обратного вызова вредоносного контракта немедленно вызывает withdraw() снова, и поскольку баланс еще не был обновлен, она снова проходит проверку баланса! Этот цикл повторяется, пока ContractA полностью не будет опустошен. Черт возьми, как умно, не правда ли?

Вот как злоумышленник использует это в коде:

// Атака контракта вызывает withdraw() // ContractA отправляет ETH, что вызывает fallback() // fallback() снова вызывает withdraw() до обновления баланса // Полоскайте и повторяйте, пока все средства не будут украдены

Я видел, как проекты теряли миллионы, потому что не понимали эту простую вектор атаки. Меня бесит, как много разработчиков все еще совершают эту rookie ошибку.

Три техники для защиты ваших смарт-контрактов

  1. Модификатор nonReentrant

    Это блокирует контракт во время выполнения, предотвращая повторный вход в любую функцию, помеченную этим модификатором. Просто, но эффективно.

  2. Шаблон Проверок-Эффектов-Взаимодействий

    Это мой личный фаворит. Вместо:

    // УЯЗВИМЫЙ require(balance > 0); отправить(эфир); баланс = 0;

    Сделайте это:

    // БЕЗОПАСНО require(balance > 0); баланс = 0; // Обновить состояние ПЕРЕД внешними взаимодействиями отправить(эфир);

    Всегда обновляйте свое состояние перед отправкой ETH или токенов!

  3. ГлобальнаяReentrancyGuard

    Для проектов с несколькими взаимодействующими контрактами это обеспечивает защиту по всей вашей экосистеме контрактов, используя общий механизм блокировки.

Эти техники не являются лишь академическими - они спасли бесчисленные проекты от полного финансового краха.

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

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

ETH-0.98%
Посмотреть Оригинал
На этой странице может содержаться сторонний контент, который предоставляется исключительно в информационных целях (не в качестве заявлений/гарантий) и не должен рассматриваться как поддержка взглядов компании Gate или как финансовый или профессиональный совет. Подробности смотрите в разделе «Отказ от ответственности» .
  • Награда
  • комментарий
  • Репост
  • Поделиться
комментарий
0/400
Нет комментариев
  • Закрепить