Autor: enze

Editora: Liz

introducción

Recientemente, se descubrió que la biblioteca de cifrado elíptico, que se utiliza ampliamente en el ecosistema JavaScript, tenía una grave vulnerabilidad de seguridad (GHSA-vjh7-7g9h-fjfh). Al construir entradas específicas y extraer la clave privada después de firmar solo una vez, un atacante puede obtener control total sobre los activos digitales o las credenciales de identidad de la víctima.

La causa raíz de esta vulnerabilidad radica en el defecto de procesamiento de la entrada no estándar por parte de la biblioteca elíptica, que puede provocar que se repita el número aleatorio k en la firma ECDSA. Dado que la seguridad del algoritmo ECDSA depende en gran medida de la unicidad de k, una vez que se repite k, la clave privada se puede derivar directamente, lo que causa riesgos de seguridad irreversibles.

Este artículo analizará los principios, las causas y los impactos de la vulnerabilidad y brindará sugerencias de reparación para ayudar a los desarrolladores a reducir los riesgos de seguridad.

Antecedentes de vulnerabilidad

Introducción a la biblioteca elíptica

elliptic es una biblioteca de criptografía de curva elíptica ampliamente utilizada en el ecosistema de JavaScript, que admite múltiples curvas (como secp256k1, ed25519). Esta biblioteca es utilizada por una gran cantidad de billeteras de criptomonedas, sistemas de autenticación de identidad, aplicaciones Web3, etc.

Impacto

  • Versiones afectadas: elliptic<= 6.6.0

  • Curvas afectadas: secp256k1, ed25519, etc.

  • Escenarios de impacto: Todas las aplicaciones que aceptan entradas externas para firmas ECDSA (especialmente sistemas que aceptan entradas externas para firmas)

Las aplicaciones que dependen de eliptic para la firma ECDSA y permiten a los usuarios proporcionar mensajes sin filtrar como contenido de firma tienen más probabilidades de verse afectadas por esta vulnerabilidad.

Principio de vulnerabilidad

El número aleatorio k en la firma ECDSA

Imagina que tienes un sello único (clave privada) y cada vez que firmas un documento necesitas sumergirlo en una almohadilla de tinta única (número aleatorio k). La marca estampada generará dos números r y s, que es el resultado de la firma.

Hay varios puntos claves en este proceso:

  • El sello (clave privada) nunca cambia: representa su identidad.

  • Se debe utilizar una almohadilla de tinta nueva para cada firma (el número aleatorio k nunca debe repetirse).

  • Incluso cuando se firma el mismo documento, los resultados de la firma (r, s) deben ser diferentes.

  • Cualquiera puede verificar que la impresión se realizó con su sello (firma de verificación de clave pública).

  • Pero nadie puede revertir su sello (clave privada) de la impresión mientras k esté seguro.

Para garantizar la seguridad de k, ECDSA adopta la especificación RFC 6979 y utiliza un generador de números aleatorios determinista (HMAC_DRBG o HKDF) para calcular k. Al generar k, utilice la clave privada d y el mensaje m como semillas para garantizar que k esté fijado en la misma entrada. El proceso de cálculo es el siguiente:

Puntos clave:

1. k debe ser aleatorio y único, de lo contrario se filtrará la clave privada.

2. Si k es el mismo en ambas firmas, el atacante puede simplemente recuperar la clave privada d directamente a través de las dos firmas (r, s1) y (r, s2).

Derivación matemática:

Supongamos que un usuario firma dos mensajes diferentes m1 y m2, pero el número aleatorio k es accidentalmente el mismo, entonces los resultados de la firma son los siguientes:

Un atacante puede calcular la diferencia entre s1 y s2:

Dado que m1, m2, s1 y s2 son todos conocidos, el atacante puede resolver k:

Luego, sustituya k en la ecuación de firma original y resuelva para la clave privada d:

Análisis de vulnerabilidad

La biblioteca elíptica debería haber utilizado HMAC_DRBG (un generador de números aleatorios determinista) para garantizar que k sea único para cada firma. Sin embargo, debido a errores en el procesamiento de entrada, diferentes mensajes pueden generar el mismo k en algunos casos, lo que resulta en la divulgación de la clave privada.

k Generar código

En el método sign() de la biblioteca elíptica, k se genera mediante el generador de números pseudoaleatorios HMAC_DRBG. El código relevante es el siguiente:

elíptico/lib/elliptic/ec/index.js

Los parámetros de entrada de HMAC_DRBG incluyen principalmente:

  • entropía → La clave privada bkey se utiliza aquí para garantizar que HMAC_DRBG tenga suficiente aleatoriedad.

  • nonce (semilla de número aleatorio) → Calculado a partir de msg, afecta el valor final generado de k.

Dado que HMAC_DRBG es determinista, la misma entropía y nonce generarán el mismo k. Si el nonce es el mismo en diferentes procesos de firma, entonces k también será el mismo, lo que conducirá a la divulgación de la clave privada.

Causa de la vulnerabilidad: la conversión de BN conduce a la reutilización de nonce

En la implementación de eliptic, msg se convierte a BN (número grande) y luego se calcula el nonce mediante msg.toArray():

Problema:

  • msg es una instancia de BN, pero nonce es una matriz.

  • Diferentes instancias de BN pueden producir la misma matriz después de la conversión.

  • Esto significa que se puede generar el mismo nonce para diferentes mensajes, lo que en última instancia conduce a una reutilización k.

Si k se reutiliza en dos mensajes diferentes, msg1 y msg2, la clave privada d se puede recuperar mediante la fórmula matemática mencionada anteriormente.

Un atacante puede construir un mensaje especial para que su nonce sea el mismo, provocando así que se reutilice k. Solo es necesario obtener un par (r, s1) y (r, s2) para recuperar la clave privada d mediante cálculo matemático. Lo que es más grave es que el atacante puede construir un mensaje malicioso para cualquier par de mensaje/firma conocido, lo que significa que siempre que se induzca a la víctima a firmar un mensaje malicioso una vez, el atacante puede recuperar completamente la clave privada y falsificar cualquier firma.

Explotación (PoC)

La biblioteca elíptica permite utilizar una cadena hexadecimal como uno de los tipos de entrada. Al firmar, convierte msg en una instancia de BN y luego en un tipo de matriz. Si dos mensajes diferentes generan la misma matriz después de la conversión, el nonce también será el mismo, lo que eventualmente conducirá a la reutilización k.

Ejemplo de código:

Salida en ejecución:

msg1 = "message" y msg2 = "-message" generan el mismo nonce después de la conversión BN (el diseño de elliptic acepta cadenas hexadecimales como uno de los posibles tipos de entrada). Dado que el nonce es el mismo, el k generado por HMAC_DRBG también es el mismo. A partir de los resultados de la firma, podemos ver que el valor r es exactamente el mismo, lo que es una manifestación directa de la reutilización de k.

Proceso de ataque completo:

1. Simular a la víctima para firmar un mensaje normal y obtener el mensaje msg0 y la firma sig0.

2. El atacante construye un mensaje malicioso msg1 e induce a la víctima a firmarlo para obtener sig1.

3. Explote la vulnerabilidad de reutilización k y calcule k a partir de (r, s1) y (r, s2).

4. Utilice k para calcular aún más la clave privada d y el ataque tendrá éxito.

Ejemplo de código:

Salida en ejecución:

Sugerencias de restauración

1. Actualice Elliptic a la versión 6.6.1 o superior. El funcionario ha solucionado este problema.

2. Evite firmar directamente mensajes no verificados y asegúrese de que el mensaje esté estandarizado.

3. Reemplace las claves privadas que puedan verse afectadas.

Resumir

Esta vulnerabilidad en elíptica expone la extrema sensibilidad de las firmas ECDSA al número aleatorio k. Una vez que se reutiliza k, la clave privada se puede recuperar directamente y el atacante puede controlar completamente los activos y la identidad del usuario. Los desarrolladores deben corregir las vulnerabilidades de manera oportuna y regular estrictamente el procesamiento de entrada para garantizar la seguridad de las firmas ECDSA. Por último, gracias a Rabby Wallet por proporcionar información sobre vulnerabilidades.

Referencias

[1] https://github.com/indutny/elliptic/security/advisories/GHSA-vjh7-7g9h-fjfh
[2] https://paulmillr.com/posts/deterministic-signatures