Mejores prácticas para almacenar de forma segura tokens de acceso

17

¿Cuáles serían las mejores prácticas para almacenar tokens de acceso de otra API para sus usuarios? En particular, estoy desarrollando una aplicación con algunos amigos que permiten que el usuario inicie sesión en Facebook para autenticarse en nuestra API REST interna y hacer que pueda buscar a sus amigos (y otras cosas).

Estaba pensando en generar una clave y usarla para cifrar el token de acceso a largo plazo de la cuenta de Facebook del usuario y posiblemente otra información confidencial. Como esquema de encriptación, utilizaría AES-256-CBC y la clave se enviaría al cliente, que se conserva (y se actualiza de vez en cuando). Pero si genero esa clave con alguna aleatoriedad, entonces el usuario solo puede usar un cliente. Como los demás clientes necesitarían esa clave para descifrar el token de acceso de Facebook y otros datos. Una solución sería generar la clave de algo único durante el inicio de sesión de Facebook, pero desafortunadamente lo único que puedo encontrar es el ID de usuario, que necesito para encontrar el registro del usuario en la base de datos.

En realidad, hay muchos temas sobre esto en Stackoverflow, pero nada responde a lo que quiero. Lo que realmente quiero es cifrar el token de acceso de Facebook y otros datos con una clave que solo el cliente conoce. La creación de esas claves solo debe ser posible cuando el usuario se autentica utilizando el SDK de Facebook o cuando se suministra la clave actual.

¿Alguna idea?

    
pregunta Joren Van Severen 04.09.2013 - 14:11
fuente

3 respuestas

8

La suma de lo que almacena el cliente y lo que almacena su servidor debe ser suficiente para recuperar los datos secretos específicos del usuario (por ejemplo, el token de acceso de Facebook). Lo que el cliente almacena es, en su mayoría, la contraseña del usuario (la única área de almacenamiento permanente en el lado del cliente es el cerebro del usuario, si queremos permitir que el usuario use varias máquinas distintas a voluntad). Si entiendo correctamente, no desea que su servidor almacene los datos "tal como están": en caso de que su servidor esté completamente comprometido, los secretos del usuario deberían ser seguros (tanto como sea posible).

Esto apunta a cifrado basado en contraseña . De la contraseña del usuario se deriva una clave simétrica K que se utiliza para cifrar simétricamente un paquete que contiene los secretos del usuario, por ejemplo. la cuenta de facebook Técnicamente, esto se vería así:

  • Cuando el usuario se registra, elige su contraseña P y la envía a su servidor.
  • Su servidor genera un valor de sal aleatorio S y calcula PBKDF2 sobre P y S , para producir 256 bits de salida T . Llamemos a A los primeros 128 bits de T y K a la otra mitad de 128 bits.
  • La primera mitad ( A ) se almacena en la base de datos del servidor; esto se utilizará para autenticar usuarios.
  • La segunda mitad ( K ) se no almacenada; Esta es la clave simétrica para ese usuario. Los secretos del usuario se cifrarán con K .
  • Cuando el usuario inicia sesión, envía su nombre y P a su servidor (a través de HTTPS). Su servidor recupera la sal S para ese usuario (tal como está almacenado en su base de datos) y vuelve a calcular T (usando P y S con PBKDF2). Si la primera mitad del T recalculado coincide con el A almacenado, el usuario se autentica y la segunda mitad de T es K . Luego, el servidor puede descifrar el paquete almacenado y acceder al token de acceso de Facebook.

Con esta configuración, el servidor nunca almacena (en su disco o en su base de datos) el token de acceso claro a Facebook, pero puede acceder a él cuando el usuario inicia sesión; es responsabilidad del servidor recordar (en la RAM) el token de acceso de Facebook siempre que lo necesite.

Tenga en cuenta que cuando el usuario cambia su contraseña, esto también cambia K (el servidor también debe generar una nueva sal S , pero incluso si el servidor no lo hizo por error, K todavía se cambiaría); por lo tanto, el servidor debe descifrar el paquete almacenado con el antiguo K y cifrarlo nuevamente con el nuevo K cuando se cambie la contraseña. Esto no es difícil de integrar porque las interfaces de cambio de contraseña habitualmente piden la contraseña antigua y la nueva contraseña, por lo que en ese momento el servidor tiene ambas.

También tenga en cuenta que cuando se olvida la contraseña, el paquete se pierde. No hay recuperación para ese caso. Si el usuario olvida su propia contraseña, tendrá que hacer un restablecimiento de la contraseña, que es similar a un nuevo registro; y deberá obtenerse un nuevo token de acceso a Facebook.

En todo lo anterior, vemos que su servidor todavía ve la contraseña del usuario. Si su servidor está totalmente comprometido y secuestrado, entonces el atacante podrá observar las contraseñas de los usuarios y los tokens de acceso de Facebook de los usuarios para todos los usuarios que inicien sesión mientras el atacante controla el servidor. Prevenir que es mucho más difícil. Podría decirse que si su servidor presenta solo una interfaz web, donde toda la "inteligencia" en el lado del cliente es Javascript enviado por su servidor, es imposible hacer mejor que lo que hace el esquema anterior, en ese sentido situación.

    
respondido por el Tom Leek 04.09.2013 - 16:27
fuente
2

Estuve en la 10a conferencia ISC de seguridad y criptología la semana pasada y allí Vi a alguien proponer un método para almacenar tokens de paso de usuario utilizando Red neuronal . Ha creado una NN que aprende tokens de pase de usuario y se actualiza utilizando un método de aprendizaje rápido de NN. Es un método nuevo y promete seguridad, pero necesita mucha atención en el aprendizaje.

ACTUALIZAR

El documento estaba en Farsi titulado significa User Access Control Using Neural Network and chaotic system

(¡la pila no admite caracteres Farsi! ¡¡En su lugar usé la imagen!)

    
respondido por el sajjadG 04.09.2013 - 15:25
fuente
2
respondido por el ma11hew28 17.02.2014 - 21:03
fuente

Lea otras preguntas en las etiquetas