Logotipo de Zephyrnet

Los fondos de cada billetera creada con la extensión del navegador Trust Wallet podrían haber sido robados sin ninguna interacción del usuario | Libro mayor

Fecha:

Cosas que saber:
– La generación de semillas de Trust Wallet fue defectuosa, la entropía total fue de solo 32 bits. Hemos creado un archivo que contiene todas las semillas posibles.

– Afortunadamente, Ledger Donjon descubrió la vulnerabilidad muy rápidamente y probablemente evitó uno de los mayores ataques en el ecosistema criptográfico.

El 14 de noviembre de 2022, Trust Wallet, una billetera de software ampliamente utilizada, anunció el lanzamiento de su extensión para navegador. Permite el acceso a activos digitales en varias cadenas de bloques directamente desde el navegador y es una adición muy esperada a las aplicaciones existentes de iOS y Android.

The Ledger Donjon descubrió recientemente una vulnerabilidad crítica en esta extensión del navegador, que permite a un atacante robar todos los activos de cualquier billetera creada con esta extensión, sin ninguna interacción del usuario. Al conocer la dirección de una cuenta, es posible calcular inmediatamente su clave privada y luego acceder a todos sus fondos. A continuación, se incluyen detalles de la vulnerabilidad, cómo la descubrió Ledger Donjon, su impacto a lo largo del tiempo, una estimación de los activos vulnerables y cómo respondió Trust Wallet para solucionarla. Pero empecemos por recordar lo básico.

Cómo se crean las billeteras

La generación de entropía es complicada. Como científicos, nos gusta la reproducibilidad y poder explicar fenómenos con principios de causa y efecto. Entonces, en términos generales, es difícil generar aleatoriedad. Además, es difícil demostrar que los números aleatorios son correctos, y un generador de números aleatorios malo pero no defectuoso puede engañar fácilmente al observador. Para una buena aleatoriedad, necesitamos una distribución uniforme de bits y bytes (e incluso el tamaño de todos los fragmentos) e imprevisibilidad. Para un observador de una secuencia, debe ser imposible tener información sobre la siguiente parte de la secuencia que se generará.

Como estas propiedades son increíblemente difíciles de lograr, el espacio de las criptomonedas trata de evitar confiar en la aleatoriedad tanto como sea posible, pero aún la necesitamos en una etapa: cuando creamos una nueva billetera.

Probablemente ya esté familiarizado con su mnemotécnico, las 12 a 24 palabras en inglés que le permiten hacer una copia de seguridad de su billetera (si no, puede verificar Academia de contabilidad artículo sobre este mismo tema).

Este nemotécnico codifica de 16 a 32 bytes de entropía, según el Norma BIP 39 – la calidad de esta entropía es crítica, ya que será la semilla de todas las claves utilizadas por su billetera en todas las cadenas, siguiendo un proceso de derivación determinista definido por el BIP 32 y BIP 44 normas

Este esquema determinista jerárquico es bastante omnipresente hoy en día, considerando lo fácil que les resulta a los usuarios crear una copia de seguridad de una infinidad de claves y su portabilidad (a pesar de que BIP 39 está "desaconsejado unánimemente para su implementación"). El roaming de firmantes es una característica poderosa: cuando su billetera favorita falla o decepciona, puede simplemente llevar su mnemónico (o incluso mejor, su dispositivo Ledger), cambiar a otro, mantener su libertad financiera y limitar cualquier impacto de su tiempo de inactividad.

Pero, de nuevo, requiere una fuente de entropía impecable.

Descripción general de la vulnerabilidad

Trust Wallet se basa en Núcleo de la billetera de confianza, una biblioteca multiplataforma que implementa la funcionalidad de billetera criptográfica de bajo nivel para muchas cadenas de bloques. Se centró en dispositivos móviles, pero también apunta a Wasm desde abril de 2022 (ver #2132).

Si bien la mayor parte de Trust Wallet Core es portátil, algunos módulos y funciones son muy específicos para un objetivo. Este es especialmente el caso de la parte de generación aleatoria segura, utilizada para crear material criptográfico como claves privadas y mnemotécnicos para billeteras HD. Cada implementación aprovecha el generador de números pseudoaleatorios (PRNG) que ofrece el sistema operativo:

  • Para iOS, SecRandomCopyBytes se utiliza.
  • Para Android, la entropía la proporciona una instancia de java.security.SecureRandom.

Esta suele ser una buena práctica, ya que se supone que estas primitivas son seguras.

backend de Wasm

Hay una diferencia con el objetivo Wasm. Este módulo puede ejecutarse en varios entornos, como cualquier navegador compatible con Wasm o Node.js. Estas plataformas no proporcionan un PRNG fuerte común y no se puede acceder a las interfaces de sistema "clásicas" desde estos entornos. Por ejemplo, un módulo Wasm que se ejecuta en Chrome para Linux no puede leer directamente /dev/urandom.

Para abordar esto, se ha implementado un llamado "generador aleatorio seguro" dedicado en #2240. Se basa en un PR realizado en emscripten (ver PR #12240 in emscripten) escrito precisamente para evitar la lectura /dev/urandom.

Según el autor:

Lo que hacemos aquí es simple, envolvemos std::random_device   std::mt19937 y devolver un valor uint32 aleatorio, inspirado en emscripten-core/emscripten#12240.

Aquí hay un problema importante, que conduce a una vulnerabilidad crítica para el núcleo de la billetera para Wasm y para cualquier producto que dependa de él: el PRNG utilizado es un Mersenne Twister y no debe usarse con fines criptográficos. Además, la versión especializada mt19937 toma un único valor de 32 bits como semilla de entrada.

¿Cuáles son las consecuencias aquí? El módulo aleatorio personalizado para Wasm implementa dos funciones: random32 que genera un valor aleatorio de 32 bits, y random_buffer que llena un búfer de tamaño arbitrario con datos aleatorios. En el proyecto Wallet Core, estas funciones son utilizadas exclusivamente por trezor-crypto, la biblioteca criptográfica desarrollada por Trezor para garantizar una criptografía segura en sus billeteras de hardware.

Ahora, veamos cómo se generan las billeteras HD:

  • El punto de entrada es HDWallet. Se necesita una fuerza y ​​una frase de contraseña para protegerlo más tarde:

https://github.com/trustwallet/wallet-core/blob/3.1.0/src/HDWallet.cpp#L45

Esta función luego llama mnemonic_generate para crear un mnemotécnico BIP-39:

https://github.com/trustwallet/wallet-core/blob/3.1.0/trezor-crypto/crypto/bip39.c#L55

mnemonic_generate llamadas random_buffer, que genera un búfer aleatorio que se llena con un Mersenne twister PRNG, cuya instancia se acaba de sembrar:

https://github.com/trustwallet/wallet-core/blob/3.1.0/wasm/src/Random.cpp#L19

Como la semilla tiene solo 32 bits, la versión Wasm de wallet-core permite crear solo 2 ^ 32 (~ 4 mil millones) de mnemónicos posibles. Todos estos mnemotécnicos se pueden generar en un par de horas en una sola computadora.

A partir de ahí, un atacante puede:

  • Calcule todas las semillas, claves privadas y luego direcciones de cada criptomoneda manejada por Trust Wallet.
  • Escanee las cadenas de bloques relacionadas para extraer todas las direcciones utilizadas.
  • Calcule la intersección para obtener todas las direcciones de billeteras creadas por Trust Wallet para Wasm y robar sus fondos.

Ejecutar dicho ataque lleva mucho más que un par de horas, pero es factible con unas pocas GPU en menos de un día (ver medium.com/@johncantrell97/how-i-checked-over-1-thillion-mnemonics-in-30-hours-to-win-a-bitcoin para una estimación de costos. El ataque es 256 veces más fácil aquí).

Aplicación para la extensión del navegador Trust Wallet

El  Extensión del navegador Trust Wallet es una extensión para navegadores basados ​​en Chromium. Es claramente un competidor de MetaMask, y está calificado como una "billetera criptográfica segura de múltiples cadenas y puerta de entrada a miles de aplicaciones descentralizadas Web3 (dApps)".

La extensión es de código cerrado, pero su código se puede analizar fácilmente. Se basa en la implementación vulnerable de Wasm de Trust Wallet Core.

Cuando se crea una billetera, la extensión crea un mnemotécnico de 12 palabras a partir de una semilla aleatoria de 128 bits. Mnemonic se genera de esta manera:

HDWallet.create es el envoltorio Wasm generado automáticamente para el constructor HDWallet descrito anteriormente. Eso significa que los vulnerables random_buffer se utiliza la función, por lo que los mnemotécnicos se pueden recuperar de la dirección del usuario con un ataque de fuerza bruta.

Esta extensión maneja los siguientes activos: AVAX, BNB, ETH, MATIC, SOL y TWT.

  • Las direcciones son idénticas para ETH, BNB, MATIC, AVAX y TWT. Estas son direcciones estándar de Ethereum, que comparten la misma ruta de derivación (m/44'/60'/0'/0/0).
  • Solana usa una ruta de derivación diferente: m/44'/501'/0'/0'.

Para drenar los fondos de todos los usuarios de la extensión Trust Wallet, el atacante puede:

  • Calcule y almacene todos los mnemotécnicos posibles, luego la clave privada de Ethereum y la dirección de Ethereum, que puede generar esta extensión.
  • Reúna todas las direcciones de Ethereum usadas creadas desde el primer lanzamiento de la extensión del navegador Trust Wallet y guárdelas localmente.
  • Realice una búsqueda en la base de datos de direcciones.
  • Cartera vacía con la clave privada, si se ha utilizado la dirección.

Estos pasos se pueden reproducir para cada cadena. Detallamos ahora cómo Ledger Donjon implementó este ataque en Ethereum y Binance Smart Chain, sin, por supuesto, vaciar las billeteras.

Atacando la billetera de confianza

La vulnerabilidad permite que un atacante calcule mnemónicos desde cualquier dirección de una billetera creada por la extensión del navegador. Para eso, uno necesita calcular un mapeo entre los posibles mnemotécnicos y la dirección resultante.

Generar todas las direcciones que puede crear la extensión Trust Wallet

Según la vulnerabilidad en PRNG explicada anteriormente, es posible enumerar todas las direcciones (y las claves privadas relacionadas) que puede crear la extensión Trust Wallet. Mi idea era almacenar todas las direcciones posibles en una tabla grande. Luego, a partir de una lista de direcciones extraídas de la cadena de bloques de Ethereum, se puede verificar si algunas direcciones están presentes en esta tabla. Si es así, se puede calcular su clave privada.

La derivación de la entropía a la mnemotécnica y luego a la dirección de Ethereum utiliza el mecanismo de derivación estándar BIP-32BIP-39, y la BIP-44 jerarquía de cuentas.

La primera dificultad fue enumerar todas estas direcciones. La transformación de semilla PRNG a dirección requiere los siguientes pasos:

  • Generación de entropía: inicialice el Mersenne Twister con la semilla y llámelo 16 veces para reunir la entropía inicial.
  • Entropía a mnemotécnica: un SHA-256 para calcular la suma de comprobación final incrustada en la última palabra.
  • Mnemónico a semilla: mnemotécnicos se convierten en una semilla de 512 bits usando PKBDF2-HMAC-SHA512 con 2048 iteraciones. Hay 2 cálculos SHA-512 por iteración, por lo que el costo total es de 4096 cálculos SHA-512.
  • Semilla a clave maestra BIP-32: 1 HMAC SHA-512 que cuesta 2 cálculos SHA-512.
  • Clave maestra para la clave privada de Ethereum: la clave maestra se deriva de m/44'/60'/0'/0/0. Esto requiere 3 derivaciones de clave privada secundaria reforzada y 2 derivaciones de clave secundaria normal.
    • Cada derivación de clave privada secundaria reforzada requiere un cálculo HMAC SHA-512 (2 SHA-512) y una adición en secp256k1.
    • Cada derivación de clave privada secundaria normal requiere una derivación de clave privada secundaria y una multiplicación escalar en secp256k1 para convertir la clave privada proporcionada en la entrada en una clave pública.
  • Clave privada de Ethereum para abordar: este último paso requiere una conversión de clave privada a pública, por lo que otra multiplicación escalar y un hash Keccak-256.

El costo total de todos estos pasos es entonces:

  • Inicialización y 16 llamadas a Mersenne Twister
  • 1SHA-256
  • 4108SHA-512
  • adiciones de 5 puntos
  • 2 multiplicaciones escalares en secp256k1

Los pasos más costosos son los cálculos SHA-512 y las multiplicaciones escalares. Para abreviar, el proceso general para transformar la semilla PRNG en una dirección Ethereum es lento. Ejecutar tales cálculos en una sola CPU llevaría meses, y probablemente varias semanas en las CPU que estaban disponibles en Donjon. Entonces, lo implementamos usando OpenCL (basado en GPU de resolución BIP39) y lo ejecuté en 2 GPU NVIDIA GeForce GTX 1080 Ti.

El resultado de esta herramienta es un archivo grande que contiene todas las direcciones de Ethereum que puede generar la extensión. Como hay 2^32 semillas posibles y cada dirección tiene una longitud de 20 bytes, esta tabla ocupa 80 Gb.

A partir de ahí, las búsquedas en la tabla son lentas: para hacer coincidir una dirección, sería necesario iterar a través de toda esta gran tabla.

Para acelerar estas búsquedas, dividimos la tabla en 256 tablas más pequeñas, según el primer byte de la dirección de Ethereum. Cada tabla contiene pares de semillas PRNG y su dirección Ethereum resultante.

Finalmente, para poder realizar búsquedas rápidas en cada tabla, las ordenamos según la dirección de Ethereum. Ahora es posible realizar búsquedas binarias en estas tablas: las búsquedas en estas tablas ordenadas son muy económicas.

Para ahorrar algo de espacio en disco, almacenamos la semilla PRNG y solo los primeros 8 bytes de cada dirección Ethereum. Los últimos 12 bytes no son necesarios, ya que las colisiones son insignificantes en mi caso de uso. Cada entrada ocupa entonces 12 bytes. Las tablas completas luego toman 48 Gb.

Estos son los tiempos para cada paso:

Usando estas tablas, es posible recuperar inmediatamente los mnemotécnicos usados ​​para generar una dirección. Para evaluar el impacto de la vulnerabilidad, Binance me pidió la mnemotécnica de 3 direcciones de prueba que proporcionaron. Aquí está el resultado:

Recuperar los 3 mnemotécnicos y las claves privadas tomó unos cientos de milisegundos. Según nuestras pruebas, el proceso es lo suficientemente rápido como para procesar en tiempo real todas las transacciones en la cadena de bloques de Ethereum y romper todas las direcciones vulnerables tan pronto como se utilizan. Al almacenar en caché las direcciones ya probadas, lo mismo se aplica a otras cadenas de bloques como BSC. En este escenario de ataque, uno podría monitorear las transacciones cuando llegan al mempool y calcular las claves privadas del remitente o el destinatario en tiempo real.

Listado de todas las direcciones de Ethereum usadas

Lo que nos gustaría es estimar el número real de billeteras vulnerables y su saldo. Esto suena fácil, ya que todas las transacciones son públicas, por lo que todas las direcciones están disponibles en la cadena de bloques. Sin embargo, no hay forma de recuperar directamente la lista de las direcciones utilizadas.

Implementamos un método que itera a través de cada bloque de la cadena de bloques de Ethereum. Extrajimos las direcciones del remitente y el destinatario de todas las transacciones y los parámetros de dirección de cada llamada a los contratos ERC-20.

Tenga en cuenta que con este método, solo se pueden detectar las billeteras usadas: algunas billeteras vulnerables que no recibieron activos nunca interactuaron con la cadena de bloques.

Escaneamos la cadena de bloques de Ethereum entre los bloques 14820000 y 16096000. El bloque 14820000 se creó el 21 de mayo de 2022, por lo tanto, justo antes de la solicitud de extracción que agregó el código vulnerable en Trust Wallet Core. 16096000 fue el último bloque cuando escribí esta publicación.

Los nodos públicos parecen tener un límite de velocidad, por lo que consulté varios nodos públicos en paralelo para recopilar un total de 147,910,120 32,613,317 XNUMX direcciones durante varias docenas de horas. Después de eliminar los duplicados, obtenemos una lista de XNUMX XNUMX XNUMX direcciones únicas.

El mismo método se ha utilizado para Binance Smart Chain. Se escanearon los nodos públicos de BSC.

Estimación del número de cuentas vulnerables

Finalmente, se ha escrito una herramienta para probar si una dirección ha sido creada por la extensión Trust Wallet. Realiza una búsqueda en las tablas generadas, obtiene la semilla PRNG y, a partir de ahí, calcula el mnemotécnico, la clave privada de Ethereum y la dirección asociada.

El cálculo es muy rápido. Las direcciones candidatas se ordenaron de antemano para minimizar la E/S y realizar una búsqueda binaria anidada. Las búsquedas en los 32 millones de direcciones tardan unos minutos con un simple script de Python.

Aquí hay un ejemplo con una dirección tomada de un tweet público respondiendo al anuncio de la extensión Trust Wallet. Tomé este como ejemplo ya que esta dirección tiene nunca ha sido usado, por lo que los fondos de los usuarios no están en riesgo.

La herramienta se ha ejecutado en el conjunto de datos de 1,873,720 4 22 detallado anteriormente. Probar todas las direcciones y calcular las claves privadas de las cuentas vulnerables tomó XNUMX min XNUMX s, por lo que es muy económico.

Con esta lista de claves privadas vulnerables, es posible enumerar todas las direcciones correspondientes, sus saldos y, obviamente, drenarlos... Durante nuestras investigaciones, alrededor de $30 millones estuvieron en riesgo en algún momento, pero no monitoreamos todas las cadenas y tokens a lo largo del tiempo. .

Remediación

2022, 17 de noviembre

La vulnerabilidad ha sido reportada a Binance usando su programa de recompensas de errores el 2022 de noviembre de 17.

Para confirmar la vulnerabilidad, Binance nos envió 3 direcciones y les pidió que proporcionaran mnemónicos:

¿Puede intentar ejecutar su herramienta y proporcionar mnemónicos para estas 3 direcciones?
Wallet 1 – 0xdf6D9547e163D5E7eafBe2FeB24Bfa12A4C913C0
Wallet 2 – 0xE1E0580cb5eA0c0FD034FF2cdfc872ce4493676C
Wallet 3 – 0x02b2Ae981b138F066344774A2AD75225A046c377
¡Gracias!
Saludos cordiales.

Una vez que se han calculado previamente todas las direcciones posibles, recuperar el mnemotécnico de una dirección es tan simple como buscar en una tabla de 4 mil millones de entradas. Los tres mnemotécnicos se han recuperado en 0.2 s:

2022, 21 de noviembre

Unos días después, el 21 de noviembre, el equipo de Trustwallet comprometido públicamente en Github la solución que evita la generación de nuevas semillas defectuosas. Estábamos bastante preocupados de que alguien lo notara y explotara la vulnerabilidad.

2022, noviembre

El equipo de Trustwallet actualizó la aplicación para advertir a sus usuarios, evitar que generen nuevas semillas defectuosas y eliminó los flujos de recepción.

A partir de ahí monitoreamos la situación y los fondos en riesgo. Solo unos días después del lanzamiento de estas billeteras vulnerables, alrededor de $ 30 millones estaban en riesgo.

2023, marzo 

El equipo de Trustwallet nos otorgó la recompensa más alta que ofrecen: $ 100k

2023, 22 de abril

Después de meses esperando que los usuarios migraran sus fondos, el equipo de Trustwallet reveló la vulnerabilidad y escribió un Post mortem. A partir de ahora, todavía hay billeteras con fondos restantes que pueden ser robados (~$100k). Trust Wallet prometió el reembolso de los fondos robados.

Conclusión

Esta vulnerabilidad ilustra el peor de los casos de un error criptográfico: cuentas comprometidas para siempre.

Crear una buena aleatoriedad es una tarea abrumadora: los dispositivos Ledger se basan en una lógica de silicio dedicada en nuestros chips de tarjetas inteligentes certificados que han sido el estándar de oro de las industrias seguras durante los últimos 40 años para garantizar una aleatoriedad de alta calidad y resistencia a la manipulación.

Dada la complejidad de contactar a los propietarios de esas cuentas y la posibilidad de usar esas cuentas comprometidas en todo tipo de billeteras de software y hardware diferentes, TrustWallet hizo un trabajo bastante bueno al reducir el riesgo para sus usuarios.

En el futuro (muy) (cercano) es probable que los bots luchen para ser los primeros en robar los fondos depositados en esas direcciones, similar a ¿Qué sucedió con las billeteras cerebrales en el pasado?.

Un agradecimiento especial a Jean-Baptiste Bédrune por salvar el mundo. Solo unos días después del lanzamiento de la extensión Trust Wallet, casi 30 millones de dólares estaban en riesgo. Podría haber ocurrido un escenario de pesadilla si un atacante encontrara la vulnerabilidad después de un par de meses.

Durante nuestras investigaciones, también notamos que algunas direcciones eran vulnerables aunque se generaron mucho antes del lanzamiento de Trust Wallet. Eso probablemente significa que esta vulnerabilidad existe en algunas otras implementaciones de billetera, lo cual es preocupante...

punto_img

Información más reciente

punto_img