¿Cómo guardar las contraseñas en aplicaciones?

guardar las contraseñas

A la hora de crear una nueva aplicación multiusuario siempre llega el momento de manejar contraseñas para gestionar el acceso de los usuarios a la misma. En estos momentos llega la pregunta de cómo guardar las contraseñas de una forma que sea segura y confiable para los usuarios. En esta entrada se presentarán algunos de los métodos incorrectos más utilizados y se explicará una forma segura de realizar esta tarea.

Objetivos de la entrada

Antes de continuar es importante acotar el alcance de la entrada. En esta se explicará cómo guardar las contraseñas en aplicaciones multiusuario. En las que el usuario de ha de identificar mediante un par usuario y contraseña. La aplicación solamente necesita saber que la contraseña introducida es la correcta o no. En ningún momento será necesario recuperar la contraseña para utilizar en otro servicio. Es decir, no se va a implementar un llavero sino un control de acceso. En el caso de los llaveros la única forma segura de guardar las contraseñas es encriptando las mismas.

Por otro lado, también es necesario definir que vamos a entender por guardar los datos de forma segura. En esta ocasión entendemos que las contraseñas se almacenan de forma seguirá si un atacante que accede al sistema y obtienen los datos no puede recuperar las contraseñas utilizadas por los usuarios.

Métodos inadecuados para guardar contraseñas

Inicialmente, en esta primera sección se describirán dos métodos inadecuados muy utilizados. Por lo que no han de ser empleados para guardar contraseñas en una aplicación. Concretamente se explicarán porque no utilizar: texto plano y encriptado.

Texto plano

Uno de los métodos más sencillos de implementar es un archivo en el que se guardan los datos en texto plano. Permitiendo la lectura sin problemas de los pares usuario-contraseña. En este caso es fácil comprobar que si un atacante obtiene el archivo obtendrá automáticamente los datos. Esto le permitiría utilizar esta información para acceder a las cuentas de todos los usuarios y suplantar su identidad.

Encriptado

La primera idea después de ver esto es encriptar el archivo. A pesar de utilizar un algoritmo seguro esto no es una buena idea. Un atacante obtendrá un archivo encriptado del que no podrá obtener directamente las contraseñas. Pero posiblemente no sea difícil obtener esta información indirectamente.

A pesar de parecer una buena idea tiene un punto débil. La palabra utilizada para encriptar los datos ha de estar disponible para poder validar las cuentas. En tal caso es altamente probable que el atacante puede obtener esta palabra fácilmente. Buscándola en la base de datos o el código. Permitiéndole así obtener también el listado de las contraseñas.

En el improbable caso de que no obtenga también la palabra, mediante un ataque de fuerza bruta podrá obtener todas las contraseñas. Dificultado solamente un poco su objetivo.

Guardado seguro de contraseñas

Después de ver las técnicas poco recomendables se puede ver otra más fiable. Una que responda a la pregunta cómo guardar contraseñas de forma segura. Un método básico es guardar el código hash en lugar de la contraseña. Es decir, guardar una transformación una transformación de la contraseña. En una entrada anterior se explico algunas de sus propiedades de las funciones hash. Una de las más importantes para lo que nos afecta es que no son reversibles. Por lo que, a partir de un código hash no existe manera directa de obtener el conjunto de datos original.

Así para poder validar usuarios solamente se ha de guardar el nombre de usuarios y el código hash de contraseña. En un entorno así construido, la validación de un usuario no es más complicada que cuando las contraseñas se guardan en texto plano. Simplemente cuando el usuario introduce su par de palabras usuario y contraseña se ha de calcular el código hash de la segunda. En este punto es necesario comprobar si el par de palabras usuario y hash existe. En caso afirmativo se ha validado la identidad del usuario, mientras que en caso negativo se ha de denegar el acceso.

Por lo que, en este escenario un atacante que obtenga el archivo con los pares usuario y hash no puede recuperar directamente las contraseñas. Únicamente puede intentar obtener contraseñas mediante un ataque de fuerza bruta en el que pruebe contraseñas hasta que encuentre alguna que genere alguno de los códigos hash existentes. En este punto la dificultad del ataque depende de las contraseñas utilizadas por los usuarios. Aunque se puede complicar algo mas las cosas como se explica a continuación.

Mejoras a las funciones de hash

Existen dos técnicas que permiten complicar la obtención por fuerza bruta de las contraseñas, agregando a las contraseñas lo que se llama sal y pimienta.

Pimienta y sal

Sal

La complejidad de las contraseñas se puede aumentar utilizando una cadena aleatoria, diferente para cada uno de los usuarios, que se concatena a la contraseña antes de obtener el hash. Así, aunque dos usuarios tengan la misma contraseña, el hash en la base de datos será diferente. Evitando que el atacante pueda realizar un ataque genérico para encontrar las contraseñas de los usuarios, viéndose obligado a realizar un ataque diferente por usuario.

A la hora de guardar las contraseñas se ha de modificar el proceso ligeramente. En lugar de guardar el hash de la contraseña se guardará tanto la sal como en hash de la sal y la contraseña. Los pasos necesarios para validar la contraseña de un usuario al utilizar sal requieren los siguientes pasos:

  1. Solicitar el nombre de usuario y contraseña
  2. Comprobar si el usuario existe, en caso afirmativo obtener la sal y en caso negativo denegar el acceso
  3. General el código hash de código de la sal y la contraseña
  4. Comprobar si el código hash coincide con el almacenado, en caso afirmativo se valida el usuario, en caso negativo se deniega el acceso.

Debido a que el valor de la sal es diferente para cada usuario este se ha de almacenar junto al nombre de usuario y el hash de la contraseña. Aunque el atacante conozca el valor de la sal que se añade a la contraseña no es un problema ya que se ha aumentado la complejidad del ataque necesario para obtener las contraseñas.

Pimienta

Un segundo paso para aumentar la dificultad de los ataques es agregar una segunda cadena aleatoria de un conjunto que se ha generado previamente. Esta es la que se suele llamar pimienta.  Al agregar una segunda cadena un ataque por diccionario ha de probar tantas combinaciones como valores de pimienta exista. Multiplicando el coste de un ataque por fuerza bruta.

El proceso para guardar las contraseñas aumenta en complejidad con este método. Inicialmente se ha de generar un conjunto de pimientas y se han de guardar de forma que sea fácilmente recuperables. Una vez un usuario guarda una contraseña se escoge un valor de la pimienta al azar y se concatena con la contraseña para obtener un código hash. El proceso de validación requiere ahora los siguientes pasos:

  1. Solicitar el nombre de usuario y contraseña
  2. Obtener todos los posibles valores de la pimienta
  3. General el código hash de código hash de la contraseña con todas las pimientas
  4. Comprobar si alguno de los códigos obtenidos coincide con el almacenado, en caso afirmativo se valida el usuario, en caso negativo se deniega el acceso 

Combinación de pimienta y sal

Obviamente, la combinación de los métodos permite obtener un nivel mayor de seguridad que utilizar solamente uno de ellos por separado. Al combinar ambos, generalmente la sal se suele añadir antes de la contraseña y la pimienta después. Calculando los códigos hash de la cadena que se obtenga de concatenar: sal + contraseña + pimienta.

Conclusiones

En esta entrada se ha presentado un método más seguro que la encriptación para guardar las contraseñas de los usuarios a la hora de crear una aplicación. La combinación de las técnicas descritas en esta entrada permite mejorar considerablemente la seguridad de nuestros sistemas.

Sin votos
Por favor espera...
Etiquetas:

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *