Как мы сообщали ранее, спцециалисты по кибербезопасности из компанииIndependent Security Evaluators (ISE) обнаружили 732 уязвимых закрытых ключа, которые подписали 49 060 транзакций в блокчейне эфириума.

В ходе исследования было обнаружено, что средства с этих уязвимых адресов были отправлены на адрес, принадлежащей хакеру (или группе хакеров), которые проводят активную кампанию по компрометации закрытых ключей с целью получения этих средств. Ниже более подробная историю того, как исследователям удалось обраружить«блокчейн-бандита» (они его так назвали).

Блокчейны — это открытые реестры транзакций, верифицируемые с помощью открытых и закрытых ключей для подтверждения права владения данными транзакций. В настоящее время в блокчейне эфириума есть 345 млн. транзакций, которые были созданы 47 млн. пар ключей.

Вероятность генерации закрытого ключа, уже используемого в блокчейне, составляет около 1 на 2 в 256 степени (то есть на практике невозможно). Чтобы покрыть только 1% возможных комбинаций ключей — даже если использовать вычислительные ресурсы, позволяющие генерировать 100 триллионов ключей в секунду — потребовалось бы несколько лет. Однако вместо попыток полного перебора закрытых ключей специалисты ISE разработали способы обнаружения ключей, которые могли быть сгенерированы с уязвимостями в коде и/или генераторе случайных чисел. В следующих разделах описано, как генерируется адреса в эфириуме, а также подход ISE к обнаружению закрытых ключей, которые были сгенерированы c этими уязвимостями.

Закрытые ключи эфириума

Проект эфириум использует криптографию на основе эллиптических кривых для генерации пары открытых/закрытых ключей. 256-битный закрытый ключ используется для вычисления точки на кривой secp256k1 для генерации открытого ключа. Затем открытый ключ хешируется с помощью алгоритма keccak256. Этот хеш усекается 160 бит, чтобы получить публичный адрес. Адрес эфириума не может быть реверсирован или использован каким-либо другим образом для получения закрытого ключа, который использовался для его генерации.

Учитывая случайно сгенерированный закрытый ключ, то есть в пределах допустимого диапазона от одного до максимального значения, определенного кривой secp256k1, мы можем получить открытый адрес, взяв самые правые 160 бит хеша открытого ключа keccack256. На рисунке ниже показан процесс для получения адреса эфириума из случайно сгенерированного 256-битного закрытого ключа.

Зная этот алгоритм, цель нашего исследования состояла в том, чтобы найти адреса эфириума, которые могли быть сгенерированы уязвимой реализацией алгоритма, или которые были верно получены, но из неслучайных закрытых ключей.

Блокчейн эфириума позволяет любому запрашивать адрес для получения информации о нём. Это делается путем запроса в ноду эфириума, которая может быть запущена локально или удаленно. Несколько онлайн-сервисов предоставляют базовые данные о адресах — к примеру, Etherscan, который может использоваться для запроса публичного адреса эфириума из приведенного выше примера: A99FDD90FF61DD08CF049155D18E086F7806641B. Можно найти этот адрес на Etherscan и увидеть, что адрес получил 0 транзакций.

Учитывая, что почти 50 млн. публичных адресов эфириума подписывали транзакции, вполне вероятно, что мы можем столкнуться со слабыми или неслучайными ключами из-за нескольких возможных факторов. Одним из наиболее очевидных является усечение ключа. То есть, когда генерируется случайный 256-битный закрытый ключ, но используется только небольшое подмножество из-за кодирования/компилятора/фреймворка или других неизвестных ошибок. Возьмем, к примеру, 256-битный закрытый ключ со значением:

  • 0x47579DA2BEA463533DBFAD6FCF8E90876C2FE9760DC1162ACC4059EE37BDDB5C

Если обрезать до 32 бит, получится следующий ключ:

  • 0x0000000000000000000000000000000000000000000000000000000037BDDB5C

В эксперименте мы выбрали закрытый ключ, равный 1, только по той причине, что он является нижней границей возможного закрытого ключа для secp256k1. Таким образом, мы используем закрытый ключ

  • 0x0000000000000000000000000000000000000000000000000000000000000001

для получения публичного адреса 0x7e5f4552091a69125d5dfcb7b8c2659029395bdf.

Как говорилось ранее, крайне маловероятно то, что два пользователя эфириума сгенерируют один и тот же закрытый ключ — при условии, что по крайней мере один пользователь генерирует его случайным образом. Не имеет значения, исследуем ли мы ключи полным перебором, начиная от нижних или верхних значений, или ключей, которые используют цифры числа «пи», случайно сгенерированных и т. д. — в любом случае не должно быть совпадений со случайно сгенерированным ключом другого пользователя эфириума.

Мы обнаружили, что адрес, полученный из закрытого ключа 0x01, имеет 679 транзакций (хотя в настоящее время на этом адресе эфир не хранится). Мы можем предположить, что закрытый ключ 0x01 было выбран специально или из-за ошибки. Следующие разделы детализируют наш поиск, чтобы понять и изучить, как широко распространено создание слабых ключей в блокчейне эфириума.

Метод исследования

Целью нашего исследования был поиск адресов эфириума, основанных на использовании слабых ключей, и изучение того, как эти адреса используются. Хотя маловероятно, что слабый ключ когда-либо будет сгенерирован при использовании правильного алгоритма, мы предположили, что слабые закрытые ключи могут генерироваться из-за ошибок кода или ошибок операционной системы, устройства и среды выполнения, и что эти проблемы общие. Помимо усечения ключей, есть несколько других распространенных ошибок, которые могут ослабить 256-битные ключи:

  • Ошибки логики кода;
  • Ошибки энтропии;
  • Случайные ошибки устройства;
  • Плохо обработанные исключения;
  • Ошибки памяти;
  • Повреждение памяти;
  • Компрометация вредоносным ПО.

Конечно же, из-за ограниченных вычислительных ресурсов не представляется возможным перебрать все ключи эфириума, поэтому мы сосредоточились на более достижимых целях: переборе ключей, которые появляются в 32-битном подмножестве 256-битного закрытого ключа. Это 4 294 967 295 закрытых ключей, для которых нам потребуется вычислить соответствующий публичный адрес эфириума и найти его в блокчейне.

Для массового сканирования потенциальных адресов эфириума нецелесообразно (и даже неправильно с точки зрения использования ресурсов) делать запросы в такие онлайн-сервисы как Etherscan. Вместо этого мы сгенерировали хеш-карту всех публичных адресов эфириума. На локальном ноутбуке среднего класса это позволяет генерировать примерно 15 000 ключей в секунду.

Мы сфокусировались на восьми 32-битных подмножествах в 256-битном пространстве ключей, чтобы найти используемые адреса эфириума, которые были получены из слабых закрытых ключей. Чтобы проиллюстрировать области, которые мы отсканировали, на иллюстрации ниже показано каждое подмножество, который мы определили.

Группа А 0000000000000000000000000000000000000000000000000000000000000001 до 00000000000000000000000000000000000000000000000000000000FFFFFFFF

Группа Б 0000000000000000000000000000000000000000000000000000000100000000 до 000000000000000000000000000000000000000000000000FFFFFFFF00000000

Группа С 0000000000000000000000000000000000000000000000010000000000000000 до 0000000000000000000000000000000000000000FFFFFFFF0000000000000000

Группа D 0000000000000000000000000000000000000001000000000000000000000000 до 00000000000000000000000000000000FFFFFFFF000000000000000000000000

Группа Е 0000000000000000000000000000000100000000000000000000000000000000 до 000000000000000000000000FFFFFFFF00000000000000000000000000000000

Группа F 0000000000000000000000010000000000000000000000000000000000000000 до 0000000000000000FFFFFFFF0000000000000000000000000000000000000000

Группа G 0000000000000000000000000000000000000000000000000000000000000000 до 00000000FFFFFFFF000000000000000000000000000000000000000000000000

Группа Н 0000000100000000000000000000000000000000000000000000000000000000 до FFFFFFFF00000000000000000000000000000000000000000000000000000000

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

Результаты

Мы обнаружили 49 060 транзакций на общую сумму 32 ETH, распределенных по 732 открытым ключам, для которых мы нашли закрытый ключ. Текущее балансы по этим ключам составляли 0 ETH, однако эти балансы непостоянны, поскольку на адреса периодически поступает эфир.

Большинство ключей было обнаружено в группе A — 464 секретных ключа. Общая стоимость транзакций с использованием этих слабых закрытых ключей составила 28,9456 ETH (при текущем балансе 0 ETH). Интересно, что один ключ в группе B имел исходящую транзакцию на адрес, который в настоящее время содержит 44 744 ETH (подробнее об этом ниже).

К счастью, использование слабых закрытых ключей не является широко распространенной проблемой. Однако было удивительно встретить 732 активных ключа, к которым мы могли получить доступ. Также нас удивил большой совокупный объем транзакций.

Общее время вычислений для сканирования 8 групп на 256-битном пространстве ключей через 32-битные окна составило около 128 часов работы ЦП на группу (всего 1024 часа). К счастью, эту задачу можно выполнять параллельно, и мы смогли разделить все 8 групп и отсканировать их за 8 часов. Таким образом, можно проводить периодические проверки для выявления новых слабых закрытых ключей.

Blockchainbandit

Как мы упоминали выше, при сканировании была обнаружена исходящая транзакция на адрес 0x957cd4ff9b3894fc78b5134a8dc72b032ffbc464. Мы его называем «блокчейн-бандит» (blockchainbandit). После беглого изучения этой транзакции мы обнаружили, что адрес назначения принадлежит какому-либо человеку или группе, которая проводит активные кампании для компрометации/сбора закрытых ключей — сейчас на балансе находится 44 747 ETH ($7 400 000). Блокчейн-бандиту удалось собрать столько эфира за счёт 5487 транзакций.

Мы хотели посмотреть, как быстро блокчейн-бандит забирает средства, поэтому направили $1 в эфире на адрес, закрытый ключ которого он должен знать — 0x0000000000000000000000000000000000000000000000000a00000000000000, который представлен следующим публичным адресом: 0x4c636a08fdf3692a9bca111e8a7f4a0e28eb4457. Бандит мгновенно отправил транзакцию с этого адреса на свой.

Проводя дополнительные исследования с целью понять, почему и как генерируются эти слабые ключи, мы также столкнулись с проблемой в кошельке Parity.

Кошелёк Parity с пустым сидом

Адрес 0x00a329c0648769a73afac7f9381e08fb43dbea72 получен из закрытого ключа 0x4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7, который генерируется их пустого сида (“ ”) при использовании кошелька Parity. По этому адресу было совершено 13 409 транзакций и передано 5215,586 ETH. Этот адрес очень активый — на приведенном ниже рисунке показано ежемесячное количество транзакций (адрес впервые был использован в блокчейне эфириума в марте 2017 года):

Заключение

В связи с растущей популярностью криптовалют в сочетании с довольно успешными хакерскими кампаниями мы вынуждены сделать вывод, что количество целевых атак на любые системы, работающие с закрытыми ключами, в будущем будет только расти. Разработчики ПО, которые взаимодействуют с очень ценными закрытыми ключами, должны знать о всех принципах всесторонней защиты от существующих угроз и использовать инновационные меры для противодействия угрозам в будущем.

Любая реализация, которая использует генерацию открытого ключа на основе ECDSA (Bitcoin, Waves, Ripple, ZCash, Monero и др.) или аналогичных криптографических алгоритмов, должна быть проверена на наличие ошибок генерации ключа.

Источник coinspot.io