Resumen
El monedero de Monero (wallet2) tiene un modo de sincronización en segundo plano pensado para seguir escaneando la cadena mientras el monedero está bloqueado, usando solo la clave de visualización. Para ello guarda una caché aparte, la "caché de fondo", que puede ir protegida con una contraseña específica para ese modo, distinta de la del monedero principal.
Antes de escribir esa caché, el código hace una copia completa del monedero y la "limpia" con wallet2::clear_user_data(), cuyo propósito documentado es eliminar todo lo que un monedero de fondo con solo la clave de visualización no necesita. El problema es que esa limpieza es incompleta:
- Borra
m_tx_keys, el mapa con las claves secretas de las transacciones salientes. - No borra
m_additional_tx_keys, el mapa vecino que guarda las claves secretas adicionales de esas mismas transacciones (valoresstd::vector<crypto::secret_key>indexados por hash de transacción), y que también se serializa en la caché.
Resultado: esas claves adicionales acaban en la caché de fondo, cifradas con la clave de esa caché y no solo bajo la protección de la caché principal del monedero.
El hallazgo se hizo por revisión del código fuente (árbol con DEF_MONERO_VERSION "0.18.1.0" en src/version.cpp.in). El investigador no validó el rango exacto de versiones afectadas y señala que la lógica probablemente es independiente del sistema operativo. No se creó exploit ni prueba práctica. En HackerOne figura con severidad baja y como resuelto.
Pasos de reproducción
No hay prueba de concepto: se reproduce leyendo el código. El recorrido es este:
- En
wallet2::store_background_cache()(src/wallet/wallet2.cpp:13751) se serializa el monedero actual, se deserializa en un objeto de monedero de fondo, se llama abackground_w2->clear_user_data()y se guarda el resultado como caché de fondo. - En
wallet2::clear_user_data()(src/wallet/wallet2.cpp:4532) se vacíanm_tx_keys, notas, destinos, etiquetas, atributos y otros datos de usuario, pero no aparecem_additional_tx_keys. El comentario desrc/wallet/wallet2.h:1819confirma que esta función existe para minimizar datos sensibles en el monedero de fondo. - En la serialización del monedero (
src/wallet/wallet2.h:1390)m_additional_tx_keysforma parte de la caché. - En la definición del campo (
src/wallet/wallet2.h:1934) se ve que contiene valoresstd::vector<crypto::secret_key>. - En la ruta de confirmación de transacciones (
src/wallet/wallet2.cpp:7627) se guardaptx.additional_tx_keysenm_additional_tx_keyscuandostore_tx_info()está activo, ym_store_tx_infovaletruepor defecto (src/wallet/wallet2.cpp:1200). - Esas claves se usan después como material secreto en las comprobaciones de clave de transacción (
src/wallet/wallet2.cpp:12088) y para generar pruebas de transacción (src/wallet/wallet2.cpp:12252), lo que demuestra que son sensibles.
Impacto
Alguien con acceso local a la caché de fondo y a su contraseña o clave, pero no a la contraseña principal del monedero, podría extraer las claves secretas adicionales de las transacciones salientes que las usaron. Con ellas podría, en algunas condiciones:
- Obtener material capaz de generar pruebas sobre pagos salientes concretos.
- Vincular el monedero con pagos específicos, sobre todo si lo combina con identificadores de transacción, direcciones de destino u otros metadatos del monedero o de la caché.
Es, por tanto, una degradación de la privacidad que parece cruzar la frontera de confianza que el bloqueo del monedero y el modo "solo clave de visualización" pretenden establecer.
Límites del impacto: no parece exponer la semilla, ni la clave privada de gasto, ni la clave privada de visualización, y no permite gastar fondos. Además, solo afecta a transacciones con claves adicionales no vacías y exige acceso local más las credenciales de la caché de fondo. El propio investigador admite que los mantenedores podrían considerar suficiente la protección de esa caché.
Remediación
El investigador propone borrar también m_additional_tx_keys dentro de wallet2::clear_user_data(), junto a m_tx_keys, y añadir una prueba de regresión o una comprobación sobre la serialización que garantice que una caché de fondo generada a partir de un monedero con ambos campos no conserve ninguno de los dos. El reporte no detalla qué cambio se aplicó finalmente.