viernes, 21 de septiembre de 2007

Cómo almacenar passwords en una base de datos

A menudo escribimos aplicaciones que deben realizar validación de usuarios y permisos. En estos casos es bastante común que los desarrolladores incluyan campos como 'User' y 'Password' en la tabla de usuarios. También sucede que las contraseñas se guardan en texto plano, lo cual acarrea problemas de seguridad, como veremos a continuación.
Los administradores de la base de datos NO deben tener acceso a las contraseñas. Además, si un atacante logra acceso a la base de datos, va a tener una manera muy fácil de obtener las contraseñas de los usuarios.
Incluso, dependiendo de la configuración de la base de datos, es posible que cuando busquemos "SELECT * FROM USERS WHERE USER='my_user' AND PASSWORD='my_password';", no se valide si la contraseña está en mayúsculas o minúsculas. Esto hace fácil a los atacantes probar distintas contraseñas, ya que no se está validando mayúsculas y minúsculas.
A veces los desarrolladores encriptan las contraseñas aplicando algún algoritmo de encripción. Hay que tener cuidado por los siguientes motivos:
- En general estos algoritmos son bidireccionales, lo cual quiere decir que si tenemos la clave de encripción, se puede obtener la contraseña original a partir del texto cifrado.
- Los buenos algoritmos de encripción son en general conocidos y verificados por la comunidad de programadores y matemáticos. Debes desconfiar de aquellos que ofrecen fórmulas 'mágicas' o que no quieren divulgar la forma de encripción.
Solución:
Lo que debemos hacer es aplicar un algoritmo de hash (ej: SHA, SHA1, SHA2, MD5, etc) a la contraseña para obtener un código a partir del cual no se pueda obtener el texto original. Esto debe hacerse cada vez que el usuario suministra una contraseña, ya sea en el ingreso al sistema, o cuando el usuario modifica su contraseña. Recuerda almacenar en la base de datos el resultado de aplicar el algoritmo de hash a la contraseña suministrada por el usuario.
Cuando busquemos el usuario, la consulta SQL quedaría algo así: "SELECT * FROM USERS WHERE USER='my_user' AND PASSWORD='5eb942810a75ebc850972a89285d570d484c89c4';".
Implicancias: si antes el usuario olvidaba su contraseña, podía pedírsela a los administradores. Ahora, hay que implementar una rutina de blanqueo de contraseñas para estos casos.
Espero que esto ayude.

Saludos!
English version

Technorati tags:

No hay comentarios: