Pre-generando 'tokens seguros'

2

En nuestra aplicación web, hacemos un buen uso de los tokens de un solo uso. Por ejemplo, cuando alguien crea cualquiera de las tres "cuentas", restablece su contraseña o cualquier otra cantidad de cosas que requieren tokens aleatorios de un solo uso, nosotros:

  1. Genera 32 bytes aleatorios desde el CSPRNG del SO
    1. La URL base-64 lo codifica
    2. Almacene el hash en nuestra base de datos (Scrypt con N = 2 ^ 15, r = 8, P = 1)
    3. Proporcione al usuario el token de uso único (generalmente en forma de una URL)

Todo esto funciona bien. Sin embargo, a través de los perfiles, hemos notado que algunas de nuestras llamadas a la API pueden demorar un par de segundos porque tienen que verificar y crear tokens. Algunas llamadas a la API usarán Scrypt tres o más veces.

Si bien no es terrible, nos gustaría acelerar las llamadas a la API si es posible.

He planteado la idea de generar previamente algunos tokens aleatorios, pero me gustaría una segunda opinión antes de ir a la cabeza y comenzar con esto.

Hay dos maneras en las que creo que podríamos abordar esto. Primero, simplemente crearíamos (token, hash, salt) triples y almacenaríamos en memoria. El aspecto negativo de esto es que tendríamos los tokens sin cifrar simplemente sentados allí, y un atacante podría obtenerlos y usarlos. Sin embargo, eso requeriría acceso a la instancia específica de AWS y los tokens de un solo uso serían la menor de nuestras preocupaciones en esa situación.

El segundo sería utilizar una bóveda de algún tipo, por lo que las tuplas todavía están en la memoria, pero están cifradas. Esto suena más seguro, pero aún requiere que la contraseña de la bóveda esté en algún lugar, por lo que el atacante aún tendría acceso si tuviera acceso a la instancia de AWS.

¿Pensamientos? Estoy un poco preocupado por esta idea, pero realmente me gustaría reducir algunas llamadas de API de tres segundos a menos de un segundo.

    
pregunta Eric Lagergren 11.03.2016 - 22:49
fuente

3 respuestas

1

Resumen: no es necesario utilizar scrypt en datos verdaderamente aleatorios como el suyo. Solo usa un hash seguro como SHA256 y estarás bien.

Explicación: Hashes como SHA256 son, a nuestro entender, irreversibles. La única forma de pasar de un hash al texto original es usar una combinación de precomputación y forzado. Resulta que el cálculo previo es muy exitoso para almacenar contraseñas porque las personas eligen contraseñas débiles y predecibles. Esta es la razón por la que se necesita crear toda la ciencia de los hashes de contraseña.

Sin embargo, tiene 256 bits de entropía. Es inviable generar una tabla de arco iris (no tenemos espacio para almacenarla en este planeta) o fuerza bruta ( el sol estallará antes de que lleguemos a la mitad del camino) un simple hash SHA256 sobre un espacio de entrada tan grande.

Use el SHA256 rápido en sus datos aleatorios y tenga la seguridad de que no se puede rastrear.

    
respondido por el Neil Smithline 12.03.2016 - 01:10
fuente
0

En lugar de ejecutar scrypt en un token aleatorio, para este tipo de situaciones generaría un hmac. Aquí hay un ejemplo de reddit en la dirección de correo electrónico de la copia de seguridad de la información. a>:

def generate_notification_email_unsubscribe_token(user_id36, user_email=None,
                                                  user_password_hash=None):
    """Generate a token used for one-click unsubscribe links for notification
    emails.
    user_id36: A base36-encoded user id.
    user_email: The user's email.  Looked up if not provided.
    user_password_hash: The hash of the user's password.  Looked up if not
                        provided.
    """
    import hashlib
    import hmac

    if (not user_email) or (not user_password_hash):
        user = Account._byID36(user_id36, data=True)
        if not user_email:
            user_email = user.email
        if not user_password_hash:
            user_password_hash = user.password

    return hmac.new(
        g.secrets['email_notifications'],
        user_id36 + user_email + user_password_hash,

Si necesita asegurarse de que solo se use una vez, también puede insertar ese valor en su base de datos y eliminarlo una vez que se usa, como está haciendo actualmente.

    
respondido por el Xiong Chiamiov 12.03.2016 - 00:31
fuente
0

Dice que le preocupa que los atacantes obtengan acceso a los tokens si los genera previamente. Aunque esto técnicamente les da una ventana más grande, sería mucho más difícil para un atacante monitorear su token seguro que se genera de todos modos.

La razón por la que las contraseñas de hash es que las futuras violaciones en los próximos años no revelan las contraseñas. En este caso, solo 1 minuto de las infracciones pasadas son un problema. Si alguien te viola hace 1 minuto, es probable que también te lo hagan a ti.

Mi sugerencia es esta:

  • Tenga un programa que genere, por ejemplo, 600 tokens seguros. Aísle la memoria de este programa de otros programas y procesos lo mejor que pueda. (Por ejemplo, conviértalo en un usuario diferente al de sus otras cosas).
  • Cualquier proceso puede solicitar un token del programa. Cuando se solicita un token, se elimina de la agrupación.
  • Dependiendo de qué tan paranoico sea, haga que el programa descarte las 10 fichas más antiguas cada segundo y genere 10 nuevas. De esta manera, cualquier token solo puede durar un minuto.

La respuesta de Neil también es correcta (si por alguna razón, Sha256 está actuando lento para ti, puedes usar el arriba).

    
respondido por el PyRulez 13.03.2016 - 03:43
fuente

Lea otras preguntas en las etiquetas