Esta semana ha estado en la boca de «todos» la reciente vulnerabilidad de KeePass (aunque en realidad se reportó el primer día de mayo), y que a fecha de este post, aún no tiene parche lanzado por parte del fabricante, luego lo comentamos.
Se trata del CVE-2023-32784 y fue reportado por el usuario conocido en SourceForge con el nickname de vdohney, quien a través de la publicación denominada «Security – Dumping Master Password from Memory, Even When Locked» reportó al fabricante este hallazgo que posteriormente se registro con Mitre Corporation (por lo visto).

Básicamente el investigador reportaba lo siguiente (cito textualmente):

Encontré un problema potencial en el último KeePass 2.X (configuración predeterminada). Dado un volcado de memoria de proceso, puedo reconstruir la contraseña maestra. No importa si el espacio de trabajo está bloqueado o no, funciona independientemente. La fuente de memoria tampoco es importante; por ejemplo, puede ser un archivo de paginación (swap) o el archivo de hibernación. No se necesita ejecución de código, únicamente la memoria sola.

A lo que rápidamente Dominik Reichl (autor de este gestor de contraseña) contestó mostrando interés por el hallazgo.
Días después el propio Dominik reconocía la vulnerabilidad y comentaba abiertamente algunas mejoras que se incorporará a la nueva versión de KeePass (2.54), que también cubren otras caracteristicas (también relacionada con seguridad). Aún no se tiene fecha fija del lanzamiento de la nueva versión, sin embargo se estima que pueda ser a principios de junio (es una tentativa del propio Dominik).

Bien, resulta que vdohney también hizo la divulgación de una PoC (prueba de concepto) a través de su repositorio de GitHub a la que denomino: keepass-password-dumper y que automatiza la extracción de la «Master Key» a partir de un volcado de memoria. Según comenta, el volcado de memoria puede ser un volcado completo de la RAM o simplemente un volcado de la memoria vinculada al proceso de la herramienta. En este caso yo he realizado pruebas con el volcado básico del proceso KeePass.exe y por a continuación os dejo mis conclusiones.

Análisis:

Como comentaba hace un momento, lo primero que haré es hacerme con un volcado de memoria (en caliente) asociada al proceso KeePass.exe. Para ello puedo tirar del propio Administrador de tareas de Windows (aunque como miembros de un equipo de Red Team ya deberíamos ir pensando como obtener este mismo recurso de forma remota y/o desatendida):

Al pulsar esta opción «Crear archivo de volcado«, obtendremos un fichero con extensión DMP que será almacenado en el disco, en una ruta por defecto.

Para mayor comodidad moveré dicho volcado en el propio directorio donde tengo la herramienta keepass-password-dumper:

Para poner a trabajar a este automatismo de vdohney será necesario contar con .NET implementado en el equipo (.NET 7.0 necesariamente, ya hice pruebas sin éxito con la versión anterior). Ejecutamos el siguiente comando:

dotnet run Dump_file_X.DMP

Pasado unos segundos, después de ir recorriendo el volcado de la memoria identificando carácter a carácter la composición de la «Master Key«, recibiremos un mensaje como este:

¿Qué se puede apreciar aquí? 2 cosas principalmente:

  • Lo primero y más llamativo, hemos sido capaces de obtener gran parte de la «Master Key» asociada a una base de datos.
  • Existen al menos 2 caracteres de la «Master Key» (los 2 primeros, por lo general) que no fueron claramente identificados, en este caso para el segundo carácter me define algunas aproximaciones, sin embargo para el primer carácter la identidad es enigmática.

Vayamos a una caso práctico. Si directamente llevamos los caracteres claramente identificados, a la base de datos de KeePass objetivo:

Obviamente los resultados no serán los anhelados y conseguiremos un mensaje como este:

Ahora bien, ¿Cómo podemos descubrir y resolver la identidad de esos 2 primeros caracteres?

Pues, no se me ocurre otra manera de presentar mi solución alternativa y complementaria para esta necesidad.

Complemento a los resultados obtenidos:

Haciendo pruebas en mi laboratorio, me recordé de una herramienta (que ya traje a este blog), denominada PoshKPBrute que nos venía bien para hacer fuerza bruta (mediante diccionario) para intentar descubrir la contraseña de un fichero con extensión kdbx. Pero claro, las posibilidades quedan a merced de lo efectivo que sea el diccionario proporcionado, por tanto si mi «Master Key» es ciertamente robusta, las posibilidades se reducen drásticamente.

Llegados a este punto pensé:

Pero claro, ahora la fuerza bruta que se deba hacer para complementar la Master Key es de tan solo de 2 caracteres, y para 1 de ellos solo debo centrarme en X caracteres (que no todos), pues listo, automatismo que te crio!
No se, a veces me da por pensar en MMA y otras veces por ver que puedo automatizar.

Como el scripting en PowerShell no es mi fuerte y tampoco pretendo «reinventar la rueda», me he permitido tomar el código fuente de PoshKPBrute, recortarlo (manteniendo las funciones principales y su estructura base), optimizarlo (para este nuevo fin) y en definitivamente adaptarlo para que a partir de la necesidad del usuario que acaba de ejecutar keepass-password-dumper y necesite completar la «Master Key» pueda obtener finalmente la composición completa y definitiva de este elemento clave.

Ya mismo estoy dejando en mi GitHub el script en PowerShell que resolví y decidí llamarlo «originalmente»: BruteForce-to-KeePass.ps1.

Ahora veamos su funcionamiento. Para ponerlo en marcha primeramente importaré el módulo a PowerShell:

Import-Module BruteForce-to-KeePass.ps1

Luego podré ponerlo en marcha directamente escribiendo:

BruteForce-to-KeePass

Que por lo que fuera, si no tengo implementado KeePass en el equipo donde estoy ejecutando el script, conseguiría ver el siguiente mensaje de advertencia:

También he añadido un mensaje de error para cuando el usuario indique un fichero kdbx inexistente o erróneo:

Listo, así de simple, ahora si podremos conseguir la ansiada «Master Key» asociada a la base de datos (fichero kdbx) de forma completa e inequívoca:

Reseñar que el script (BruteForce-to-KeePass.ps1) tan solo nos solicitará 3 datos que obviamente a esta altura ya lo tendríamos en nuestro poder. Estos son:

  • El conjunto de caracteres conocidos para la segunda posición de la «Master Key«. Recordemos que esto nos lo arroja keepass-password-dumper.
  • El «sufijo» o la cadena de caracteres ya conocidos de la «Master Key«. También identificada gracias a keepass-password-dumper.
  • Finalmente el fichero kdbx asociado a la base de datos de KeePass objetivo.

Con estos datos, lo primero que hará BruteForce-to-KeePass.ps1 será generarnos un diccionario con todas las posibilidades.

Luego y ya gracias al «core» de PoshKPBrute hará el descubrimiento de la contraseña válida de la base de datos de KeePass (del fichero kdbx definido). Veamos un ejemplo de resultado favorable:

¡Bingo! Ya tenemos acceso a las contraseñas dentro de la base de datos de KeePass:

Esto fue todo por hoy, no dudéis en escribir cualquier inquietud que os susciten mientras validáis estas posibilidades y le dais caña al automatismo que he generado. Por su puesto está lejos de ser perfecto, sin embargo a mi me resultó funcional, espero que a vosotros también os aporte. Hasta el siguiente post.

Referencias: