
Отравление адресов: атака, которой нужно лишь чтобы вы скопировали не то
Почти все атаки на пользователей криптовалют требуют, чтобы вы ошиблись: нажали на ссылку, ввели сид-фразу в форму, одобрили то, чего не прочитали. Отравлению адресов нужно меньше. Ему нужно, чтобы вы скопировали адрес из собственной истории транзакций.
Нет ни вредоносного кода, ни фишингового сайта, ни подписи, которую надо у вас выманить. Весь вклад атакующего — положить правдоподобно выглядящую строку туда, куда вы позже потянетесь.
Как это работает
Начнём с того, что вообще делает это возможным: адреса никто не читает. Биткоин- или эфириум-адрес — это три десятка с лишним символов base58 или шестнадцатеричных, без смысла, без контрольной суммы, которую можно оценить на глаз, и без единой причины держать его в голове. Поэтому все кошельки, обозреватели блоков и биржи сокращают их для показа — 0x8f3C…9A063 — и все пользователи приучаются проверять видимые концы и пропускать середину.
Эта привычка и есть вся поверхность атаки.
Атакующий перебором генерирует адреса, пока один не совпадёт по первым и последним символам с адресом, которым вы действительно пользуетесь, — обычно с тем, куда вы недавно отправляли деньги. Это дёшево. Генерировать пары ключей быстро, а подобрать, скажем, четыре ведущих и четыре хвостовых символа на обычном железе — вопрос секунд. Никто ничего не взламывает; просто бросают кости, пока число не покажется знакомым.
Затем этот адрес заводят в вашу историю. Обычные способы:
Пыль. Вам присылают крошечную сумму — несколько сатоши, доли цента какого-нибудь токена — с похожего адреса. Это обычная входящая транзакция, поэтому она ложится в вашу историю, как любая другая. В UTXO-сетях пыль вдобавок становится тратимой монетой в вашем кошельке, и это пригодится дальше.
Переводы нулевой суммы. В EVM-сетях transfer нуля токенов ERC-20 — валидная транзакция. Атакующий отправляет 0 токенов с вашего адреса на свою подделку, и некоторые интерфейсы рисуют это как исходящий платёж, сделанный вами. Ваша история теперь показывает, что вы будто бы отправляли на адрес, который никогда не выбирали.
Поддельные события. Вредоносный контракт токена может испустить событие Transfer, которого не было. Обозреватели и кошельки, доверяющие журналам событий, его покажут. Ничего не двигалось; запись — просто ложь.
Дальше они ждут. Дни, иногда месяцы. Атака окупается в следующий раз, когда вы соберётесь платить тому же контрагенту, пролистаете историю в поисках «адреса, который я использовал в прошлый раз», и скопируете не ту строку. Оба выглядят как 0x8f3C…9A063. Вы проверяете концы. Концы совпадают.
Почему обычный совет не держит
«Всегда перепроверяйте адрес» — стандартная рекомендация, и сама по себе она проваливается, потому что проверка — ровно то, на что атака и рассчитана. Вы проверили. Вы сравнили шесть символов, показанных кошельком, с шестью символами в памяти, и они совпали — потому что атакующий сделал их одинаковыми.
Проверка работает только тогда, когда сравниваемое дорого подделать. Четыре или шесть совпадающих символов стоят секунд. Шестнадцать совпадающих символов стоили бы дороже, чем сама кража. Вся игра — в том, на каком конце этой кривой находятся ваши привычки.
В UTXO-сетях есть вторая ловушка. Тот пылевой платёж теперь монета в вашем кошельке, и если кошелёк автоматически объединяет входы, она может попасть в более позднюю транзакцию, связав запылённый адрес с остальными вашими монетами. Это скорее проблема приватности, чем кражи, но именно поэтому пыль стоит игнорировать, а не «прибирать».
Что действительно защищает
Никогда не берите адрес из истории транзакций. Это единственное изменение, которое имеет значение. Ваша история — запись того, что произошло, а не список тех, кому вы доверяете, и писать в неё может кто угодно в мире. Берите адреса у контрагента, по каналу, где вы заметили бы самозванца, или из адресной книги, которую заполняли сами.
Сравнивайте адреса целиком — или сравнивайте то, что суммирует адрес целиком. Прочитать все сорок два символа нереалистично. Сравнить идентикон — маленькую картинку, детерминированно порождённую из всей строки, — вполне, потому что подделка, отличающаяся где угодно в середине, даёт заметно другой рисунок. Ваш глаз делает работу, которую не сделает ваше терпение.
Пользуйтесь сохранённым контактом. Адрес, сохранённый однажды из однажды проверенного источника, позже отравить нельзя. Для этого адресные книги и существуют, и поэтому SSP хранит контакты на вашем устройстве, а не на сервере: список контактов надёжен, только если никто другой не может его править.
Отправляйте пробный платёж при крупных или первых переводах. Малая сумма, подтверждение получения по другому каналу, потом остальное. Комиссии делают это неудобным, и это по-прежнему правильно для платежа, который было бы больно потерять.
Игнорируйте пыль. Не тратьте её, не «наводите порядок» и будьте осторожны с автоматическим объединением, если вам важна приватность.
Что с этим делает SSP
Отравление адресов — задача отображения не меньше, чем безопасности, поэтому часть ответа живёт в том, как адреса рисуются.
SSP сокращает адреса до шести ведущих и шести хвостовых символов — 0x8f3C4b…9A0631 — вместо трёх-четырёх, которые использует множество интерфейсов. Это не косметика. Каждый лишний символ умножает перебором стоимость получения совпадения, а двенадцать видимых символов уводят убедительную подделку далеко за пределы «между делом сгенерировал».
Середина приглушается, а не удаляется. В развёрнутом виде кошелёк показывает всю строку: концы полужирным, середина светлее, — так что та часть, на пропуск которой рассчитывают атакующие, физически остаётся на экране, а не заменяется многоточием, за которым может скрываться что угодно.
Один и тот же код работает в обоих приложениях. splitAddressForDisplay в SSP Wallet — прямой порт из SSP Key, намеренно оставленный идентичным, чтобы адрес выглядел одинаково в браузере и на телефоне. Это важно, потому что SSP показывает вам транзакцию дважды, на двух устройствах, — а второй взгляд становится настоящей проверкой только тогда, когда обе поверхности рисуют одно и то же одинаково. Два разных способа сокращения позволили бы расхождению спрятаться в этой разнице.
На экране одобрения в SSP Key получатель показывается с идентиконом, порождённым из полного адреса, рядом с сокращённым текстом, а по нажатию адрес разворачивается целиком как выделяемый текст. Именно идентикон побеждает подмену в середине строки: атакующий может подогнать ваши первые и последние символы, но не может подогнать картинку, выведенную из каждого символа, не решив куда более трудную задачу.
Ничто из этого не гарантия. Если вы вставите отравленный адрес и одобрите его на обоих устройствах, SSP его подпишет — это и значит быть кошельком, который вы контролируете, а не хранителем, оспаривающим ваши решения. Мультиподпись два из двух не даёт другому потратить ваши монеты; она не помешает вам намеренно заплатить не тому. Как и в любой атаке, которая работает через ваши действия, защита должна сработать до подписи, а не во время неё.
Коротко
Отравление адресов работает потому, что вы сравниваете шесть символов вместо сорока двух, а атакующий знает, какие именно шесть. Защита — не в большей внимательности, а в том, чтобы никогда не брать адрес оттуда, куда может писать атакующий, и пользоваться инструментами, которые возвращают вам на глаза те части, что вы пропустили бы.


