Анализ принципа уязвимости подмены произвольного адреса в ERC2771 Multicall от SharkTeam

robot
Генерация тезисов в процессе

8 декабря 2023 OpenZeppelin выпустил важное предупреждение о безопасности. Оказывается, при совместном использовании стандарта ERC-2771 и функций типа Multicall есть риск подмены адреса! Я глубоко изучил эту уязвимость и хочу поделиться своими находками.

Анализ атаки

Рассмотрим одну из атак:

  • Атакующий: 0xFDe0d1575Ed8E06FBf36256bcdfA1F359281455A
  • Транзакция: 0xecdd111a60debfadc6533de30fb7f55dc5ceed01dfadd30e4a7ebdb416d2f6b6

Схема атаки гениально проста:

  1. Злоумышленник обменял 5 WETH на примерно 3,455,399,346 TIME
  2. Затем сконструировал хитрые параметры calldata и вызвал [Forwarder].execute
  3. Эта функция запустила multicall в контракте TIME, а оставшийся calldata использовался для burn() - уничтожения токенов в пуле!

Как же это работает?

В этой атаке сошлись звёзды: ERC-2771, Multicall и тщательно составленные данные. Контракт TOKEN наследует ERC2771Context, и тут начинается самое интересное!

ERC-2771 даёт виртуальный msg.sender, позволяя делегировать транзакции третьей стороне. При этом настоящий адрес добавляется в calldata. Когда [Forwarder] вызывает контракт, _msgSender() проверяет эти данные и обрезает последние 20 байт как "настоящий" msg.sender.

Multicall же превращает один вызов в несколько, экономя газ. Он принимает массив вызовов и выполняет их через delegatecall().

И вот тут ловушка! Атакующий смещает calldata так, что первые 4 байта новых данных соответствуют функции burn(), а параметр - огромная сумма токенов. В строке 0x20 добавляется адрес TIME-ETH пула ликвидности, который становится "ожидаемым" msg.sender!

Корень проблемы

В ERC-2771 [Forwarder] никогда не планировался для работы с multicall! Атакующий добавил параметры _msgSender() во внешний вызов multicall. Внутри функции multicall некоторые функции тоже добавляли эти параметры, что позволило имитировать вызов от ЛЮБОГО адреса!

Меры защиты

  1. Новая версия OpenZeppelin Multicall теперь сохраняет длину контекста ERC-2771 и учитывает её при каждом дочернем вызове.

  2. ThirdWeb пошёл дальше и запретил любым контрактам вызывать multicall, предотвращая использование [Forwarder].

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

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