Pregunta ¿Cómo sabe Linux que la nueva contraseña es similar a la anterior?


Algunas veces intenté cambiar una contraseña de usuario en varias máquinas Linux y cuando la nueva contraseña era similar a la anterior, el sistema operativo se quejaba de que eran muy similares.

Siempre me pregunté, ¿cómo sabe el sistema esto? Pensé que la contraseña se guarda como un hash. ¿Significa esto que cuando el sistema puede comparar la nueva contraseña por similitud, la anterior se guarda en realidad como texto sin formato?


140


origen


1er apagado: ¿texto simple? no. Si (!) Guardaste guarda el hash y compara los hash. Sin embargo, en Linux comprueba la contraseña actual con una nueva contraseña. AMBOS son provistos por el usuario cuando cambia las contraseñas. - Rinzwind
@Rinzwind Pero comparar hashes no funcionará porque una diferencia de un carácter debería resultar en un hash completamente diferente - slhck
Ver también ¿Facebook almacena contraseñas de texto sin formato? en Seguridad de información para otras formas de detectar similitudes, dado solo el hash de la contraseña anterior y el texto sin formato de la nueva contraseña (no texto sin formato para el anterior). - Bob
De hecho, puede probar la similitud entre una contraseña antigua hash y una nueva contraseña de texto simple. Simplemente genere una lista de contraseñas similar a la nueva, cópielas todas y compare los hashes resultantes con el hash de contraseña anterior. Si hay alguna coincidencia, entonces es similar. - BWG
@BWG: Esa es una pequeña simplificación excesiva: los esquemas de hashing actuales sacan el hash, así que primero tienes que extraer la sal del antiguo hash de contraseñas y asegurarte de usar esa sal para tus contraseñas similares a las nuevas. (Señalo esto porque es posible que la API no exponga una forma de forzar una sal específica). - Ulrich Schwarz


Respuestas:


Dado que necesita suministrar tanto el viejo y la nueva contraseña cuando se usa passwd, se pueden comparar fácilmente en texto plano, en memoria, sin escribirlos en algún lugar de la unidad.

De hecho, su contraseña se codifica cuando finalmente se almacena, pero hasta que eso suceda, la herramienta donde ingresa su contraseña puede acceder directamente, como cualquier otro programa, puede acceder a las cosas que ingresó en su teclado mientras estaba leyendo STDIN.

Esta es una característica de Sistema PAM que se utiliza en el fondo de la passwd herramienta. PAM es utilizado por las distribuciones de Linux modernas.

Más específicamente, pam_cracklib es un módulo para PAM que permite rechazar contraseñas basadas en varias debilidades que los harían muy vulnerables.

No son solo las contraseñas que son demasiado similares y que pueden considerarse inseguras. los código fuente  tiene varios ejemplos de lo que se puede verificar, p. si una contraseña es un palíndromo o cuál es la distancia de edición entre dos palabras. La idea es hacer que las contraseñas sean más resistentes a los ataques de diccionario.

Ver también el pam_cracklib Manpage.


154



¿Tiene ideas sobre "cómo" su explicación se ajusta a los argumentos informados en mi respuesta? ¿Hay dos enfoques diferentes, tomados por la aplicación "passwd", cuando el host es no PAM-consciente? P.S .: Sin críticas en absoluto. Me pregunto (como PAM, por cierto, fue mi primera suposición ... justo antes de guardar el código fuente). - Damiano Verzulli
Más inquietantes son las reglas de contraseña corporativa que le avisan si ha utilizado la misma contraseña o una similar entre cualquiera de los cuatro últimos. - Nick T
@NickT ¿Cómo es eso (necesariamente) perturbador? ¿No podrían simplemente guardar sus últimos 4 hash, y luego comparar cada uno de ellos con el nuevo propuesto de la misma manera que esta pregunta? - neminem
@neminem "... o similar" - Nick T
@NickT Ah, es justo, porque en este caso particular está comparando con la "contraseña anterior" que ingresa el usuario para cambiar la contraseña, en lugar de contra un hash guardado. Todavia tu podría hipotéticamente use el método BWG publicado en un comentario, para al menos verificar cambios realmente simples (una sustitución de personaje, un personaje agregado / eliminado, etc.). - neminem


Al menos en mi Ubuntu, los mensajes "muy similares" salen cuando: "... más de la mitad de los personajes son diferentes ..." (ver más abajo para más detalles). gracias al soporte PAM, como se explica claramente en la respuesta @slhck.

Para otra plataforma, donde no se utiliza PAM, los mensajes "demasiado similares" aparecen cuando: "... más de la mitad de los personajes son diferentes ..." (ver más abajo para más detalles)

Para verificar más a fondo esta afirmación, es posible verificar el código fuente. Aquí es cómo.

El programa "passwd" está incluido en el paquete passwd:

verzulli@iMac:~$ which passwd
/usr/bin/passwd
verzulli@iMac:~$ dpkg -S /usr/bin/passwd
passwd: /usr/bin/passwd

Al tratar con tecnologías de código abierto, tenemos acceso sin restricciones al código fuente. Obtenerlo es tan simple como:

verzulli@iMac:/usr/local/src/passwd$ apt-get source passwd

Luego es fácil encontrar el fragmento de código relevante:

verzulli@iMac:/usr/local/src/passwd$ grep -i -r 'too similar' .
[...]
./shadow-4.1.5.1/NEWS:- new password is not "too similar" if it is long enough
./shadow-4.1.5.1/libmisc/obscure.c:     msg = _("too similar");

Una comprobación rápida de "obscure.c" da esto (estoy cortando y pegando solo la parte relevante del código):

static const char *password_check (
    const char *old,
    const char *new,
    const struct passwd *pwdp)
{
    const char *msg = NULL;
    char *oldmono, *newmono, *wrapped;

    if (strcmp (new, old) == 0) {
            return _("no change");
    }
    [...]
    if (palindrome (oldmono, newmono)) {
            msg = _("a palindrome");
    } else if (strcmp (oldmono, newmono) == 0) {
            msg = _("case changes only");
    } else if (similar (oldmono, newmono)) {
            msg = _("too similar");
    } else if (simple (old, new)) {
            msg = _("too simple");
    } else if (strstr (wrapped, newmono) != NULL) {
            msg = _("rotated");
    } else {
    }
    [...]
    return msg;
}

Por lo tanto, ahora sabemos que existe una función "similar" que, en función de la antigua y la nueva comprobación, ambas son similares. Aquí está el fragmento:

/*
 * more than half of the characters are different ones.
 */
static bool similar (const char *old, const char *new)
{
    int i, j;

    /*
     * XXX - sometimes this fails when changing from a simple password
     * to a really long one (MD5).  For now, I just return success if
     * the new password is long enough.  Please feel free to suggest
     * something better...  --marekm
     */
    if (strlen (new) >= 8) {
            return false;
    }

    for (i = j = 0; ('\0' != new[i]) && ('\0' != old[i]); i++) {
            if (strchr (new, old[i]) != NULL) {
                    j++;
            }
    }

    if (i >= j * 2) {
            return false;
    }

    return true;
}

No he revisado el código C. Me limité a confiar en el comentario justo antes de la definición de la función :-)


La diferenciación entre plataformas PAM y NO PAM conscientes se define en el archivo "obscure.c" que está estructurado como:

#include <config.h>
#ifndef USE_PAM
[...lots of things, including all the above...]
#else                           /* !USE_PAM */
extern int errno;               /* warning: ANSI C forbids an empty source file */
#endif                          /* !USE_PAM */

45



Esta es una respuesta larga que no parece responder directamente a la pregunta de cómo se puede comparar con la contraseña anterior cuando las contraseñas son hash. - jamesdlin
@jamesdlin: como se indica en el comentario de Rinzwind a la pregunta original, hash hace NO desempeñar un papel en este asunto: cuando se emite el comando "passwd" para cambiar la contraseña, se le solicita que proporcione la contraseña "vieja" y la "nueva". Por lo tanto, el código "passwd" no tiene ningún problema al comparar / verificar ambas contraseñas de una vez (en formas claras, no en hash). - Damiano Verzulli
@DamianoVerzulli Sin embargo, esto realmente no aborda la cuestión. La pregunta no era "¿qué código C usas para decir si dos cadenas son similares?" eso es exactamente lo mismo para las contraseñas que para cualquier otra cosa. Lo que pasa contraseñas eso los hace interesantes es que nunca se almacenan en texto plano, y eso es lo que la pregunta plantea. Esto responde "qué criterios se usan y cómo se hace en C", pero es demasiado tiempo para "qué criterios" y "cómo lo haría en C" es una pregunta SO, no una cuestión SU. - cpast
@DamianoVerzulli Y el hecho de que passwd pide contraseñas viejas y nuevas es la respuesta. El resto de esta respuesta es irrelvant. - jamesdlin
+1 para una respuesta extremadamente relevante e interesante! Es agradable ver que el código real que compara la contraseña realmente funciona en el texto plano y, como se esperaba, no en el hash. - nico


La respuesta es mucho más simple de lo que piensas. De hecho, casi califica como mágico, porque una vez que explicas el truco, ya no está:

$ passwd
Current Password:
New Password:
Repeat New Password:

Password changed successfully

Sabe que su nueva contraseña es similar ... Porque usted escribió la antigua en un momento anterior.


37



"... o dulces". - Nick T
Conejo tonto, trix son para niños! - iAdjunct
Lo que no explica es cuando conoce tus contraseñas pasadas :) "La contraseña se ha utilizado demasiado recientemente", lo que impide intercambiar las mismas pocas contraseñas en un entorno corporativo. - Juha Untinen
@Juha Untinen: Eso es cierto, pero eso se puede manejar simplemente recordando los últimos N hashes. Capturar "lo mismo que la Nth contraseña" es fácil, es el "similar hasta la Nth contraseña "eso es difícil. Hasta donde yo sé, estos sistemas solo verifican la similitud con la última contraseña, y la igualdad con la última N. Si lo hacen verifican la similitud con la última N ... eso es realmente interesante truco ahora, ¿no? No tengo idea de cómo lo harían. - Cort Ammon


Aunque las otras respuestas son correctas, puede valer la pena mencionar que no necesita proporcionar la contraseña anterior para que esto funcione.

De hecho, uno puede generar un grupo de contraseñas similar a la nueva contraseña que usted suministró, hash, y luego verificar si alguno de estos valores hash coincide con el anterior. Si este es el caso, ¡la nueva contraseña se juzga de manera similar a la anterior! :)


8



Si bien este es un medio para lograr esta hazaña (y lo usan muchos sitios web), eso no es lo que sucede en este caso. - Brian S
Ese es un buen truco! Un poco más intensivo computacionalmente, ¡pero listo! - Cort Ammon
Al menos debe dar una estimación de cuántas contraseñas similares deberían generarse para tener una verificación significativa o un enlace a un recurso externo. De lo contrario, esto es solo una idea de una posible alternativa, no una respuesta justificada. - hyde
@hyde que depende de criterios que alguien pueda pensar. Para mí, las contraseñas son similares si se agregaron / eliminaron / modificaron un máximo de 3 caracteres. Así que eso es 62 hashes para cada personaje (y eso si solo usamos alfanuméricos) por combinación de 3 desde la longitud de la contraseña (n), cual es 62 * (n!)/(6 * (n - 3)!), que equivale a 13540 para una contraseña de 12 caracteres de longitud. Pero si alguien piensa en algo diferente, la ecuación es inútil, entonces, ¿para qué molestarse? - Killah
Respuesta estúpida, pero una idea sin embargo. ¿Por qué estúpido? 1. Tendría que generar una cantidad inimaginable de hashes. 2. Tal configuración debilitaría la seguridad de la contraseña original. Si alguien obtiene hash de todas las contraseñas similares en lugar de solo un hash, tendrían mucho más fácil tiempo para descifrarlo. - Rok Kralj


Un aspecto no fue cubierto: historial de contraseñas. Algunos sistemas apoyan esto. Para hacer eso, mantiene un historial de contraseñas y las encripta con la contraseña actual. Cuando cambia su contraseña, usa la contraseña "anterior" para descifrar la lista y verificarla. Y cuando establece una nueva contraseña, guarda la lista (nuevamente) encriptada con una clave derivada de la nueva contraseña.

Así es como remember=N funciona en PAM (almacenado en /etc/security/opasswd) Pero también Windows y otros proveedores de Unix ofrecen funciones similares.


4