Usar libsecret para manejar claves en Gnome Keyring

Vamos a ver como funciona GNOME Keyring y como acceder a los datos que almacena usando la librería libsecret.

Muchas aplicaciones requieren un password de acceso como medida de control para acceder a algún recurso. Con el fin de evitar que la aplicación nos solicite el usuario y contraseña cada vez que accedemos al recurso protegido se utiliza GNOME Keyring. GNOME Keyring es una colección de componentes en GNOME que almacena secretos, contraseñas, claves, certificados y los pone a disposición de las aplicaciones. Las aplicaciones que usan GNOME Keyring pueden almacenar estos secretos y usarlos cuando los necesitan. Al estar integrado con el inicio de sesión del usuario, el almacenamiento secreto se puede desbloquear cuando el usuario inicia sesión en el sistema.

La librería libsecret sirve para almacenar y recuperar contraseñas y otros secretos, comunicándose con el "Servicio de Secretos" usando D-Bus. Tanto GNOME Keyring como Ksecretservice son implementaciones de un "Servicio de Secretos".

Para operar con GNOME Keyring podemos usar Seahorse, que ya vimos al trabajar con certificados con GnuPG.

Vamos a usar un programa sencillo que utiliza los servicios que vienen de ejemplo en la documentación. Si lanzamos la aplicación sin parámetros realiza una búsqueda de la clave siguiendo los atributos que se le pasan en el esquema. Si pasamos un argumento creamos una clave usando el argumento de password.

/* 
gcc -g -Wall `pkg-config --cflags libsecret-1` gfindpass.c -o gfindpass `pkg-config --libs libsecret-1` 
*/ 
 
#include <glib.h> 
#include <libsecret/secret.h> 
#include <locale.h> 
 
#define EXAMPLE_SCHEMA example_get_schema () 
 
static const SecretSchema * 
example_get_schema (void) 
{ 
    static const SecretSchema the_schema = { 
        "org.example.Password", SECRET_SCHEMA_NONE, 
        { 
            { "number", SECRET_SCHEMA_ATTRIBUTE_INTEGER }, 
            { "string", SECRET_SCHEMA_ATTRIBUTE_STRING }, 
            { "even", SECRET_SCHEMA_ATTRIBUTE_BOOLEAN }, 
            { "NULL", 0 }, 
        } 
    }; 
    return &the_schema; 
} 
 
static void grabar_pass(char *npass)  
{ 
    GError *error = NULL; 
 
    /* 
     * Las variables que forman la lista de argumentos serán usadas  
     * posteriormente para encontrar el password.  
     * Estos atrubutos deben cumplir con el esquema. 
     * La etiqueta 'Clave clibre' servirá como referencia, por ejemplo en  
     * seahorse, pero no para localizar o usar la clave 
    */ 
    secret_password_store_sync (EXAMPLE_SCHEMA, SECRET_COLLECTION_DEFAULT, 
                                 "Clave clibre", npass, NULL, &error, 
                                 "number", 9, 
                                 "string", "nine", 
                                 "even", FALSE, 
                                 NULL); 
 
    if (error != NULL) { 
         /* ... manejamos aquí los errores */ 
        g_print("Error al grabar el pass: %s\n", error->message);  
        g_error_free (error); 
    } else { 
        /* ... la password se ha grabado correctamente */ 
        g_print("Password guardado con éxito\n");  
    } 
 
} 
 
int main(int argc, char *argv[]) 
{ 
     
    GError *error = NULL; 
 
    setlocale(LC_ALL, "");  
 
    g_print("Probando gnome-keyring....\n"); 
 
    if (argc == 2) // guardamos pass 
        grabar_pass(argv[1]); 
 
    /* Los atributos usados en la búsqueda del password deben cumplir con el  
     * esquema.  
    */ 
    gchar *password = secret_password_lookup_sync (EXAMPLE_SCHEMA, NULL, &error, 
                                                    "string", "nine", 
                                                    "even", FALSE, 
                                                    NULL); 
    if (error != NULL) { 
        /* ... manejamos los errores aquí */ 
        g_print("Error leyendo passwords: %s\n", error->message);  
        g_error_free (error); 
        exit(EXIT_FAILURE); 
    } else if (password == NULL) { 
        /* password es igual a null en caso de no encontrarse */ 
        g_print("Password no encontrado\n"); 
 
    } else { 
        /* ... tenemos el password */ 
        g_print("Password encontrado!!!: %s\n", password); 
        secret_password_free (password); 
    } 
 
    exit(EXIT_SUCCESS); 
} 

Creamos el ejecutable:

gcc -g -Wall `pkg-config --cflags libsecret-1` gfindpass.c -o gfindpass `pkg-config --libs libsecret-1`

Necesitamos la librería libsecret-1 que a su vez usa la librería glib. En ramas debian podemos instalarlas con:

sudo apt install libsecret-1-dev

Vamos a mirar con seahorse como almacena las contraseñas guardadas:

Claves en Seahorse

Este equipo no hay actualmente ninguna contraseña.

Si lanzamos la aplicación no encuentra ninguna coincidencia:

./gfindpass 
Probando gnome-keyring....
Password no encontrado

Vamos a crear una contraseña, a si que le pasamos un valor como parámetro a la aplicación:

./gfindpass 123456
Probando gnome-keyring....
Password guardado con éxito
Password encontrado!!!: 123456

Sobra decir que no se debe usar un password 123456 en ningún caso. Tampoco es buena idea utilizar una aplicación de este tipo que no solo muestra el password en pantalla, también lo deja en el cache del scroll del terminal

Hemos creado una entrada de clave y la aplicación busca la clave y la encuentra.

Si ejecutamos solo para buscar la clave, nos da el resultado:

./gfindpass 
Probando gnome-keyring....
Password encontrado!!!: 123456

Podemos ver en seahorse que tenemos creada la clave en contraseñas, en el deposito de claves que tenemos por defecto: 'Inicio de sesión':

Claves en Seahorse

Si miramos las propiedades de la clave, podemos ver los atributos que le dimos a la clave en el esquema, que son los que se utilizan en la búsqueda:

Detalles clave Seahorse

Es importante tener en cuenta que este deposito se desbloquea siempre que abrimos una sesión. Eso hace que estén disponibles las password, por ejemplo de la aplicación de correo que lee por IMAP los mails y los envía por SMTP. En este caso crearía una entrada en el deposito de claves para cada una de ellas. Al estar el deposito desbloqueado es accesible a cualquier aplicación que se ejecute en la sesión de usuario.

Esta tecnología esta orientada a proteger de ataques pasivos, no de ataques activos. Pongo aquí un extracto de la página de gnome-wiki: la Filosofía de Seguridad de gnome-keyring donde explican muy bien los objetivos, riesgos y protecciones que nos ofrece una aplicación de este tipo:

Security Theater (teatro de seguridad)

Un objetivo de gnome-keyring es no hacer cosas que hagan que el usuario se sienta seguro, pero que en realidad no sean "seguras".

Un ejemplo de teatro de seguridad es dar la ilusión de que de alguna manera una aplicación que se ejecuta en un contexto de seguridad (como su sesión de usuario) puede mantener la información de otra aplicación ejecutándose en el mismo contexto de seguridad.

Otro ejemplo de teatro de seguridad podría ser: ocultar, pero en realidad no cifrar secretos.

Ataques pasivos

Un ataque pasivo es aquel en el que el atacante no puede modificar nada dentro del contexto de seguridad. En el contexto de gnome-keyring, un atacante pasivo no tendría acceso a su sesión de usuario.

El objetivo de gnome-keyring es protegerte de los ataques pasivos. Los ataques pasivos son aquellos que podrían ocurrir mientras no está conectado, o desde otro usuario (no root) que se ejecuta en la misma computadora.

Algunos pasos que toma gnome-keyring para prevenir ataques pasivos son:

  • Cifrar sus secretos (contraseñas y claves) para que si le roban la computadora o si copia el disco duro, no estarán disponibles para el atacante
  • Intentar evitar que sus secretos sean intercambiados o escritos en el disco
  • Posicionar y desechar todos los secretos cuando su computadora está bloqueada
  • Permitir solo que el mismo usuario use y dispense secretos

Ataques activos

Un ataque activo es donde el atacante puede cambiar algo en su contexto de seguridad. En el contexto de gnome-keyring, un atacante activo tendría acceso a su sesión de usuario de alguna manera. Un atacante activo puede instalar una aplicación en su computadora, mostrar una ventana, escuchar los eventos X que van a otra ventana, leer su memoria, espiarlo desde una cuenta root, etc.

Si bien sería bueno que gnome-keyring algún día se endurezca contra los ataques activos que se originan en la sesión del usuario, la realidad es que el "escritorio" de software libre hoy en día simplemente no está diseñado con esas cosas en mente. Necesitamos completar e integrar cosas como las siguientes. Felicitaciones a las grandes personas que trabajan en partes de estas cosas:

  • Trusted X
  • Uso generalizado de contextos de seguridad para diferentes aplicaciones (SELinux, AppArmor)
  • Firma de solicitud (para ACL)

No estamos en contra del objetivo de proteger contra ataques activos, pero sin endurecer el escritorio en general, tales esfuerzos equivalen a un teatro de seguridad- William JonMcCann

En general es importante saber el alcance de una herramienta/tecnología/recurso/aplicación a la hora de proteger un recurso así como sus limitaciones.

En este caso, cualquiera que tenga acceso a nuestra sesión de usuario tendría acceso a las claves del anillo de claves. Abrir un correo/pdf/documento que explote una vulnerabilidad en una aplicación, o ejecutar una aplicación o script malicioso podrían tener acceso a las claves del anillo, no por un defecto en la implementación de gnome-keyring, sino porque no esta diseñada esa herramienta para evitar ese tipo de explotación.

Podemos crear otro deposito de contraseñas que este protegido con contraseña y tenerlo bloqueado por defecto. En este deposito podríamos tener claves que solo se utilicen de forma más esporádica y desbloquearlos cuando necesitemos usarlo.

Con seahorse podemos crear el depósito:

Seahorse crear deposito

Lo he llamdo depositoPrivado. Le damos una contraseña que nos pedirá cuando queramos desbloquear el depósito. Borramos la clave que creamos en el deposito 'Inicio de sesión'. Ponemos el nuevo deposito como predeterminado y ejecutamos nuestra aplicación para crear una clave:

./gfindpass 77877
Probando gnome-keyring....
Password guardado con exito
Password encontrado!!!: 77877

Podemos ver que la clave se a creado en el nuevo depósito:

Pero también nos ha creado una nueva clave en el deposito 'Inicio de sesión' para desbloquear automáticamente el depositoPrivado (en anteriores versiones había una pestaña que nos permitía desactivar esta opción al crear nuevos depósitos):

Esto no nos interesa así que la borramos. Dejamos el deposito de inicio de sesión como deposito por defecto, bloqueamos el depositoPrivado y ejecutamos nuestra aplicación:

./gfindpass 
Probando gnome-keyring....

Cuando intenta acceder a las claves, al estar bloqueadas nos pide el password:

y si es correcto nos da el resultado:

Password encontrado!!!: 77877

Aunque esto funciona, si realmente tenemos password que requieren una protección mayor, como pasaba con el certificado privado del anterior post, no debe de estar en un equipo en el que se pueda ver comprometido. Lo podemos tener en un equipo que solo se use para eso, en una maquina virtual segura o utilizar otros sistemas de seguridad adicionales.

Modificado por última vez enViernes, 14 Agosto 2020 19:59
(0 votos)

Deja un comentario

Asegúrese de introducir toda la información requerida, indicada por un asterisco (*). No se permite código HTML.