Часть I
Содержание
- Часть I - Отслеживание проблемы до источника
- Часть II - Контекст и влияние
- Кодовое название "Milk Sad"
- Не первый взлом: слабая энтропия в кошельке Cake
- Даже не второй взлом: Использование Mersenne Twister в кошельке Trust Wallet
- Текущие кражи в разных блокчейнах - некоторые факты
- Поиск кошельков - мотивация и ограничения
- Поиск кошельков - реализация
- Другие подтвержденные жертвы этой кражи
- Основная хронология краж
- Реакция команды Libbitcoin и контекст
- Предполагаемые проблемы с RNG в старых версиях bx
- Часть III - Итоги и перспективы
- Кредиты и благодарности
Часть II - Контекст и влияние
Для удобства чтения в этом разделе мы перейдем к нехронологическому изложению.
Кодовое название “Milk Sad”
Итак, перед нами стояла неожиданная задача по оперативному раскрытию информации, и мы столкнулись с необходимостью придумать проекту название, которое было бы актуально и в то же время ничего не говорило бы посторонним о сути технической проблемы. Было предложено использовать два начальных слова первого мнемонического секрета BIP39, генерируемого bx
в нулевой момент времени: milk sad wage cup reward [...]
-> Milk Sad. Так мы нашли название нашего проекта.
Не первый взлом: слабая энтропия в кошельке Cake
На ранней стадии оценки возможных уязвимостей, которые могут привести к подобной проблеме, один из членов нашей команды вспомнил о ситуации со слабой энтропией в кошельке Cake Wallet.
Насколько нам известно, в мае 2021 года команда разработчиков Cake Wallet объявила о наличии уязвимости в энтропии их кошельков, в связи с чем все пользователи должны были изменить свои мнемонические фразы.
Дальнейшее расследование этой ситуации, проведенное пользователем Reddit Pure-Cricket7485, выявило ощутимые недостатки в стратегии источника энтропии кошелька Cake Wallet.
В частности: Cake Wallet использовал для генерации сидов кошельков небезопасную функцию Dart’s Random():
Uint8List randomBytes(int length, {bool secure = false}) {
assert(length > 0);
final random = secure ? Random.secure() : Random();
final ret = Uint8List(length);
for (var i = 0; i < length; i++) {
ret[i] = random.nextInt(256);
}
return ret;
}
Это настоящая проблема, учитывая, что Dart’s Random() может вернуться к 0 или системному времени
Random::Random() {
uint64_t seed = FLAG_random_seed;
if (seed == 0) {
Dart_EntropySource callback = Dart::entropy_source_callback();
if (callback != nullptr) {
if (!callback(reinterpret_cast<uint8_t*>(&seed), sizeof(seed))) {
// Callback failed. Reset the seed to 0.
seed = 0;
}
}
}
if (seed == 0) {
// We did not get a seed so far. As a fallback we do use the current time.
seed = OS::GetCurrentTimeMicros();
}
Initialize(seed);
}
Один из пользователей Reddit сравнил этот подход с Mersenne Twister, что заставило нас задуматься, нет ли у bx
аналогичного недостатка.
Даже не второй взлом: Использование Mersenne Twister в кошельке Trust Wallet
Через несколько дней после начала процесса раскрытия информации мы узнали об уязвимости в Trust Wallet, опубликованной в конце апреля 2023 года. Прочитав прекрасный отчёт Ledger Donjon об обнаружении и исследовании CVE-2023-31290, мы были несколько шокированы, насколько эта уязвимость близка к уязвимости в bx
! А публикация Trust Wallet подтверждает, что атаки на кошельки их пользователей происходили уже в декабре 2022 года. Почему же деньги из кошельков, сгенерированных bx
, стали исчезать только в середине 2023 года?
Здесь есть в чём покопаться, поэтому начнём с деталей уязвимости.
Уязвимая версия Trust Wallet и bx
имеют один и тот же базовый фатальный недостаток, заключающийся в генерации энтропии кошелька на основе непригодного алгоритма MT19937 Mersenne Twister. bx
дополнительно использует для сида MT19937 некоторую информацию о часах, но на практике это не имеет большого значения для удалённой оффлайн атаки перебором. Это всё те же ограниченные 32 бита ключевого пространства, которые злоумышленники могут прочесать вдоль и поперёк.
Насколько нам известно, Trust Wallet создает только 12-словные кошельки на основе мнемоники BIP39, что фиксирует требования к энтропии (и, соответственно, к использованию ГПСЧ) на уровне 128 бит. bx
более гибкий и генерирует 128-, 192-, 256-битные выходы (и другие). Больше вариантов — больше пространства для поиска, но пересекаются ли кошельки, сгенерированные с помощью bx seed -b 128
, с кошельками, созданными Trust wallet?
Оказывается, нет — из-за нюанса в использовании ГПСЧ. Алгоритм MT19937 Mersenne Twister, используемый Trust Wallet и bx
, одинаков, но выход потребляется несколько по-разному.
При заполнении массива энтропии данными ГПСЧ Trust Wallet потребляет один выход MT19937 размером 32 бита, берёт для заполнения массива младшие 8 бит этого выхода и выбрасывает остальные 24 бита через & 0x000000ff
в wasm/src/Random.cpp:
// Copyright © 2017-2022 Trust Wallet.
//
[...]
void random_buffer(uint8_t* buf, size_t len) {
std::mt19937 rng(std::random_device{}());
std::generate_n(buf, len, [&rng]() -> uint8_t { return rng() & 0x000000ff; });
return;
}
В силу используемых в libbitcoin-system
механизмов C++ для pseudo_random::fill()
, его код выполняет то же самое усечение 32 бит -> 8 бит, но с точностью до наоборот — забирая из ГПСЧ 8 старших битов.
В результате все выходные данные bx seed
, насколько нам известно, находятся в совершенно ином ключевом пространстве, чем то, которое генерирует код Trust Wallet, а значит, и мнемоники BIP39 также отличаются.
Чтобы подтвердить это, проведём небольшой эксперимент. В отчёте Ledger Donjon приведён конкретный пример кошелька, который описывается следующим образом:
[...]
RNG seed: 0x8ec170a8
Mnemonic:
sorry slush already pass garden decade grid drip machine cradle call put
[...]
Если пересчитать RNG seed 0x8ec170a8
с помощью кода bx
для 12-словной мнемоники BIP39, то получится следующее:
local chef load churn future essence type leave program weird ancient owner
Это подтверждает, что процесс генерации кошельков действительно отличается.
В конце Ledger Donjon приводит следующую строку, которую, на наш взгляд, можно считать предвестием:
“В ходе нашего расследования мы также заметили, что среди уязвимых адресов есть несколько штук, которые были сгенерированы задолго до релиза Trust Wallet. Это, вероятно, означает, что данная уязвимость существует и в других реализациях кошелька, что не может не вызывать беспокойства…”
Однако мы подозреваем, что эти другие кошельки, замеченные Ledger Donjon, не были сгенерированы версиями bx
3.x
, если только Ledger Donjon не экспериментировал с выводами ГПСЧ и не натолкнулся на другую модель использования. Наличие других пострадавших кошельков в 12-словном диапазоне Trust Wallet позволяет предположить, что существуют и иные инструменты генерации кошельков, использующие MT19937. Из-за нехватки времени мы пока не проводили дальнейшее исследование.
Если сравнивать нашу задачу по раскрытию информации по bx
с задачей Ledger’а по Trust Wallet, то можно отметить, что в том случае раскрытие информации осуществлялось одному коммерческому и, очевидно, хорошо финансируемому производителю кошельков. Судя по публикациям, Trust Wallet имел прямые каналы связи с отдельными пользователями, которые он мог использовать для выборочного информирования их об уязвимостях, связанных с их кошельками. Кроме того, их кошельки были уязвимы лишь в течение ограниченного времени, и проблема была обнаружена относительно быстро, при этом многие пользователи продолжали использовать приложение как обычно.
В своем отчёте команда Trust Wallet называет общую сумму потерянных средств в 170 000 долларов США:
“Несмотря на все наши усилия, было совершено два эксплойта, в результате чего общая сумма потерянных средств на момент атаки составила около 170 000 долларов США.”
Как мы поняли, Trust Wallet решил материально стимулировать пользователей, чтобы они перевели свои средства в безопасное место, а также возместить потерянные средства пострадавшим от кражи. Кроме того, за скоординированное раскрытие информации они выплатили Ledger Donjon значительное вознаграждение в размере 100 000 долларов США.
К нашему случаю, к сожалению, большинство этих факторов неприменимы. Учитывая некоммерческий характер проекта Libbitcoin, отсутствие прямых каналов связи с конечными пользователями, многолетнюю историю существования пострадавших кошельков и, вероятно, широкое распространение импортируемых/экспортируемых ключей и мнемоник BIP39, ситуация для исследования безопасности и поиска проблем здесь гораздо сложнее.
С учётом уже опубликованных отчётов Trust Wallet и Ledger Donjon, компрометации всех закрытых ключей bx seed
и продолжающейся активной эксплуатации кошельков bx
, нам стало ясно, что долгое согласованное раскрытие информации никому не поможет. Если мы хотим дать владельцам пострадавших bx
кошельков шанс сохранить свои средства, то нам нужно стремиться к тому, чтобы публикация заняла несколько дней, а не месяцев. В данной ситуации время на стороне злоумышленников, а не жертв.
Хорошо зарекомендовавшие себя программы обеспечения безопасности, такие как Google Project Zero, придерживаются аналогичной политики в отношении активно эксплуатируемых уязвимостей:
“[...] если Project Zero находит доказательства того, что уязвимость активно эксплуатируется против реальных пользователей, то вместо 90-дневной политики вводится 7-дневная политика раскрытия информации. [...]”
Текущие кражи в разных блокчейнах - некоторые факты
Ввиду ограниченности по времени мы решили сфокусироваться на Биткойне как основной сети. Из-за гибкости вывода bx seed
могут быть затронуты средства во всех монетах, совместимых с мнемоникой BIP39 (или даже просто с сидом BIP32). При наличии основной работы и ограниченных временных и вычислительных ресурсов проделывать последовательность шагов по 100 раз не представлялось возможным. Поэтому данный обзор посвящен только Биткойну и даёт лишь частичное представление о действиях в рамках кражи. Приведённые цифры можно рассматривать как нижнюю границу общего объема пострадавшей денежной массы.
Для Биткойна можно выделить два основных кластера транзакций, которые, по нашему мнению, были злонамеренными:
1.) Крупная кража 2023-07-12:
Дата | транзакция | адрес получателя | примерный объём | замечено |
---|---|---|---|---|
2023-07-12 10:41 | 593e11588a2529ed.. | 3GMQRwh8Yz1WVftL.. | ~5.0538 | 14 адресов |
2023-07-12 10:41 | 81cfe97cc16a4939.. | 3LwDzjA1xH8amCHu.. | ~9.744 | > 300 адресов |
2023-07-12 10:41 | a22b33a9a4ca0de2.. | 3D2mKf28exn26v7B.. | ~9.744 | > 1200 адресов |
Мы приписываем их одному хорошо подготовленному вору, который похитил около ~29,65 BTC на сумму до 850 000 долларов США, и это только в биткоинах (по курсу на 8/2023). Мы считаем, что, скорее всего, в тот же день этот взломщик совершил кражу и других монет. На момент написания поста эти средства никуда не переместились с этого нового места.
- Существует и вторая, более ранняя модель движения средств, которая, как мы полагаем, также является кражей:
Это поведение началось 3 мая 2023 г. и состояло из множества небольших операций по зачистке кошельков, которые продолжались до 15 июля. В общей сложности, по нашим оценкам, сумма этих зачисток составила около 0,33 BTC. Средства были ещё раз перемещены на другие адреса, что отличает эту модель поведения от описанной выше.
Мы не видели сообщений о похищении средств с этих адресов. Теоретически этот особый пользователь мог законно перемещать свои средства из множества различных кошельков (см. дальнейший анализ), или же он всё-таки тоже является злоумышленником. Адреса, приведённые ниже, связаны между собой тем, что были отмечены в одной и той же транзакции, что указывает на то, что это один субъект или группа.
Адреса предполагаемого злоумышленника:
- bc1qdmpx2th8h7l4j0z93sxnrlpuaxfvkkfxlv7n2c (0.1382 BTC)
- bc1qpnq4q7dcgvpuz8z9dy3d3jp4vuumw0hte4d32n (0.0700 BTC)
- bc1qf9q85mt73sr0vzlqkvy75pyal3g5w2ca7zx3cv (0.0045 BTC)
- bc1q5rcm7gcl3n50q93xcwwz5una7xy89unlqhy075 (0.1147 BTC)
Вот список некоторых известных монет с подтверждёнными случаями воровства (до публикации данного расследования):
- Bitcoin (BTC)
- Ethereum (ETH)
- Ripple (XRP)
- Dogecoin (DOGE)
- Solana (SOL)
- Litecoin (LTC)
- Bitcoin Cash (BCH)
- Zcash (ZEC)
Вероятно, речь идет о гораздо большем количестве монет, поскольку дополнительные затраты на проведение данной атаки на другие монеты в затронутых кошельках ограничиваются временем на R&D, необходимым для идентификации и вывода средств. Мы надеемся, что есть шанс поймать злоумышленников за счёт отслеживания по конкретным монетам их идентификации и методов работы, но пока нам нечего сообщить по этому поводу.
В целом, по нашим оценкам, в рамках этого взлома было перемещено криптовалютных активов на сумму более 900 тыс. долларов США (по курсу 8/2023), хотя некоторые из пострадавших кошельков могли быть опустошены посредством других уязвимостей.
Поиск кошельков — мотивация и ограничения
Основная причина оперативного поиска пострадавших кошельков Bitcoin заключалась в оценке общего ущерба с точки зрения объема похищенных и оставшихся средств, а также в техническом подтверждении того, что уязвимость реальна и является единственным объяснением первоначальной кражи. У нас была надежда, что если мы обнаружим значительные остатки средств, то будет небольшой, но ненулевой шанс каким-то образом сообщить об этом законному владельцу, чтобы он смог спасти их. На этапе планирования мы рассматривали варианты передачи предупреждения владельцу кошелька через централизованную биржу, используемую для прямых депозитов, поиска владельцев кошельков с публичными адресами или обнаружения других каналов обратной связи. В крайнем случае, мы могли бы продлить запланированное время раскрытия информации на время поиска вариантов.
В конечном итоге, по состоянию на дату публикации расследования мы не обнаружили в анализируемых диапазонах сети Bitcoin существенных остатков средств, превышающих порог в $5000, связанных с кошельками, сгенерированными на версиях bx3.x
. Вполне возможно, что на аналогичных кошельках того или иного типа с несколько иными путями создания остаются и более крупные суммы средств, однако в ходе проведенного анализа мы их пока не обнаружили. Также возможно, что некоторые владельцы кошельков используют дополнительные пароли BIP39, которые обеспечивают умеренную или сильную защиту в зависимости от стойкости пароля и других факторов, что значительно затрудняет обнаружение.
Мы хотели бы внести ясность относительно наших действий в рамках расследования:
- Двум первоначально описанным жертвам удалось вернуть небольшую часть содержимого собственного кошелька, которую не успели украсть, используя свой обычный сетап кошелька, который был у них до кражи.
- Мы не перемещали никаких средств ни в одном из кошельков неизвестных жертв, ни одну монету.
- Мы не знакомы и никак не связаны со злоумышленником(-ами), похитившим эти средства.
В общем, никто из участников нашей группы не перемещал средства, законным владельцем которых он не является, и не знает личностей похитителей.
Насколько нам известно, даже при идеальных гипотетических обстоятельствах перемещение чужих средств во избежание их хищения злоумышленниками может обернуться юридическим кошмаром. Даже при самом идеальном сценарии — когда есть одна жертва, чёткие доказательства права собственности, хорошо установленные личности с обеих сторон, единая юрисдикция и надёжные каналы связи — это сопряжено с большим риском.
В нашей ситуации обстоятельства были существенно хуже, чем в идеальном случае, по большинству возможных критериев. Поэтому любой сценарий, связанный с перемещением чего-либо ценного, чем мы не владели до раскрытия информации, представлялся нам шквалом юридических проблем. (Помните: мы не юристы, и это не юридическая консультация; мы также не финансисты, поэтому это также не финансовая консультация).
Тем читателям, которые готовы пойти на авантюру и выступить в роли "белого рыцаря", предлагаем рассмотреть следующую дилемму: любой злоумышленник может вычислить закрытые ключи владельца, что сводит на нет ценность любых криптографических подписей с этими ключами. В любом сценарии, предусматривающем перевод средств владельца кошелька на другой кошелёк, который контролируете вы, как вы узнаете, что человек, появившийся в вашем директе (или на пороге вашего дома) с просьбой вернуть "свои" средства, является их законным владельцем? Особенно если нет централизованной структуры, такой как крупная биржа, которая бы поддержала это заявление, предоставив хотя бы какие-то доказательства?
Вот такая непростая ситуация! И это даже не затрагивает других проблем, таких как соблюдение законов о борьбе с отмыванием денег (AML), налоговой отчётности и множества других аспектов.
Если вы являетесь одним из пострадавших от кражи: нет, у нас точно нет ваших средств и мы не знаем, как их вернуть. Извините!
Если вас это утешит, мы приложили все усилия, чтобы дать нашим пострадавшим друзьям и всем остальным жертвам хотя бы какое-то объяснение и понимание того, почему вообще это оказалось возможно, и помочь им избежать повторных проблем из-за той же уязвимости.
Вы можете воспользоваться сервисом поиска, чтобы проверить, затронут ли ваш кошелёк.
Поиск кошельков – реализация
Обратите внимание, что мы намеренно не раскрываем некоторые нетривиальные технические детали, поскольку нам необходимо соблюдать этический компромисс между раскрытием технических подробностей, необходимых для освещения этой проблемы, и предоставлением мошенникам лишнего технического преимущества. Кроме того, несмотря на то, что мы являемся адептами открытого кода, мы не будем публиковать кастомный код, написанный нами для on-chain анализа, по аналогичной причине.
В рамках нашего расследования мы сосредоточились на стандартных форматах адресов BIP44, BIP49 и BIP84 и путях их деривации. Основное внимание мы уделили поиску как ранее использовавшихся, так и используемых сейчас кошельков Bitcoin, сгенерированных с помощью bx seed | bx mnemonic-new
на версиях bx
3.x
с обычными длинами и настройками мнемонических фраз BIP39.
В частности, речь идет о:
- 128 бит = 12 слов,
bx seed -b 128
- 192 бит = 18 слов,
bx seed -b 192
(по умолчанию) - 256 бит = 24 слова,
bx seed -b 256
Мы использовали общедоступный список всех биткойн-адресов, которые исторически были замечены в сети Bitcoin, и построили на этом наборе данных фильтр bloom с очень низким коэффициентом ложных срабатываний. Используя этот фильтр, мы смогли быстро прошерстить адреса, найти и отбросить множество неиспользуемых кошельков, соответствующие производные аккаунты которых никогда не были замечены в сети, не прибегая к затратному поиску на фулл-ноде Bitcoin.
Мы рассматривали только те кошельки, где был использован первый адрес. Стандарт предписывает сканировать первые 20 адресов, но вычисление адресов является узким местом в нашем поиске. Также мы учитывали только кошельки, использующие стандартные пути деривации, указанные в BIP44, BIP49 и BIP84. В общей сложности мы обнаружили более 2600 различных активно используемых криптовалютных кошельков Bitcoin, основанных на слабой энтропии bx seed
.
Большинство этих кошельков, группа из более чем 2550, имеют странно схожий паттерн использования: небольшие депозиты примерно в одни и те же даты в 2018 году. Мы считаем, что это результат использования автоматического инструмента bx
и что у этих кошельков может быть один и тот же владелец. Мы не уверены, в чем заключался тот эксперимент, однако все они находятся в диапазоне сид вывода 256-бит и имеют тип адреса BIP49 (префикс '3'), что позволяет немного отличить их от других адресов.
Исключив это большое количество особых кошельков, мы выявили менее 50 кошельков с более индивидуальным паттерном использования, который мы связываем с тем, что владельцы — реальные люди. Они распределены по указанным диапазонам и типам адресов. Мы знаем, что наше исследование неполное, поскольку мы не обнаружили всех кошельков, попавших под зачистку, которая наблюдалась на блокчейне.
В этом наборе кошельков нам удалось найти и идентифицировать оба кошелька первоначальной жертвы. Это даёт нам уверенность в том, что наше расследование причин кражи на верном пути.
На значительной части обнаруженных индивидуальных кошельков не было BTC до 2023 года, поэтому злоумышленники не могли вывести с них деньги. Однако мы по-прежнему считаем их пострадавшими по двум причинам:
- Любые новые депозиты на них подвергаются риску немедленного автоматического хищения (как описано в статье Ledger Donjon).
- Доступ к закрытым ключам кошельков позволяет восстановить все производные адреса на всех монетах, связав с ними предыдущие действия владельца кошелька, что существенно влияет на конфиденциальность.
Другие подтвержденные жертвы этой кражи
Через несколько дней после крупной кражи, произошедшей 12 июля 2023 г., на Reddit появилась информация от одного из пострадавших:
Пользователь Reddit u/0n0t0le представляет собой интересный пример, поскольку он потерял ~0,25 BTC, но смог переместить и сохранить более 1,05 BTC, которые злоумышленники на тот момент не нашли или не забрали.
В этом случае 1) мы смогли подтвердить, что пользователь хранил свои средства на уязвимом кошельке в диапазоне bx seed
.
Обратите внимание, что мнемонические секреты BIP39, как и другие закрытые ключи кошельков, обычно не содержат чётких указаний на программное обеспечение, с помощью которого они были сгенерированы. Поскольку формат предназначен для экспорта и импорта между различными программами для работы с кошельками, пользователи могут не совсем чётко или правильно помнить, где был создан тот или иной кошелёк. Это может привести к появлению большого количества путаной информации о другом потенциально затронутом ПО кошельков и затруднить поиск фактов.
С целью поддержания корректности мы не указываем другие наводки, по которым работаем, но можем обновить этот раздел позднее.
Основная хронология хищений и нашего расследования
Дата | Событие |
---|---|
17/11/2022 | Ledger Donjon раскрыл уязвимость Trust Wallet руководству Binance |
21/11/2022 | Патч к коду Trust Wallet на GitHub публично удаляет использование Mersenne Twister |
+21/11/2022 | Trust Wallet выборочно уведомляет об уязвимости затронутых пользователей |
?/12/2022 | Уязвимые кошельки Trust Wallet подвергаются атаке на чейне (по данным их команды) |
?/03/2023 | Уязвимые кошельки Trust Wallet снова подвергаются атаке на чейне (по данным их команды) |
22/04/2023 | Trust Wallet публично признаёт уязвимость в своих кошельках |
25/04/2023 | Ledger Donjon публикует отчёт об уязвимости кошелька Trust Wallet |
03/05/2023 | Первый потенциальный эксплойт кошельков bx 3.x |
12/07/2023 | Основной эксплойт кошельков bx |
21/07/2023 | Мы обнаруживаем уязвимость bx в ходе анализа инцидентов |
22/07/2023 | Мы отправляем первое письмо для установления связи с командой Libbitcoin |
25/07/2023 | Первый ответ команды Libbitcoin, в котором сообщается, что команда слишком занята для контактов |
25/07/2023 | Мы отправляем команде Libbitcoin контекстную информацию без подробностей об уязвимости с просьбой принять меры |
03/08/2023 | Мы направляем команде Libbitcoin техническую информацию об уязвимости и подробный контекст расследования |
03/08/2023 | Приходит ответ команды Libbitcoin, где указано, что они не считают это багом |
04/08/2023 | Мы запрашиваем у MITRE CVE для уязвимости bx seed в версиях 3.x |
05/08/2023 | Получен очередной ответ команды Libbitcoin, где говорится, что они не считают это ошибкой |
07/08/2023 | MITRE назначает CVE для проблемы bx 3.x |
08/08/2023 | Публикация этого поста |
Обратите внимание, что данная хронология сконцентрирована на основных событиях и не является исчерпывающей.
Ответ команды Libbitcoin и некоторый контекст
Во время нашей ускоренной координированной подготовки к раскрытию информации команда Libbitcoin сразу же оспорила релевантность наших выводов и присвоение CVE. Как мы поняли, они считают, что команда bx seed
никогда не должна продуктивно использоваться ни одним пользователем bx
, поскольку она достаточно задокументирована как не подходящая для безопасной генерации кошельков.
Мы не согласны с такой оценкой.
Просим вас обратить внимание на следующую временную шкалу и ссылки на ресурсы:
Дата | Информация |
---|---|
21/07/2013 | В инструмент-предшественник Libbitcoin Explorer добавлена команда newseed для генерации энтропии |
16/10/2014 | Создана первая вики-страница документации Libbitcoin Explorer для bx seed |
14/12/2014 | Первый релиз Libbitcoin Explorer (bx), начиная с версии 2.0.0 |
21/12/2015 | Релиз Libbitcoin Explorer (bx) 2.2.0 |
10/02/2017 | Релиз Libbitcoin Explorer (bx) 2.3.0 |
19/01/2015 | Член команды Libbitcoin добавляет и обновляет предложения по использованию bx seed в книге "Mastering Bitcoin" (описание ниже) |
21/10/2016 | Команда Libbitcoin изменила генерацию seed на Mersenne Twister с PR#559, коммит |
08/03/2017 | Libbitcoin Explorer (bx) 3.0.0, включает PR#559 |
29/08/2019 | Libbitcoin Explorer (bx) 3.6.0, последний официальный релиз на сегодняшний день |
02/05/2021 | В ветке GitHub Команда bx seed переименована в bx entropy , по-прежнему основана на Mersenne Twister, PR#628, 1, 2 |
Нам известно лишь об одном предупреждении на странице документации bx seed
в вики:
ПРЕДУПРЕЖДЕНИЕ: Псевдослучайный сидинг может внести в ваши ключи криптографическую слабость. Эта команда предоставляется для удобства.
Формулировка "может внести" довольно слабая, и пользователь вполне может не знать, что при этом получается сид, который совершенно небезопасен и не должен использоваться для хранения чего-либо ценного.
При добавлении в приложение к книге "Mastering Bitcoin" рабочих процессов, связанных с bx seed
, члены команды Libbitcoin описали их следующим образом:
Сгенерируйте случайное значение "seed" с помощью команды seed, которая использует генератор случайных чисел операционной системы. Передайте seed команде
ec-new
[...]
$ bx seed | bx ec-new > private_key [...]
Аналогично, в главе 4 "Mastering Bitcoin":
Вы также можете использовать инструмент командной строки Bitcoin Explorer (см. [appdx_bx]) для генерации и отображения закрытых ключей с помощью команд
seed
,ec-new
иec-to-wif
:
$ bx seed | bx ec-new | bx ec-to-wif [...]
Ни в главе 4, ни в приложении нет предупреждения о том, что bx seed
не производит безопасных случайных чисел. Примеры не предупреждают пользователя о том, что созданные таким образом кошельки небезопасны.
Мы сообщили об этом авторам книги "Mastering Bitcoin", и они намерены переработать данный текст.
Следующая документация Libbitcoin включает bx seed
:
Страница | Отрывок команды | Последнее изменение |
---|---|---|
wiki landing page | bx seed bx ec-new bx ec-to-public bx ec-to-address | 7/2018 |
bx mnemonic-new documentation | bx seed -b 128 bx mnemonic-new | 4/2017 |
bx hd-new documentation | bx seed bx hd-new | 4/2022 |
Random Numbers | bx seed -b 256 | 7/2018 |
Все эти примеры не содержат никаких предупреждений о том, что созданные кошельки небезопасны.
Другие примечательные особенности:
- Параметр
bx seed
-b
не может быть настроен на вывод размера менее 128 бит в двоичном виде. В связанных с этим ограничением комментариях к коду есть “Минимальная безопасная длина сида в битах” и “Это мягкие требования к безопасности и рациональности”. Довольно странно, что конструкция явно не позволяет пользователю создать слишком короткий сид, но не мешает ему создать сид с недостаточной случайностью.
Общие замечания:
- Даты релизов и коммитов взяты из временных меток на Git/GitHub. В некоторых случаях они могут отличаться от реальных дат.
Предполагаемые проблемы с RNG в старых версиях bx
В основной части нашего быстрого и насыщенного расследования мы сосредоточились на проблемах, связанных с Mersenne Twister, в версиях bx
, выпущенных после марта 2017 года.
Однако недавно мы наблюдали некоторые моменты в старых версиях bx
(до версии 3.0.0
), которые указывают на другое слабое поведение генератора случайных чисел bx seed
, частично зависящее от системной среды, где выполняется bx
. В частности, источник энтропии std::random_device
в сочетании с std::default_random_engine
может вести себя недостаточно безопасно, если случайный механизм использует недостаточный сидинг и работает как не криптостойкий ГПСЧ, подобный Mersenne Twister.
Tool | Версия | Релиз | Статус | Детали |
---|---|---|---|---|
sx | 1.x ? | 2014 | 🔍 вероятное затронут (в некоторых системах) | std::random_device + std::default_random_engine |
bx | 2.0.0 - 2.1.0 | 2014 - 2015 | 🔍 вероятное затронут (в некоторых системах) | std::random_device + std::default_random_engine |
bx | 2.2.0 - 2.3.0 | 2015 - 2017 | ❔ неясное, но улучшенное поведение | std::random_device + std::uniform_int_distribution |
bx | 3.0.0 - 3.6.0 | 2017 - сейчас | 🔥 подтвержденная возможность эксплойта | get_clock_seed() + std::mt19937 Mersenne Twister |
Пожалуйста, рассматривайте это как предварительное указание на возможные проблемы. Вероятно, что в некоторых из публичных краж уже использовалась уязвимость генератора случайных чисел в версиях до bx 3.0.0
, но пока мы этого не подтвердили.
Мы планируем провести дополнительные исследования.
Часть III - Итоги и перспективы
Основные уроки
- Используйте для своих кошельков фразы-пароли BIP39, в идеале — сложные пароли, основанные на энтропии из отдельного источника.
- Доверяйте генерацию кошельков только тщательно проверенному ПО.
- Документируйте каждый сетап при генерации кошелька, это может оказаться очень важно для вас в будущем.
Краткий пересказ
В этом посте мы предоставили техническую информацию о слабой функции генерации энтропии в Libbitcoin Explorer, подтвердили практическое использование слабой функции для создания более чем 2600 криптовалютных кошельков в основной сети Bitcoin и логически связали её с недавним крупным хищением криптовалюты на нескольких популярных блокчейнах, ущерб от которого оценивается в 900 000 долларов. Кроме того, мы описали сходство данной уязвимости с другой активно эксплуатированной уязвимостью в Trust Wallet, а также привели некоторые сведения о контексте Libbitcoin Explorer и общей хронологии событий.
Предстоящая работа
- Мы планируем продолжить исследования безопасности поведения ГПСЧ в версиях bx 2.x.
- Мы можем обновить эту страницу в ближайшее время по мере поступления информации.
Дополнительные ссылки
- Ошибка безопасности — использование твистера Мерсенна MT19937 в криптографической библиотеке Intel
Коммерческая деятельность
Мы не получили никакого вознаграждения за данное расследование и не принимаем пожертвований.
Если вам понравилась наша работа, ознакомьтесь со следующими коммерческими услугами, предлагаемыми различными членами команды и организациями:
- Инфосек фирма, специализирующаяся на работе с высокорисковыми клиентами
- Пен-тестинг, моделирование угроз, практическое проектирование систем безопасности
- Оценка безопасности всего стека и заключение договоров на оказание консультационных услуг
- Состав: Shane Engelman, Anton Livaja, Ryan Heywood и Lance Vick
- Фриланс-консультант по вопросам информационной безопасности
- Пен-тестинг, аудит кода, исследование безопасности, фаззинг
- Фокус на OpenPGP: OpenPGP CA, Sequoia PGP, OpenPGP на HSM-устройствах (OpenPGP-карты, PKCS #11, PIV)
Прочие примечания
- Включенные фрагменты кода Libbitcoin лицензируются под AGPLv3.
- Для других фрагментов кода см. прилагаемое уведомление об авторских правах.
Основная команда
Distrust
- Anton Livaja - [email protected]
- Lance R. Vick - [email protected], https://lance.dev
- Ryan Heywood - [email protected], https://ryansquared.pub
- Shane Engelman - [email protected]
Независимые консультанты
- Christian Reitter - https://inhq.net
- Daniel Grove - [email protected]
- Dustin Johnson - [email protected]
- Heiko Schaefer - [email protected]
- James Callahan - [email protected]
- Jochen Hoenicke - https://jhoenicke.de
- John Naulty - [email protected]
- Matthew Brooks - *@logicwax.com
Особые благодарности
- Jack Kearney - Turnkey
- Несколько доверенных консультантов, пожелавших остаться неизвестными. Вы знаете, кто вы.
@rudex, почти детективная история...
Сам для генерации seed-фразы использую простой скрипт на основе Mnemonic от Trezor:
Это для seed-фразы из 24 слов. Если нужно 12 слов - strength=128
Чтобы все работало необходимо: