2009-03-14 20 views
6

Nuestras aplicaciones basadas en la web tienen cuentas de usuario atadas a los usuarios con las contraseñas especificadas durante la creación de la cuenta. En el caso de Java, ¿cómo se procesa la contraseña de forma segura, antes de persistir en su hash en la base de datos?¿Cómo se almacenan los hashes de contraseña de forma segura en la memoria, al crear cuentas?

Para ser más específicos, ¿cómo se asegura que la cadena que contiene la contraseña se recolecta en un intervalo de tiempo suficientemente corto?

+0

Esto podría ayudar a asegurar la contraseña durante el proceso de registro.http: //wheelersoftware.com/articles/spring-security-hash-salt-passwords.html –

Respuesta

6

Si tiene la posibilidad (puede ser difícil en aplicaciones web), sería mejor almacenar contraseñas en matrices de caracteres que almacenarlas en cadenas. Si usted tiene que almacenar la contraseña, puede sobrescribir en la memoria mediante el uso de Array.fill() y hacer la referencia disponible para el recolector de basura por descartarlo:

Arrays.fill(password, ' '); 
password = null; 

Acabo de notar que anulando la contraseña sería un poco paranoico, pero usted puede hacer si se tranquiliza ti :)

+0

Si esto es posible en una aplicación web, lea la contraseña del flujo de entrada del servlet en una matriz de bytes, y luego complete la matriz con ceros después de mantener la contraseña, entonces debería ser un enfoque viable. El proyecto OWASP Java usa esto en un ejemplo, pero no para las contraseñas persistentes. –

+2

¿No requiere esto que el recolector de basura no compacte la pila y deje una copia de la matriz en otro lugar de la memoria? –

+1

@KeeperOfTheSoul: Sí, finalmente depende del comportamiento del GC. También depende de si la matriz se serializará o no. Con todo, deseé que Java tuviera una clase SecureString similar a la de Microsoft .Net. –

4

Si crea el hash en el lado del cliente, no debería haber necesidad de pensar sobre este problema. La contraseña simple nunca se envía al servidor.

+0

Sí, ese es un buen enfoque, pero entonces ¿no sería eso también irse? atacantes con la capacidad de estudiar el algoritmo hash en uso? Concedido que es la seguridad a través de la oscuridad en cierto modo, pero limita la cantidad de información disponible para el atacante sobre cómo se almacenan las contraseñas. –

+0

Esa sería una opción, pero ¿un atacante no podría interceptar el hash generado por el cliente también y luego generar nuevamente la misma solicitud HTTP para iniciar sesión? –

+0

@Markus, HTTPS siempre se utiliza, por lo que la probabilidad de un ataque MITM es baja o nula. –

2

Dos palabras: Alcance local. Las variables declaradas para el procesamiento de contraseñas deben tener el alcance más pequeño posible.

Una vez que las variables salen del alcance, los objetos son elegibles para la recolección de basura.

A menudo, usted está recogiendo cosas de una solicitud. Desea una transacción muy, muy pequeña que acepte la solicitud, codifique la contraseña, la persista y redireccione. La página a la que redirige puede obtener contenido y hacer todo el "otro" procesamiento que es parte de su aplicación.

1

No hay forma de garantizar que las contraseñas de texto sin cifrar se eliminen de la memoria en Java.

Sin embargo, un pirata informático no necesita acceder a la memoria de un programa para obtener contraseñas de texto sin cifrar. Hay formas mucho más simples (como olfatear los paquetes) por lo que es muy poco probable que alguien confíe en este enfoque.

El mejor enfoque es hacer que el cliente encripte la contraseña como lo sugiere @Mork0075. Sin embargo, si bien significa que no puede obtener fácilmente la contraseña, un programa puede obtener la versión encriptada de las contraseñas y así pretender ser un usuario. Una forma de evitar esto es encriptar toda la conexión usando SSL.

Todo esto es bastante académico, ya que el enfoque más simple para un hacker es monitorear los paquetes en la base de datos y obtener la contraseña para su base de datos. Sospecho que el acceso directo a su base de datos es más preocupante ... o tal vez no lo es. ;)

+0

Estoy buscando proteger las contraseñas, no porque un atacante intente este enfoque: la caja se ha visto comprometida si puede echar un vistazo a la memoria, por lo que hay cosas más importantes de las que preocuparse. Estoy tratando de evitar que las contraseñas aparezcan en un volcado de pila de Java obtenido para el diagnóstico. –

0

de usar la demanda contraseña:

  1. Server elige un valor desafío y lo envía al cliente
  2. El servidor realiza una traducción de 1 vía con la contraseña y el desafío, por ej. MD5(CONCAT(challenge, password)) y lo asigna a la sesión.
  3. La contraseña de texto sin formato está ahora fuera del alcance y lista para la recolección de basura.
  4. El cliente también realiza la misma traducción y envía el resultado al servidor.
  5. Si el Servidor y el Cliente eligen el mismo valor final, el cliente se autentica.

Este método evita ataques de repetición, pero requiere que el valor desafío a ser muy impredecible (al azar) y no a menudo reutilizado (largo).

La contraseña de texto plano está solo en el alcance durante el manejo de la solicitud de conexión inicial, no durante la autenticación. No importa cuánto tiempo esté en el alcance el resultado de traducción de 1 vía (no basura) porque tiene poco valor de reproducción.

+0

Eso funcionaría bien para el proceso de inicio de sesión, pero el autor solicitó el registro de una cuenta, por lo que también debe almacenar un valor hash en una base de datos. Este hash no se puede generar a través de un valor de desafío, ya que no se pudo restaurar al iniciar sesión. –

5

No utiliza una cadena. Utiliza un char [] y luego sobrescribe el char [] cuando termina.

No hay absolutamente ninguna garantía cuando se trata de recolección de basura (aparte de eso, el finalizador se ejecutará antes de que se recolecte el objeto). Es posible que el GC nunca se ejecute; si se ejecuta, es posible que nunca haga GC en la cadena que tiene la contraseña.

Cuestiones relacionadas