Уязвимость аппаратных кошельков Coldcard привела к краже биткоинов более чем на $88 млн

Сводка рынка от ИИ
Сообщается, что выявленный дефект генерации ключей в аппаратном кошельке Coldcard позволил злоумышленникам похитить более $88M в BTC; эксплуатация уязвимости описывается как продолжающаяся, а средства агрегируются в блокчейне. Хотя это не является проблемой Bitcoin на уровне протокола, инцидент может оказывать давление на краткосрочные настроения, повышая риски хранения и операционные риски, потенциально провоцируя ускоренную миграцию к самостоятельному хранению, усиление внимания к цепочкам поставок аппаратных кошельков и более активный мониторинг связанных адресов биржами и командами по комплаенсу.
Степень влияния
● Высокая
Затронутые активы
BTC/USDT+0.92%
Инсайт ИИ · BTC/USDTИнсайт ИИ
▼ Медвежий
Торговать
⚠️ Инсайты, сгенерированные ИИ, основаны на новостном контенте и предоставляются исключительно в информационных целях. Они не являются инвестиционной рекомендацией и не отражают позицию BingX. Торговля сопряжена с риском. Пожалуйста, торгуйте ответственно.
Общий ущерб превысил $88 млн: разбор уязвимости Coldcard и мониторинг похищенных средств. 31 июля были скомпрометированы около 500 аппаратных кошельков Coldcard. По оценке, злоумышленники похитили 594 BTC на сумму порядка $38 млн. Позже Coinkite, производитель Coldcard, подтвердила наличие уязвимости в процессе генерации ключей, затрагивающей несколько поколений устройств: Coldcard Mk2, Mk3, Mk4, Q и Mk5. Совокупные потери от эксплуатации уязвимости уже превысили $88 млн, атака продолжается. Пользователям Coldcard рекомендуется как можно быстрее перевести средства на новый адрес. Ниже приведены выводы Beosin по анализу уязвимости и отслеживанию украденных средств. I. Анализ уязвимости Изучение истории коммитов прошивки Coldcard показывает, что в коммите 37e4af5451c260c1e7d429fe8972c4cb5e68ee59 команда разработки внесла изменения в участки кода, связанные с конфигурацией MK4. В частности, в mpconfigboard.h было установлено: // We have our own version of this code. #define MICROPY_HW_ENABLE_RNG (0) В MicroPython для STM32 этот макрос определяет путь компиляции для стандартной привязки аппаратного генератора случайных чисел (RNG) и общей реализации random. Значение 0 отключает использование стандартного аппаратного RNG как бэкенда для generic rng_get(). По смыслу комментариев разработчик должен реализовать RNG самостоятельно. В пользовательском файле rng.h объявлены лишь два объекта MicroPython: MP_DECLARE_CONST_FUN_OBJ_0(pyb_rng_get_obj); MP_DECLARE_CONST_FUN_OBJ_1(pyb_rng_get_bytes_obj); Реализация выглядит так: /// \function pyb_rng_get() ///// Returns a 30bit hardwaregenerated random number, or fails! //STATIC mp_obj_t pyb_rng_get(void){ // Retrieve and return the new random number return mp_obj_new_int(rng_get_or_fault() >> 2); } /// \function rng_get_bytes() /// Fills a buffer with random bits; the caller must provide a buffer of appropriate size. STATIC mp_obj_t pyb_rng_get_bytes(mp_obj_t buffer_io) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(buffer_io, &bufinfo, MP_BUFFER_WRITE); mp_uint_t count = bufinfo.len; if(count SR & RNG_SR_DRDY)) { if (HAL_GetTick() start >= RNG_TIMEOUT_MS) { // Hardware failure... do not return anything! mp_raise_OSError(MP_EFAULT); } } // Retrieve and return the new random number last_value = RNG>DR; return last_value; } Это указывает на то, что пользовательский код Coldcard действительно нацелен на использование аппаратного RNG, но гарантирует его применение только при вызовах pyb_rng_get* или внутренней random_buffer(). При создании кошелька фактически вызывается другой путь. Функция инициализации в shared/seed.py: async def make_new_wallet(nwords): # Select a new random seed. await ux_dramatic_pause('Generating...', 3) seed = generate_seed() words = await approve_word_list(seed, nwords) if words: await commit_new_words(words) Далее управление переходит в shared/random.py. В прежних версиях random.py явно зависел от ngu.random и содержал: # random.py subset of the random module, with no compatibility, using cryptographically secure RNG # for bytes, use ngu.random.bytes(len) # bytes = ngu.random.bytes Инициализация кошелька использует random.bytes, а не pyb.rng(); при этом пользовательский pyb_rng_get_obj не переопределяет random.bytes автоматически. На фоне MICROPY_HW_ENABLE_RNG = 0 генерация сид-фразы не использовала аппаратный RNG и вместо этого обращалась к pyb_rng_yasmarang из micropython/ports/stm32/rng.c: #if MICROPY_HW_ENABLE_RNG uint32_t rng_get(void) { // Use STM32 hardware RNG ... } #else // For MCUs without an RNG, we still need to provide an rng_get() function. // A pseudoRNG is not ideal, but we use it for now. // Yasmarang random number generator static uint32_t pyb_rng_yasmarang(void) { static bool seeded = false; static uint32_t pad = 0, n = 0; ... } uint32_t rng_get(void) { return pyb_rng_yasmarang(); } #endif pyb_rng_yasmarang — псевдослучайный генератор, крайне непригодный для создания сидов аппаратного кошелька: злоумышленник может перебором восстановить ключ. Coinkite также указала, что теперь явно исключает stm32/rng.c из сборки через Makefile: Do not compile MicroPython's fallback PRNG. The boardspecific rng.c provides rng_get(), and this empty object satisfies the upstream object list. $(BUILD)/rng.o: CFLAGS += Dpyb_rng_yasmarang=errordonotwantthis $(BUILD)/rng.o: $(ECHO) "SKIP stm32/rng.c" $(Q)$(CC) $(CFLAGS) x c c /dev/null o $@ II. Отслеживание похищенных средств Средства с кошельков нескольких пострадавших уже были переведены и агрегированы в нескольких адресах, при этом признаков дальнейшего "отмывания" на момент анализа не наблюдается. На основе threat intelligence и анализа ончейн-поведения Beosin Trace выявил следующие адреса-агрегаторы: bc1qq85v2c926eg6pgxhwp6q7lf6cnsz80qs3fcu9r (562 BTC) bc1qx76cae2706qd5q576feh7xq8rfcsjpf2htfhe3 (398.47 BTC) Кроме того, у следующих адресов отмечен сходный сценарий поступления средств; дальнейших переводов пока не зафиксировано: bc1q8jy96fe5lf8vfugydnte3cguk92gpev7kwtp3q (89.62 BTC) bc1q0rvn88w08j75k4h48lf9fvhan7unjp7vjf5q6m (64.9 BTC) bc1qtfrwa4j6rmj9rsgspv6a0yjumkg39js2numu75 (45.9 BTC) bc1qmd5m5ktv7m5ffujxv4248fxv36myvdx79n8jp6 (30.18 BTC) Атаки на пользователей Coldcard продолжаются. Команда Beosin ведет постоянный мониторинг новых адресов-агрегаторов и анализирует связанные потоки средств. III. Итоги Крупный инцидент безопасности вокруг аппаратных кошельков Coldcard связан с ошибкой реализации: при критически важной процедуре генерации сид-фразы использовался псевдослучайный генератор. Разработчикам необходимы регулярные комплексные тесты и аудит кода. Пользователям Coldcard следует оперативно перевести активы и внимательно отслеживать дальнейшие сообщения Coinkite по безопасности. Beosin — компания в сфере безопасности блокчейна и технологий регуляторного комплаенса, специализирующаяся на предрелизных аудитах смарт-контрактов, мониторинге и блокировке рисков в реальном времени, возврате активов, AML для виртуальных активов и расследовательском трейсинге. Beosin предоставляет "one-stop" продукты и услуги по комплаенсу и безопасности регуляторам и правоохранительным органам более чем в 20 странах и регионах, свыше 200 провайдерам услуг с виртуальными активами, а также 4"500+ Web3-проектам.