Краткое описание
Вчера была совершена атака на релееров, суммарные потери составили более 2 ETH.
Метод атакующего заключался в том, что он инициировал транзакции вывода 0.1 ETH из пула через релееров, используя в качестве адреса получателя специальный контракт, созданный им ранее, не позволяющий получать средства на адрес контракта при выводе из пула Tornado - в результате, подобные транзакции релееров завершались с ошибкой, но комиссия сети за газ с них списывалась.
Принятые меры для решения проблемы
Сразу же после обнаружения проблемы - спасибо Vladoss, который заметил подозрительные транзакции и оповестил меня - мною были разосланы сообщения всем атакованным релеерам (ещё до выяснения атакующего и определения точного вектора атаки) - тем, чей контракт был мне известен, я написал в мессенджерах, остальные были уведомлены путём onchain-сообщений (1, 2).
Спустя несколько часов принцип атаки был уже полностью понятен и был выпущен экстренный патч программного обеспечения для релееров - внимание, ВСЕ релееры должны переустановить с нуля на чистый сервер текущий софт, пользуясь инструкцией в данном репозитории.
P.S. Кстати, если бы proposal 27 был принят, текущая ситуация бы не произошла - умное вычисление gas проверяет корректность транзакции перед выполнением. По этой же причине сайдчейны, код которых был обновлён, в безопасности - там подобный метод бы не сработал.
Полный лог событий
Адрес атакующего: 0x3b96c58304e1d980b3cad36296303c303120ec16
Подготовка к атаке:
- Атакующий вносит в пул Tornado Cash 0.1 ETH: tx link
- Атакующий создаёт мастер-контракт: адрес 0xa6cdb3cd8a27731754d7879b87cc30fc631a305e
- Вызывая функцию с селектором
e3fbf27a
, атакующий с помощью мастер-контракта создаёт 40 контрактов с одинаковым исходным кодом: tx link
Именно итоговые адреса 40 контрактов будут использованы в качестве получателей в транзакциях вывода при атаке.
Цели атакующего:
Были атакованы четыре релеера - default-relayer.eth, torrelayer.eth, а также first-relayer.eth через воркер-адрес 0x864df9cd806d58341f13602103bf853066ff962a и 0xgm777.eth через воркер-адрес 0x03392600086874456e08d2bac104380bcdebcfc0.
Стоит так же отметить, что атакованы все релееры, имеющие низкие комиссии (ниже 0.39% на Ethereum Mainnet), что позволяет с большой вероятностью предположить, что атакующим являлся один из релееров с высокой комиссией.
Все транзакции атакующего примерно идентичны (полный список можно увидеть в логе транзакций адресов, ссылки на которые представлены выше), поэтому для примера разберём одну транзакцию - 0x7bd231bef00a5943cee743aca1e026e5a0010b295e7ac3e734c081c25cd70270.
В функцию withdraw
у контракта Tornado Router пятым аргументом передаётся адрес, куда будут выведены средства:
Рассмотрим контракт по этому адресу: 0x65cebaa6f812ab4be7dc7fb1b2a8b62d548e0b60. Это один из описанных выше 40 контрактов и, поскольку контракт, разумеется, не верифицирован, декомпилируем его и посмотрим на вызываемую функцию:
Поскольку адрес, находящийся в переменной _operator
, является non-payable, отправить на него выводимый ETH невозможно. v0
после вызова становится false
, и вызов завершается выбросом ошибки revert(Error(v3))
, однако комиссия сети за транзакцию всё равно списывается с релеера.
Итоги
Суммарные потери атакованных релееров составили более 2 ETH, сильнее всего пострадал first-relayer.eth, потеряв примерно 1.2 ETH.
Патч выпущен спустя несколько часов после атаки, все релееры должны переустановить программное обеспечение на чистый Ubuntu-сервер по ссылке: https://git.tornado.ws/tornadocash/tornado-relayer
Так же, релееры запрашивают компенсацию потерь, однако это мы уже обсудим в английской теме, как в основной, когда она будет готова.