Vulnerabilidad en el monedero físico Coldcard lleva a robo de más de $88 millones en bitcoin

iconMetaEra
Compartir
AI summary iconResumen
Una vulnerabilidad en el monedero hardware Coldcard relacionada con un RNG mal configurado ha llevado al robo de más de 594 BTC, valorados en más de $88 millones. El problema afectó a los modelos Coldcard Mk2, Mk3, Mk4, Q y Mk5, exponiendo las claves privadas a ataques de fuerza bruta. Beosin ha rastreado los fondos acumulados hacia varias direcciones de Bitcoin. El incidente plantea preocupaciones bajo CFT y resalta la urgencia de cumplir con MiCA mientras la UE endurece las regulaciones de cripto.

Pérdida de más de 88 millones de dólares: Análisis de la vulnerabilidad del billetera hardware Coldcard y rastreo de los fondos robados El 31 de julio, se robaron un total de 594 bitcoins de aproximadamente 500 billeteras hardware Coldcard, valorados en unos 38 millones de dólares. Posteriormente, Coinkite, la empresa responsable de la producción de las billeteras Coldcard, confirmó que existía una vulnerabilidad de seguridad en el proceso de generación de claves, afectando múltiples generaciones de productos, incluyendo Coldcard Mk2, Mk3, Mk4, Q y Mk5.

Actualmente, el monto perdido debido a este ataque de vulnerabilidad ha superado los 88 millones de dólares, y el ataque sigue en curso. Los usuarios de billeteras Coldcard deben transferir sus fondos a otras direcciones lo antes posible. A continuación se presenta el análisis de Beosin sobre esta vulnerabilidad y el seguimiento de los fondos robados.

I. Análisis de la vulnerabilidad

Al analizar los registros de confirmación del firmware de Coldcard, se puede observar que en la confirmación anterior 37e4af5451c260c1e7d429fe8972c4cb5e68ee59, el equipo de desarrollo actualizó varios códigos relacionados con la configuración de MK4, que incluyen:

// Tenemos nuestra propia versión de este código.#define MICROPY_HW_ENABLE_RNG       (0)

En la plataforma MicroPython STM32, esta macro controla la ruta de compilación para el generador de números aleatorios hardware predeterminado (RNG) y la implementación general de números aleatorios. Establecerla en 0 hace que la ruta del RNG hardware predeterminado no se utilice como backend para rng_get().

Su nota indica que el desarrollador implementará el RNG; al revisar el rng.h personalizado, se descubre que solo se declaran dos objetos MicroPython:

MP_DECLARE_CONST_FUN_OBJ_0(pyb_rng_get_obj);MP_DECLARE_CONST_FUN_OBJ_1(pyb_rng_get_bytes_obj);

La implementación correspondiente es:

/// \function pyb_rng_get()///// Devuelve un número aleatorio generado por hardware de 30 bits: ¡o falla!//STATIC mp_obj_t pyb_rng_get(void){    // Obtener y devolver el nuevo número aleatorio    return mp_obj_new_int(rng_get_or_fault() >> 2);}
/// \function rng_get_bytes()/// Llena un búfer con bits aleatorios; el llamador debe proporcionar un búfer de tamaño adecuado.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 < 1) {        mp_raise_ValueError(NULL);    }
    // Leer palabras de 32 bits y desempaquetarlas en el búfer proporcionado    random_buffer(bufinfo.buf, count);
    return mp_const_none;}
MP_DEFINE_CONST_FUN_OBJ_0(pyb_rng_get_obj, pyb_rng_get);MP_DEFINE_CONST_FUN_OBJ_1(pyb_rng_get_bytes_obj, pyb_rng_get_bytes);

rng_get_or_fault() lee directamente el periférico RNG de STM32:

static uint32_t rng_get_or_fault(void){    // Habilitar el periférico RNG si aún no está habilitado    rng_init();
    // Esperar a que esté disponible un nuevo número aleatorio, tarda aproximadamente 10 us    uint32_t start = HAL_GetTick();
    while (!(RNG->SR & RNG_SR_DRDY)) {        if (HAL_GetTick() - start >= RNG_TIMEOUT_MS) {            // fallo de hardware... ¡no devolver nada!            mp_raise_OSError(MP_EFAULT);        }    }
    // Obtener y devolver el nuevo número aleatorio    last_value = RNG->DR;
    return last_value;}

Esto indica que el código personalizado de Coldcard realmente desea utilizar el RNG de hardware, pero solo garantiza el uso de esta función de hardware al llamar a pyb_rng_get* o su internal random_buffer().

Y durante la creación del monedero, se llama efectivamente al siguiente código, donde la función de creación de monedero en shared/seed.py es:

async def make_new_wallet(nwords):    # Elegir una nueva semilla aleatoria.    await ux_dramatic_pause('Generando...', 3)    seed = generate_seed()    words = await approve_word_list(seed, nwords)    if words:        await commit_new_words(words)

Esta llamada entra primero en el módulo shared/random.py de Coldcard. En versiones anteriores, random.py dependía explícitamente de ngu.random y conservaba:

# random.py - subconjunto del módulo random, sin compatibilidad y utilizando RNG de calidad criptográfica  
# para bytes, use ngu.random.byte(len)  
# bytes = ngu.random.bytes

El proceso de inicialización de la billetera utiliza random.bytes, no pyb.rng(); la función pyb_rng_get_obj personalizada no reemplaza automáticamente random.bytes.

Dado que MICROPY_HW_ENABLE_RNG está configurado como 0, al generar la billetera no se utilizó el RNG de hardware, sino que se llamó a pyb_rng_yasmarang en micropython/ports/stm32/rng.c:

#if MICROPY_HW_ENABLE_RNG
uint32_t rng_get(void) {    // usar el generador de números aleatorios hardware de STM32    ...}
#else
// Para MCU que no tienen un RNG, aún necesitamos proporcionar una función rng_get()// Un generador pseudoaleatorio no es realmente ideal, pero lo usamos por ahora.
// Generador de números aleatorios Yasmarangstatic 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

Y pyb_rng_yasmarang es un generador de números pseudoaleatorios, que es extremadamente inseguro para la generación de semillas de billeteras hardware, ya que los atacantes pueden obtener las claves mediante fuerza bruta. Actualmente, Coinkite ha excluido explícitamente stm32/rng.c en el archivo makefile:

# No compilar el PRNG de respaldo de MicroPython. El archivo rng.c específico de la placa
# proporciona rng_get(), y este objeto vacío satisface la lista de objetos upstream.
$(BUILD)/rng.o: CFLAGS += -Dpyb_rng_yasmarang=error-do-not-want-this
$(BUILD)/rng.o:
$(ECHO) "SKIP stm32/rng.c"
$(Q)$(CC) $(CFLAGS) -x c -c /dev/null -o $@

II. Rastreo de fondos robados

Actualmente, los fondos de varias carteras de víctimas han sido transferidos y reunidos en múltiples direcciones, sin haberse realizado aún una limpieza adicional. Beosin Trace, mediante inteligencia de amenazas y análisis de comportamiento en la cadena, ha monitoreado las siguientes direcciones de reunión:

bc1qq85v2c926eg6pgxhwp6q7lf6cnsz80qs3fcu9r (562 BTC)

https://wdcdn.qpic.cn/MTMxMDI3MDE1MTgxMDU0NzA_369595_usmImxZpHsKmu9X__1785899827?w=1080&h=656

bc1qx76cae2706qd5q576feh7xq8rfcsjpf2htfhe3 (398.47 BTC)

https://wdcdn.qpic.cn/MTMxMDI3MDE1MTgxMDU0NzA_304781_-IeWjFtIQ4RhvCbz_1785899827?w=1080&h=674

Además, existen las siguientes direcciones de agrupación, cuyos flujos de fondos son similares a los de la imagen anterior y por el momento no han habido transferencias adicionales:

  • bc1q8jy96fe5lf8vfugydnte3cguk92gpev7kwtp3q (89.62 BTC)
  • bc1q0rvn88w08j75k4h48lf9fvhan7unjp7vjf5q6m (64.9 BTC)
  • bc1qtfrwa4j6rmj9rsgspv6a0yjumkg39js2numu75 (45,9 BTC)
  • bc1qmd5m5ktv7m5ffujxv4248fxv36myvdx79n8jp6 (30.18 BTC)

Los ataques contra la billetera Coldcard aún están en curso, y el equipo de Beosin continúa monitoreando más direcciones de agrupación y analizando los flujos de fondos relacionados.

Tres, conclusión

Este importante incidente de seguridad en la billetera hardware Coldcard se debió a un error en la implementación del generador de números aleatorios por parte del equipo de desarrollo, que utilizó un generador de números pseudoaleatorios en el proceso crítico de generación de la semilla de la billetera. El equipo de desarrollo debe realizar pruebas y auditorías continuas y exhaustivas del código, y los usuarios de la billetera Coldcard deben transferir sus activos lo antes posible y mantenerse atentos a los siguientes anuncios de seguridad de Coinkite.

Beosin es una empresa líder en tecnología de seguridad blockchain y cumplimiento normativo, enfocada en auditorías de seguridad de contratos inteligentes antes del lanzamiento de proyectos, monitoreo y bloqueo de riesgos de seguridad durante la operación del proyecto, recuperación de activos robados, lucha contra el lavado de dinero (AML) para activos virtuales, e investigación y rastreo. Beosin ha proporcionado productos y servicios de cumplimiento blockchain "todo en uno" a más de 200 proveedores de activos virtuales y 4.500 proyectos Web3 en más de 20 países y regiones del mundo.

Descargo de responsabilidad: La información contenida en esta página puede proceder de terceros y no refleja necesariamente los puntos de vista u opiniones de KuCoin. Este contenido se proporciona solo con fines informativos generales, sin ninguna representación o garantía de ningún tipo, y tampoco debe interpretarse como asesoramiento financiero o de inversión. KuCoin no es responsable de ningún error u omisión, ni de ningún resultado derivado del uso de esta información. Las inversiones en activos digitales pueden ser arriesgadas. Evalúa con cuidado los riesgos de un producto y tu tolerancia al riesgo en función de tus propias circunstancias financieras. Para más información, consulta nuestras Condiciones de uso y la Declaración de riesgos.