Как хакеры завладели Enjin и вывели $163 тыс

Введение
Enjin — это платформа для создания и управления цифровыми предметами (NFT) в игровой индустрии. ENJ — её нативный токен. Пользователи могут создавать NFT, вкладывая в них токены ENJ, а затем «плавить» (уничтожать) NFT, чтобы вернуть заложенные токены.
Ход инцидента
initialize в одном из подключаемых модулей. Эта функция должна была задать начальные настройки, но из-за ошибки в расположении данных записывала значение не в свою ячейку памяти, а в ячейку, которую использовал proxy-контракт для хранения адреса ожидающего управляющего (pendingManager).2. Злоумышленник вызвал эту функцию и записал туда свой адрес. Затем вызвал
acceptManager() — функцию подтверждения прав управляющего. Система проверила: адрес в поле pendingManager совпадает с адресом вызывающего. Права manager были переданы.3. Получив управление, злоумышленник подключил вредоносный adapter — подключаемый модуль. Он перенаправил через него функции
stealNFT и transferFrom, которые обычно используются для перевода цифровых предметов.4. С помощью этих функций он принудительно переводил Enjin X-активы — это NFT в экосистеме Enjin — с пользовательских адресов на свой контракт. Пользователи не давали на это разрешения.
5. Полученные активы сразу уничтожались через механизм melt. При уничтожении NFT высвобождались заложенные в них токены ENJ, которые поступали на контракт атакующего.
6. В конце транзакции злоумышленник вывел 6 518 518 ENJ на свой внешний кошелёк. По курсу на момент инцидента это составило около $163 тыс.
Почему это стало возможным
Проблема заключалась в коллизии storage — ситуации, когда одна и та же ячейка постоянной памяти используется разными частями кода для разных целей.
Proxy-контракты Enjin позволяли подключённым модулям изменять внутренние данные через DELEGATECALL. Из-за ошибки в структуре данных модуль и proxy-контракт «делили» одну ячейку. Функция
initialize, которая должна была работать только с данными модуля, фактически писала в поле pendingManager proxy-контракта.Это дало возможность любому пользователю записать свой адрес в поле ожидающего управляющего, а затем официально подтвердить права. После захвата управления открывалась возможность подключать любые модули и перенаправлять функции перевода активов.
Детали расследования: движение средств
После получения токенов ENJ злоумышленник обменял их на DAI — стейблкоин, привязанный к доллару США.
Заключение
Инцидент в Enjin показал, что даже проверенные архитектурные паттерны — такие как proxy-контракты с подключаемыми модулями — могут содержать скрытые ошибки в расположении данных. Коллизия storage, отсутствие проверки доступа к функции
initialize и возможность подключать произвольные модули без дополнительной верификации привели к захвату управления и краже пользовательских активов. 

