3 августа 2023 года MEV-бот в сети Arbitrum подвергся атаке, в результате которой было потеряно 800 000 долларов США. Первопричиной этой атаки стала недостаточная проверка пользовательского ввода.
Учитывая сложные взаимодействия между MEV-ботами и их непроверенными контрактами, становится ясно, что отсутствие открытого исходного кода не гарантирует безопасность, особенно для DeFi-протоколов.
Предыстория
MEV-бот
MEV-бот (Maximum Extractable Value Bot) предназначен для обнаружения и реализации выгодных возможностей в блокчейне. Он работает путем анализа ожидающих транзакций (то есть тех, что находятся в мемпуле) или состояний внутри сети для получения прибыли через арбитраж.
В отличие от типичных MEV-ботов, использующих фронтраннинг и сэндвич-атаки, MEV-бот, ставший целью этой атаки, был сосредоточен на выполнении таких стратегий, как треугольный арбитраж и ликвидация задолженности. Сами по себе эти боты помогают стабилизировать цены для AMM и способствуют ликвидации активов в протоколах кредитования для обеспечения бесперебойной работы, составляя важную часть здорового функционирования DeFi-экосистемы.
Флеш-кредит (Flashloan)
Флеш-кредит представляет собой уникальную инновацию в DeFi-экосистеме – форму беззалогового кредитования. Вы можете взять взаймы до миллиарда долларов через Flashloan без какого-либо обеспечения при условии, что кредит будет погашен в рамках той же транзакции. Если кредит не будет возвращен в течение этой же транзакции, она будет отменена, как будто ее никогда не существовало.
Этот механизм обычно используется для арбитража или использования других DeFi-стратегий для извлечения выгоды из временных рыночных неэффективностей.
Уязвимость
Краткая версия
Недостаточная проверка параметров пользовательского ввода позволила злоумышленнику внедрить FakeFlashloanProvider. Контракт хранилища (Vault) использовал этого провайдера для инициирования флеш-кредита. Впоследствии, возможно, для погашения флеш-кредита, контракт хранилища одобрил передачу токенов FakeFlashloanProvider, что привело к несанкционированному выводу активов из хранилища.
Подробная версия
Эксплуатируемые контракты:
Vault: Контракт-жертва 0xd614927acfb9744441180c2525faf4cedb70207f выступает в роли «Хранилища», предоставляя резервы и обеспечивая флеш-кредиты от других протоколов, таких как AAVE и Balancer.Arbitrage Bot: Уязвимый контракт 0x8db0efee6a7622cd9f46a2cf1aedc8505341a1a7, функционирующий как «Арбитражный бот», обладающий ролью заемщика в контракте «Хранилище».
Функция 0x0582f20f() в «Арбитражном боте» является основной точкой входа для запуска арбитражных сделок.
Сначала она вызывает borrow() в «Хранилище» для получения первоначального капитала, а затем выполняет логику арбитража через delegatecall к внешнему контракту, указанному в calldata, без какой-либо проверки.
function 0x0582f20f(...) {
...
v67, /* uint256 */ v68 = address(0xd614927acfb9744441180c2525faf4cedb70207f).borrow(address(v39), address(v9[0]), v29).gas(msg.gas);
...
// 0x4da91757 = swap(address,address,address,uint256,uint256,uint256,address)
MEM[MEM[64] + 32] = uint224(address(MEM[0 + v4[v69]])) | 0x4da9175700000000000000000000000000000000000000000000000000000000;
v82 = address(v76 >> 96).delegatecall(MEM[(MEM[64]) len 228], MEM[(MEM[64]) len 0]).gas(msg.gas);
...
v189 = v170.refund(0x410085df, address(v9[0]), address(v39), v68, address(v9[0]), v29, v186, 4 + MEM[64] + (varg2.length << 5) - (4 + MEM[64]) + 192).gas(msg.gas);
...
}
Впоследствии он вызывает 0x512b7351() в «Хранилище», запуская флеш-кредит к контракту злоумышленника FakeFlashloanProvider.
Функция 0x512b7351() требует, чтобы msg.sender находился в списке разрешенных (allowlist), но проверка была успешно обойдена предыдущим вызовом delegatecall. Это критически важный этап.
function 0x512b7351(...) public nonPayable {
...
if (_borrow[msg.sender] >= 1) {
v0 = !_refund;
}
require(v0, Error('BBVault: FORBIDDEN'));
...
v38 = v23.length;
v39 = v23.data;
_refund = keccak256(v23);
...
<FakeFalshloanProvider>.flashloan(...);
...
}
Во время обратного вызова (callback) флеш-кредита, функция executeOperation() в «Хранилище» сначала переводит заемные активы в «Арбитражный бот» 0x8db0ef, а затем вызывает его 0x7fe3ba8b().
function executeOperation(...) {
...
require(_refund == keccak256(v3.data), Error('BBVault: STATUS'));
Token.transfer(ArbitrageBot, amountBorrowed);
<ArbitrageBot>.call(0x7fe3ba8b...);
}
«Арбитражный бот», доверяя этому внешнему вызову, переводит полученные активы обратно в FakeFlashloanProvider.
Однако «Хранилище» не распознает этого и все равно предоставляет одобрение (approval) на перевод средств для FakeFlashloanProvider для погашения флеш-кредита в конце выполнения executeOperation().
Процесс атаки
Транзакция атаки: 0x864c8cfb8c54d3439613e6bd0d81a5ea2c5d0ad25c9af11afd190e5ea4dcfc1f
Злоумышленник вызывает 0x0582f20f() «Арбитражного бота», который, в свою очередь, выполняет delegatecall к контракту злоумышленника.


Контракт hack_contract_2 затем вызывает функцию victim 0x512b7351(). Функция 0x512b7351() требует, чтобы msg.sender был в списке разрешенных, но эта проверка была успешно проигнорирована из-за предыдущего delegatecall.

Затем victim (жертва) вызывает контракт злоумышленника FakeFlashloanProvider, переводя все активы флеш-кредита в victim и вызывая функцию executeOperation() жертвы.

Функция 0x7fe3ba8b() «Арбитражного бота» снова выполняет delegatecall к контракту злоумышленника, в этот раз переводя все активы обратно злоумышленнику.
На этом этапе активы, предоставленные провайдером флеш-кредита злоумышленника, были погашены.

Жертва («Хранилище») одобряет токены для FakeFlashloanProvider, вероятно, с намерением погасить флеш-кредит.

Злоумышленник использует это одобрение для получения прибыли, применяя transferFrom для вывода средств из хранилища жертвы.
Рекомендации по безопасности
Неоткрытый исходный код не гарантирует безопасность
Мнение о том, что закрытый и запутанный код гарантирует безопасность — это заблуждение. Этот инцидент с MEV-ботом показывает, что секретность не защищает от эксплойтов и может дать разработчикам ложное чувство защищенности.
Тщательная проверка входных данных
Крайне важно тщательно проверять все взаимодействия с контрактами и calldata, особенно при работе со стандартными интерфейсами, такими как флеш-кредиты и колбэки обмена токенов. Обеспечение целостности данных и безопасности должно быть приоритетом при проектировании и реализации контрактов.
Читайте другие статьи из этой серии:
- Введение: Десять самых «выдающихся» инцидентов безопасности в 2023 году
- #1: Сбор MEV-ботов путем использования уязвимостей в Flashbots Relay
- #2: Инцидент с Euler Finance: Крупнейший взлом 2023 года
- #3: Инцидент с KyberSwap: Мастерская эксплуатация ошибок округления с крайне тонкими вычислениями
- #4: Инцидент с Curve: Ошибка компилятора создает дефектный байт-код из безобидного исходного кода
- #5: Platypus Finance: Пережить три атаки благодаря удаче
- #6: Инцидент с Hundred Finance: Катализатор волны связанных с точностью эксплойтов в уязвимых форкнутых протоколах
- #7: Инцидент с ParaSpace: Гонка со временем, чтобы предотвратить самую критическую атаку в отрасли
- #8: Инцидент с SushiSwap: Неуклюжая попытка спасения ведет к серии атак-подражателей
- #10: Инцидент с ThirdWeb: Несовместимость между доверенными модулями раскрывает уязвимость



