jueves, 24 de abril de 2014

Hashing de contraseñas en MySQL



Las cuentas de usuario de MySQL se listan en la tabla user de la base de datos mysql . Cada cuenta MySQL tiene una contraseña asiganada, aunque lo que se guarda en la columna Password de la tabla user no es una versión en texto plano de la contraseña, si no un valor hash computado a partir de la misma. Los valores hash de las contraseñas se obtienen a partir de la función PASSWORD() .
MySQL usa contraseñas en dos fases de la comunicación cliente/servidor:
  • Cuando un cliente trata de conectar al servidor, hay un paso inicial de autenticación en el que el cliente debe presentar una contraseña cuyo valor hash coincida con el valor hash almacenado en la tabla user para la cuenta que el cliente quiere usar.
  • Una vez que el cliente conecta, puede (si tiene los suficientes permisos) cambiar o incializar los hashes de las contraseñas para las cuentas listadas en la tabla user . El cliente puede hacerlo mediante la función PASSWORD()para generar el hash de la contraseña, o mediante los comandos GRANT o SET PASSWORD.
En otras palabras, el servidor usa los valores hash durante la autenticación cuando un cliente trata de conectar por primera vez. El servidor genera valores hash si un cliente conectado invoca la función PASSWORD() o usa los comandos GRANT o SET PASSWORD para inicializar o cambiar una contraseña.
El mecanismo de hash de contraseñas se actualizó en MySQL 4.1. para proporcionar una mejor seguridad y para reducir el riesgo de intercepción de contraseñas. Sin embargo, este nuevo mecanismo sólo lo entienden los servidores y clientes MySQL 4.1. (y versiones posteriores), lo cual puede acarrear algunos problemas de compatibilidad. Un cliente 4.1. o posterior puede conectar a un servidor pre-4.1, ya que el cliente entiende los mecanismos de hashing de contraseñas antiguos y nuevos. Sin embargo, un cliente pre-4.1. que trate de conectar a un servidor 4.1. o posterior puede tener problemas. Por ejemplo, un cliente 3.23 mysql que trate de conectar a un servidor 5.0 puede fallar con el siguiente mensaje de error:
shell> mysql -h localhost -u root
Client does not support authentication protocol requested
by server; consider upgrading MySQL client
Otro ejemplo común es cuando se trata de usar la antigua extensión de mysql para PHP tras actualizar a MySQL 4.1 o posterior. (Consulte Sección 24.3.1, “Problemas comunes con MySQL y PHP”.)
La siguiente discusión describe las diferencias entre el antiguo y nuevo mecanismo de contraseñas, y qué debe hacer si actualiza su servidor pero necesita matener compatibilidad con clientes versión pre-4.1. Puede encontrar información adicional en Sección A.2.3, “Client does not support authentication protocol. Esta información es de especial importancia para programadores de PHP que migran de versiones de bases de datos MySQL 4.0 o anteriores a versiones 4.1. o posteriores.
Nota: Esta discusión contrasta el comportamiento 4.1. con el pre-4.1, pero el comportamiento 4.1 descrito aquí realmente empieza en el 4.1.1. MySQL 4.1.0 es una versión ``particular'' ya que tiene mecanismos ligeramente distintos a los implementados en 4.1.1 y posteriormente. Las diferencias entre 4.1.0 y reciones más recientes se describen con más detalle en Manual de referencia de MySQL 4.1.
Antes de MySQL 4.1, los hashes de contraseñas computados por la función PASSWORD() tienen una longitud de 16 bytes. Tales hashes tienen este aspecto:
mysql> SELECT PASSWORD('mypass');
+--------------------+
+--------------------+
| PASSWORD('mypass') | | 6f8c114b58f2ce9e |
+--------------------+
La columna Password de la tabla user (en la que se guardan los hashes) también tiene una longitud de 16 bytes antes de MySQL 4.1.
En MySQL 4.1, la función PASSWORD() se modificó para producir un valor hash más largo de 41-bytes:
mysql> SELECT PASSWORD('mypass');
+-----------------------------------------------+
| PASSWORD('mypass') |
| *43c8aa34cdc98eddd3de1fe9a9c2c2a9f92bb2098d75 |
+-----------------------------------------------+
+-----------------------------------------------+
Por consiguiene, la columna Password en la tabla user debe tener una longitud de 41 bytes para almacenar estos valores:
  • Si realiza una nueva instalación de MySQL 5.0, la columna Password se amplía a 41 bytes automáticamente.
  • Actualizar desde MySQL 4.1 (4.1.1 o posterior en la serie 4.1 ) a MySQL 5.0 no debería afectar a nada de todo esto, ya que ambas versiones usan el mismo mecanismo de hash de contraseñas. Si desea actualizar una versión antorior de MySQL a 5.0, debe actualizar primero a la versión 4.1, y luego actualizar la instalación de 4.1. a 5.0.
Una columna Password más amplia puede almacenar hashes de contraseñas en el antiguo y nuevo formato. El formato de cualquier valor hash de una contraseña puede determinarse de dos formas:
  • La diferencia óbvia es la longitud (16 bytes contra 41 bytes).
  • Una segunda diferencia es que los hashes de contraseñas en el nuevo formato simpre empieza con un carácter '*', mientras que una contraseña en el antiguo formato nunca lo hace.
El hash de la contraseña más larga tiene mejores propiedades criptográficas, y la autenticación de clientes basada en hashes largos es más segura que la basada en los antiguos hashes cortos.
Las diferencias entre hashes cortos y largos son relevantes para cómo el servidor usa las contraseñas durante la autenticación y por cómo genera los hashes de contraseñas para clientes conectados que realizan operaciones de cambio de contraseña.
La forma en que el servidor usa los hashes de contraseñas durante la autenticación se ve afectada por la longitud de la columna Password :
  • Si la columna es corta, sólo se usa autenticación de hash cortos.
  • Si la columna es larga, puede soportar hashes cortos o largos, y el servidor puede usar cualquier formato:
    • Clientes pre-4.1 pueden conectar, aunque sólo conocen el antiguo mecanismo de hash, pueden autenticar sólo para cuentas que tengan hashes cortos.
    • Clientes 4.1 y posterior pueden autenticar para cuentas que tengan hashes cortos o largos.
Para cuentas con hash corto, el proceso de autenticación es un poco más seguro para clientes 4.1 y posteriores que para clientes más antiguos. Respecto a seguridad, el gradienet de menos a más seguro es:
  • Cliente pre-4.1 autenticando con hash de contraseña corto
  • Cliente 4.1 o posterior autenticando con hash de contraseña corto.
  • Cliente 4.1 o posterior autenticando con hash de contraseña largo.
La forma en que el servidor genera los hashes de contraseña para clientes conectados se ve afectado por la longitud de la columna Password y por la opción --old-passwords. Un servidor 4.1. o posterior genera hashes largos sólo si se cumplen ciertas condiciones: La columna Password debe ser lo suficientemente larga para guardar valores largos y no debe darse la opción --old-passwords. Estas condiciones se aplican como sigue:
  • La columna Password debe ser lo suficientemente grande para guardar hashes largos (41 bytes). Si la columna no se ha actualizado y todavía tiene la longitud pre-4.1 de 16 bytes, el servidor entiende que no puede guardar hashes largos y genere sólo hashes cortos cuando un cliente realiza opraciones de cambio de contraseña mediante PASSWORD()GRANT, o SET PASSWORD. Este es el comportamiento que ocurre si ha actualizado a 4.1 pero no ha ejecutado todavía el script mysql_fix_privilege_tables para ensanchar la columna Password .
  • Si la columna Password es amplia, puede almacenar tanto hashes de contraseñas largos como cortos. En este caso, PASSWORD()GRANT, y SET PASSWORD generan hashes largos a no ser que el servidor se haya iniciado con la opción --old-passwords. Este opción fuerza al servidor a generar hashes de contraseñas cortos.
El propósito de la opción --old-passwords es permitirle mantener compatibilidad con clientes anteriores a 4.1 bajo circunstancias donde el servidor generaría hashes de contraseñas largos. La opción no afecta la autenticación (clientes 4.1. y posteriores pueden usar cuentas que tengan hashes largos de contraseña), pero no evita la creación de hashes largos de contraseñas en la tabla user como resultado de una operación de cambio de contraseña. Si eso ocurre, la cuenta no puede usarse por clientes pre-4.1. Sin la opción --old-passwords, es posible el siguiente escenario no deseable:
  • Un cliente viejo trata de conectar a una cuenta que tenga hash de contraseña corto.
  • El cliente cambia su propia contraseña. Sin --old-passwords, esto acaba con la cuenta con un hash de contraseña largo.
  • La siguiente vez que el viejo cliente trate de conectar a la cuenta, no podrá, ya que la cuenta tiene un hash de contraseña largo que requiere un nuevo mecanismo de hash durante la autenticación. (Una vez que una cuenta tiene un hash de contraseña largo en la tabla de usuario, sólo clientes 4.1. y posteriores pueden autenticar, ya que clientes pre-4.1. no entienden hashes largos.)
Este escenario ilustra que, si debe soportar clientes pre-4.1, es peligroso ejecutar un servidor 4.1 o posterior sin usar la opción --old-passwords . Ejecutando el servidor con --old-passwords, las operaciones de cambio de contraseña no generan hashes largos de contraseña y por lo tanto, no provocan que las cuentas sean inaccesibles para clientes antiguos. (Aquellos clientes no pueden bloquearse a ellos mismos mediante el cambio de su contraseña y acabando con un hash de contraseña largo.)
La desventaja de la opción --old-passwords es que cualquier contraseña que cree o cambie usará hashes cortos, incluso para clientes 4.1. Así, pierde la seguridad adicional proporcionada por los hashes de contraseña largos. Si quiere crear una cuenta que tiene un hash largo (por ejemplo, para usar con un cliente 4.1), debe hacerlo mientras el servidor se esté ejecutando sin --old-passwords.
Los siguientes escenarios son posibles al ejecutar un servidor 4.1 o posterior, incluyendo servidores MySQL 5.0:
Escenario 1:Columna Password corta en tabla de usuario:
  • Sólo se pueden guardar hashes cortos en la columna Password .
  • El servidor usa sólo hashes cortos durante la autenticación del cliente.
  • Para clientes conectados, las operaciones de generación de hashes de contraseñas mediante PASSWORD(),GRANT, o SET PASSWORD usan hashes cortos exclusivamente. Cualquier cambio a una contraseña de una cuenta resulta en una cuenta teniendo un hash de contraseña corto.
  • La opción --old-passwords puede usarse pero es supérflua ya que con una columna Password corta, el servidor genera sólo hashes de contraseña cortos de todas formas..
Escenario 2: Columna Password larga; servidor no arrancado con la opción --old-passwords :
  • Hashes cortos o largos pueden almacenarse en la columna Password .
  • Clientes 4.1 y posteriores (incluyendo clientes 5.0) pueden autenticar para cuentas que tengan tanto hashes cortos como largos.
  • Clientes pre-4.1 pueden autenticar sólo para cuentas que tengan hashes cortos.
  • Para clientes conectados, operaciones generadoras de hash como PASSWORD()GRANT, o SET PASSWORD usan hashes largos exclusivamente. Un cambio en la contraseña de una cuenta resulta en dicha cuenta con un hash largo.
Como se ha indicado, un peligro en este escenario es que es posible para cuentas con hash corto quedar inaccesibles para clientes pre-4.1. Un cambio en tales contraseñas hecho via GRANTPASSWORD(), o SET PASSWORD resulta en la cuenta con una contraseña larga. A partir de ahí, ningún cliente pre-4.1 puede autenticar a dicha cuenta hasta que el cliente actualice a 4.1.
Para tratar este problema, puede cambiar una contraseña de forma especial. Por ejemplo, normalmente usa SET PASSWORD como sigue para cambiar una contraseña de cuenta:
mysql> SET PASSWORD FOR 'some_user'@'some_host' = PASSWORD('mypass');
Para cambiar la contraseña pero crear un hash corto, use la función OLD_PASSWORD() en su lugar:
mysql> SET PASSWORD FOR 'some_user'@'some_host' = OLD_PASSWORD('mypass');
OLD_PASSWORD() es útil para situaciones en que explícitamente quiera generar un hash corto.
Escenario 3: Columna Password larga; servidor 4.1 o posterior arrancado con la opción --old-passwords:
  • Hashes crotos o largos pueden guardarse en la columna Password.
  • Clientes 4.1 y posteriores pueden autenticar para cuentas que tengan hashes cortos o largos ( pero tenga en cuenta que es posible crear hashes largos sólo cuando el servidor se arranca sin --old-passwords).
  • Clientes pre-4.1 clients pueden autenticar sólo para cuentas que tengan hashes cortos.
  • Para clientes conectados, operaciones de generación de hashes como PASSWORD()GRANT, o SET PASSWORDusan hashes cortos exclusivamente. Cualquier cambio en la contraseña de una cuenta resulta en que dicha cuenta tenga un hash de contraseña corto.
En este escenario, no puede crear cuentas que tengan hashes de contraseña cortos, ya que la opción --old-passwords evita la generación de hashes largos. También, si crea una cuenta con hashes largos antes de usar la opción --old-passwords, cambiar la contraseña de la cuenta mientras --old-passwords está en efecto resulta en la cuenta teniendo una contraseña corta, causando que se pierdan los beneficios de seguridad de un hash más largo.
Las desventajas de estos escenarios pueden resumirse así:
En el escenario 1, no puede beneficiarse de hashes largos que proporcionan más seguridad de autenticación.
En el escenario 2, las cuentas con hashes cortos son inaccesibles para clientes pre-4.1 si cambia sus contraseñas sin usar explícitamente OLD_PASSWORD().
En el escenario 3, --old-passwords evita que las cuentas con hashes cortos sean inaccesibles, pero las operaciones de cambio de contraseña causa que las cuentas con hashes largos vuelvan a ser hashes cortos, y no puede volver a hacerlos hashes largos mientras --old-passwords tenga efecto.

Fuente:enlace

No hay comentarios:

Publicar un comentario

Entradas populares