Questão Como o Linux sabe que a nova senha é semelhante à anterior?


Algumas vezes tentei alterar uma senha de usuário em várias máquinas Linux e quando a nova senha era semelhante à antiga, o sistema operacional reclamou que elas eram muito semelhantes.

Eu sempre imaginei, como o sistema sabe disso? Eu pensei que a senha é salva como um hash. Isso significa que, quando o sistema é capaz de comparar a nova senha por semelhança, a antiga é realmente salva como texto simples?


140


origem


Primeiro fora: texto simples? não. Se (!) Salvou você salvar o hash e comparar os hashes. No Linux, ele verifica a senha atual com uma nova senha. Ambos são fornecidos pelo usuário ao alterar as senhas. - Rinzwind
@Rinzwind Mas comparar hashes não funcionará porque uma diferença de um caractere deve resultar em um hash completamente diferente - slhck
Veja também O Facebook armazena senhas de texto simples? em Segurança da Informação para outras maneiras de detectar semelhança, dado apenas o hash da senha antiga e o texto sem formatação da nova senha (sem texto simples para antigo). - Bob
Você pode testar a similaridade entre uma senha antiga com hash e uma nova senha de texto sem formatação. Basta gerar uma lista de senhas semelhante à nova, agrupá-las todas e comparar os hashes resultantes com o antigo hash de senha. Se algum jogo, então é semelhante. - BWG
@BWG: Isso é uma ligeira simplificação - esquemas atuais de hash salgam o hash, então primeiro você tem que extrair o sal do hash de senha antigo e certificar-se de usar esse sal para suas senhas semelhantes a novas. (Estou apontando isso porque é possível que a API não exponha uma maneira de forçar um determinado sal.) - Ulrich Schwarz


Respostas:


Desde que você precisa fornecer tanto o antigo e a nova senha ao usar passwd, eles podem ser facilmente comparados em texto simples, na memória, sem escrevê-los em algum lugar da unidade.

Na verdade, sua senha é criptografada quando é finalmente armazenada, mas até que isso aconteça, a ferramenta onde você está digitando sua senha pode acessá-la diretamente como qualquer outro programa pode acessar as coisas que você digitou no seu teclado enquanto lia STDIN.

Esta é uma característica do Sistema PAM que é usado no fundo do passwd ferramenta. O PAM é usado pelas distribuições modernas do Linux.

Mais especificamente, pam_cracklib é um módulo para o PAM que permite rejeitar senhas com base em vários pontos fracos que os tornariam muito vulneráveis.

Não são apenas senhas que são muito parecidas e podem ser consideradas inseguras. o Código fonte  tem vários exemplos do que pode ser verificado, por ex. se uma senha é um palíndromo ou qual a distância de edição entre duas palavras. A ideia é tornar as senhas mais resistentes aos ataques de dicionário.

Veja também a pam_cracklib manpage.


154



Você tem idéias em "como" sua explicação se encaixa com argumentos relatados na minha resposta? Existem duas abordagens diferentes, tomadas pelo aplicativo "passwd", quando o host é não PAM-aware? P.S .: Nenhum crítico em tudo. Eu só estou querendo saber (como PAM, BTW, foi meu primeiro palpite ... apenas antes de grepping o código-fonte). - Damiano Verzulli
Mais preocupantes são as regras de senha corporativa que o alertam se você usou a mesma senha ou uma senha semelhante entre as quatro últimas. - Nick T
@NickT Como isso é (necessariamente) perturbador - eles não poderiam simplesmente salvar seus últimos 4 hashes, então comparar cada um deles com o seu novo proposto da mesma maneira que esta pergunta? - neminem
@neminem "... ou similar" - Nick T
@NickT Ah, é justo, porque neste caso em particular você está comparando com a "senha antiga" que é inserida pelo usuário para alterar a senha, em vez de contra um hash salvo. Ainda você poderia use hipoteticamente o método BWG postado em um comentário, para pelo menos verificar mudanças realmente simples (uma substituição de caractere, um caractere adicionado / removido, etc.). - neminem


Pelo menos no meu Ubuntu, as mensagens "muito semelhantes" saem quando: "... mais da metade dos personagens são diferentes ..." (veja abaixo para detalhes). graças ao suporte do PAM, conforme explicado claramente na resposta @slhck.

Para outra plataforma, onde o PAM não é usado, as mensagens "muito semelhantes" são exibidas quando: "... mais da metade dos personagens são diferentes ..." (veja abaixo para detalhes)

Para verificar essa declaração por conta própria, é possível verificar o código-fonte. Aqui está como.

O programa "passwd" está incluído no pacote passwd:

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

Como estamos lidando com tecnologias Open Source, temos acesso irrestrito ao código-fonte. Obtê-lo é tão simples como:

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

Depois é fácil encontrar o fragmento relevante do código:

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");

Uma verificação rápida no "obscure.c" mostra isso (estou recortando e colando apenas o trecho relevante do 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;
}

Então, agora, sabemos que há uma função "similar" que, com base na antiga e na nova, verifica se ambas são semelhantes. Aqui está o trecho:

/*
 * 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;
}

Eu não revi o código C. Limitei-me a confiar no comentário antes da definição da função :-)


A diferenciação entre plataformas PAM e não-PAM é definida no arquivo "obscure.c" que é estruturado 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 é uma resposta longa que não parece responder diretamente à questão de como ela pode ser comparada com a senha antiga quando as senhas são criptografadas. - jamesdlin
@jamesdlin: como declarado no comentário de Rinzwind à pergunta original, os hashes fazem NÃO desempenhar qualquer papel nesta questão: quando você emite o comando "passwd" para alterar a senha, é necessário fornecer a senha "antiga" e a senha "nova". Portanto, o código "passwd" não tem problema algum em comparar / verificar a senha de uma só vez (em formulários claros; não em hash). - Damiano Verzulli
@DamianoVerzulli No entanto, isso não resolve a questão. A questão não era "qual código C você usa para dizer se duas strings são semelhantes"; Isso é exatamente o mesmo para senhas como para qualquer outra coisa. A coisa sobre senhas o que os torna interessantes é que eles nunca são armazenados em texto simples, e é sobre isso que a pergunta é feita. Isso responde "quais critérios são usados ​​e como é feito em C", mas é muito longo para "quais critérios" e "como eu faria isso em C" é uma pergunta SO, não uma pergunta SU. - cpast
@DamianoVerzulli E o fato de que passwd pede senhas antigas e novas é a resposta. O resto desta resposta é irrelevante. - jamesdlin
+1 para uma resposta extremamente relevante e interessante! É bom ver que o código real que compara a senha realmente funciona no texto simples e, como esperado, não no hash. - nico


A resposta é muito mais simples do que você pensa. Na verdade, quase se qualifica como mágica, porque uma vez que você explique o truque, ele se foi:

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

Password changed successfully

Ele sabe que sua nova senha é semelhante ... Porque você digitou a antiga em apenas um momento antes.


37



"... ou doce". - Nick T
Coelho parvo, trix são para crianças! - iAdjunct
O que não explica é quando ele conhece as senhas n antigas: "A senha foi usada muito recentemente", o que impede a troca das mesmas poucas senhas em um ambiente corporativo. - Juha Untinen
@Juha Untinen: Isso é verdade, mas isso pode ser feito simplesmente lembrando os últimos N hashes. Capturar "mesmo que a senha Nth" é fácil, é o "semelhante a enésima senha "que é difícil. Tanto quanto sei, estes sistemas só verificam a semelhança com a última senha, e a mesmidade com o último N. Se eles verificarem a similaridade com o último N ... isso é realmente interessante truque agora, não é! Eu não tenho idéia de como eles fariam isso. - Cort Ammon


Embora as outras respostas estejam certas, pode valer a pena mencionar que você não precisa fornecer a senha antiga para que isso funcione!

Na verdade, é possível gerar um monte de senhas semelhantes à nova senha que você forneceu, alterá-las e, em seguida, verificar se algum desses hashes corresponde ao antigo. Se este for o caso, então a nova senha é julgada semelhante à antiga! :)


8



Embora isso seja de fato um meio de alcançar esse feito (e é usado por muitos sites), não é isso que está acontecendo nesta instância. - Brian S
Isso é um truque legal! Um pouquinho mais computacionalmente intensivo, mas inteligente! - Cort Ammon
Você deve pelo menos dar alguma estimativa de quantas senhas semelhantes precisariam ser geradas para ter uma verificação significativa ou vincular a um recurso externo. Caso contrário, isso é apenas uma idéia de alternativa possível, não uma resposta fundamentada. - hyde
@hyde depende dos critérios em que alguém pode pensar. Para mim, as senhas são semelhantes se houver no máximo 3 caracteres adicionados / removidos / modificados. Então, isso é 62 hashes para cada caractere (e isso se usarmos apenas alfanuméricos) vezes combinação de 3 a partir do tamanho da senha (n), qual é 62 * (n!)/(6 * (n - 3)!), o que equivale a 13540 para uma senha de 12 caracteres. Mas se alguém pensa em algo diferente, a equação é inútil, então por que se incomodar? - Killah
Resposta estúpida, mas uma visão, no entanto. Por que estúpido? 1. Você teria que gerar um número inimaginável de hashes. 2. Tal configuração enfraqueceria a segurança da senha original. Se alguém obtivesse hashes de todas as senhas semelhantes em vez de apenas um hash, teria muito mais facilidade para decifrá-lo. - Rok Kralj


Um aspecto não foi coberto: histórico de senhas. Alguns sistemas suportam isso. Para isso, mantém um histórico de senhas e as criptografa com a senha atual. Quando você altera sua senha, ela usa a senha "antiga" para descriptografar a lista e verificar. E quando define uma nova senha, ela salva a lista (novamente) criptografada com uma chave derivada da nova senha.

É assim remember=N trabalha em PAM (armazenado em /etc/security/opasswd). Mas também o Windows e outros fornecedores Unix oferecem funções semelhantes.


4