¿Reemplazar un hash bcrypt con un hash no válido no da como resultado una contraseña de trabajo posible?

38

Tengo un administrador al que le gusta "desactivar" las cuentas al reemplazar el hash bcrypt existente en la base de datos con un guión simple ( - ).

Estoparecefuncionaryaquelacontraseñaanterioryanoesválidaynohayunhashbcryptválidoquepuedacoincidirconcualquierotracontraseña.Peroteníacuriosidad,¿esestoefectivoocreaunriesgodeseguridad?

¿Esestaunaformaefectivadehacerquenofuncionelacontraseñaocreaunmayorriesgodeseguridad?

EstaimplementaciónespecíficautilizalafunciónPHP password_verify pero me gustaría que las respuestas se centren en cualquier Implementación general. Por favor, no se centre en la mala práctica de mi gerente. También tenemos un campo booleano para configurar al usuario como inactivo / activo, que creo que es mejor y más seguro, pero no es en lo que quiero que se centren las respuestas.

    
pregunta Markus Tenghamn 11.06.2018 - 10:36
fuente

7 respuestas

40

En términos de no permitir intentos de inicio de sesión legítimos, está bien. A menos que esté usando una función hash muy extraña, no habrá ningún valor que se asigne a - , y previene los ataques de fuerza bruta contra los valores faltantes si la base de datos también es robada, lo cual es positivo (era poco probable) , dado el uso de bcrypt, pero esto se aplica incluso si la implementación está utilizando un método terrible para almacenar contraseñas (casi cualquier otra cosa que no sea texto sin formato).

En términos de desventajas, si se toma la base de datos, disminuye ligeramente la seguridad de otras cuentas: el atacante tiene menos registros que la fuerza bruta. Si prestan atención, probablemente deberían eliminar los registros que están marcados como inactivos, pero aún así. Dije "ligeramente" ...

Los otros riesgos podrían ser si hay algún método de acceso que permita omitir el método hash para la comparación (por ejemplo, tiene un método heredado que permite suministrar el hash completo por alguna razón), en ese caso, si no lo está. comprobando el estado activo con cuidado, podría permitir el acceso proporcionando un guión. Lo ideal es eliminar este método de acceso, si este es el caso.

    
respondido por el Matthew 11.06.2018 - 10:52
fuente
18

Un hash de contraseña no válido (generalmente "*") realmente deshabilita la autenticación de la contraseña, ya que realmente no hay manera de proporcionar un valor que lo haga. Sin embargo, un hash de contraseña no válido no "desactiva" la cuenta si existen otros métodos de autenticación, por ejemplo. por clave privada ssh. De hecho, esta es una forma común de imponer la autenticación de solo clave: una contraseña no válida en combinación con una clave pública ssh en ~user/.ssh . Por lo tanto, un hash no válido en la columna de contraseña no debe interpretarse como "cuenta inactiva", sino "autenticación de contraseña bloqueada".

Si el acceso con contraseña es la única ruta disponible, un hash no válido es posiblemente superior al marcado explícito porque no necesita soporte de software: si /etc/password tenía una columna activeuser y lo usé mientras dejaba una contraseña válida en el campo de contraseña, algunas herramientas podrían ignorar el campo activeuser .

    
respondido por el alexis 11.06.2018 - 12:29
fuente
6

Ciertamente, una gran diferencia es que un usuario marcado como "inactivo" aún podría iniciar sesión, excepto su servidor busca el indicador y maneja el intento correctamente. Además, la bandera puede eliminarse, restaurando efectivamente el estado original, mientras que cambiar el hash a "-" no se puede restaurar sin guardar el hash de contraseña en otro lugar. Dependiendo de su aplicación, este puede ser o no el comportamiento deseado.

Este enfoque no crea un riesgo de seguridad, ya que un atacante con acceso a su base de datos podría simplemente ver que este usuario no debe poder iniciar sesión. Como se indicó correctamente, ningún hash bcrypt puede coincidir "- ", como el formato solo no coincide.

Como Schroeder declaró en los comentarios, esto no es una mala práctica, sino un concepto común para evitar que los usuarios inicien sesión, sin modificar el mecanismo de inicio de sesión para tener en cuenta su indicador "inactivo" (los usuarios inactivos que intentan iniciar sesión son rechazados implícitamente).

    
respondido por el GxTruth 11.06.2018 - 10:51
fuente
6

El propósito de los hashes seguros es dificultar la fuerza bruta de las contraseñas en la base de datos. Si es posible descifrar, o incluso adivinar, la contraseña del "hash simple", entonces las contraseñas de las cuentas están en riesgo.

Pero, esa no es toda la historia. Si el propósito es simplemente invalidar a alguien para que no pueda usar o adivinar la contraseña desde el lado del cliente, entonces funciona bien. Este método se ha utilizado durante mucho tiempo. Pero las entradas de contraseña en el back-end se debilitan. Esto podría estar bien si hay otros controles, y los riesgos e impactos del compromiso de la cuenta son bajos.

    
respondido por el schroeder 11.06.2018 - 10:51
fuente
5

Esta es otra en la misma línea que otras respuestas, así que permítame reiterar primero el punto principal: esta puede ser una forma efectiva de invalidar a los usuarios siempre que no haya otras formas de . Como ejemplo a tener en cuenta:

¿Cómo maneja tu sistema a los usuarios registrados? Presumiblemente, una vez que un usuario inicia sesión en su sistema, los recuerda hasta que se desconecta, probablemente con cookies / sesiones. ¿Qué almacena en la sesión para asegurarse de que su usuario permanezca conectado? Lo que es más importante, ¿qué sucede si un usuario inicia sesión y luego se invalida su hash de contraseña? Si está almacenando la contraseña en la sesión, se cerrará la sesión inmediatamente, pero sería una mala idea almacenar la contraseña en la sesión. Si almacena el hash de contraseña en la sesión, también se desconectará de inmediato. Sin embargo, si en la sesión simplemente registra el hecho de que han iniciado sesión y el ID del usuario con el que han iniciado sesión, la invalidación del hash no desconectará automáticamente a los usuarios que hayan iniciado sesión actualmente. Lo consideraría un problema, especialmente si tiene sesiones de larga duración. ¿Qué pasa si desactivas el hash de alguien y una semana después abren su navegador y todavía estás conectado de todas formas? Esto es peor si la función "Actualizar contraseña" que proporciona a los usuarios no requiere que valide sus contraseñas antiguas. En ese caso, alguien que ya haya iniciado sesión podrá permanecer conectado cuando desactive su hash y luego podrá cambiar su contraseña y recuperar un hash válido, reactivando su cuenta.

También ten cuidado con las claves API. Algunos sistemas (Gitlab obtuvo algunas dificultades para hacer esto antes de cambiar sus sistemas) tienen claves API de larga duración que se utilizan para el acceso a la API. Un usuario que conoce su clave de API podría seguir usando el sistema incluso si se cambia su hash de contraseña.

Dado el concepto general de defensa en profundidad, personalmente votaría por tener un procedimiento de desactivación "formal" en su sistema (normalmente, solo tengo una columna de estado en la tabla de usuarios que se verifica durante el proceso de autenticación / permiso normal). Después de todo, puede haber muchas advertencias que podrían hacer que un usuario con un hash desactivado aún pueda utilizar el sistema. Por supuesto, la seguridad es siempre un enfoque de costo / beneficio para cada entidad, por lo que si agregar un indicador de desactivación formal toma mucho tiempo para su sistema, y ninguna de las vías de "ataque" en las respuestas aquí le son aplicables, entonces usted es probablemente bien.

    
respondido por el Conor Mancone 11.06.2018 - 14:34
fuente
3

Sí, esa es la forma estándar en Unix, y lo ha sido durante siglos.

La página del manual shadow (5) responde a su pregunta explícitamente:

       If the password field contains some string that is not a valid
       result of crypt(3), for instance ! or *, the user will not be
       able to use a unix password to log in (but the user may log in
       the system by other means).

Hay trucos adicionales, por ejemplo, passwd (1) tiene una opción --lock :

   -l, --lock
       Lock the password of the named account. This option disables a
       password by changing it to a value which matches no possible
       encrypted value (it adds a ´!´ at the beginning of the password).

       Note that this does not disable the account. The user may still
       be able to login using another authentication token (e.g. an SSH
       key). To disable the account, administrators should use usermod
       --expiredate 1 (this set the account's expire date to Jan 2,
       1970).

       Users with a locked password are not allowed to change their
       password.
    
respondido por el Simon Richter 13.06.2018 - 08:09
fuente
2

Lo primero que se debe tener en cuenta es que un "hash de contraseña" no es simplemente un hash de la contraseña, es una estructura de varios campos que contiene no solo el hash en sí, sino una indicación de qué esquema de hash se utiliza y de cualquier parámetro necesario. (en el caso de bcrypt un parámetro de sal y un costo)

Por lo tanto, la respuesta a la pregunta de si un "hash de contraseña" no válido da como resultado que no haya contraseñas que funcionen no tiene nada que ver con las funciones de hash, se reduce a cómo el código de verificación maneja las entradas que no representan un hash de contraseña válido en una. de los formatos soportados. Uno esperaría que considerara un hash no válido como no coincidente, pero la documentación no está clara, por lo que necesitamos leer la fuente.

enlace

enlace

Al leer el código de php's password_verify, encontramos que primero llama "php_password_determine_algo", si la contraseña comienza con $ 2y $ se considera "bcrypt", si comienza con "$ argon2i $" se considera argon2 De lo contrario, se considera "desconocido".

Si el hash es "bcrypt" o "desconocido", entonces pasa a llamar a php_crypt y le pasa la contraseña y el hash, esto intenta hacer un hash de la contraseña proporcionada usando el método y salt de la contraseña existente, puede hacer esto mediante el uso de una implementación interna o llamando a la función de cifrado del sistema operativo. Parece que dado un hash existente no válido, el código interno retrocederá al DES de la vieja escuela, sin estar seguro de lo que hará la implementación del sistema.

Volviendo a la sección unknown / bcrypt en password_verify, parece que no podrá coincidir si se cumple alguna de las siguientes condiciones.

  1. php_crypt devuelve un error.
  2. la longitud del hash devuelto por php_crypt no coincide con la longitud del hash con contraseña para password_verify
  3. el hash pasado a password_verify tiene menos de 13 caracteres de longitud
  4. el contenido del hash devuelto por php_crypt no coincide con el contenido del hash pasado a password_verify

Su hash de "-" será rechazado por al menos la regla 3 de esta lista (probablemente también las reglas 1 o 2, pero eso depende del comportamiento de la implementación de criptografía utilizada).

    
respondido por el Peter Green 12.06.2018 - 07:15
fuente

Lea otras preguntas en las etiquetas