Pergunta

Eu estava procurando por um algoritmo eficaz que pode me dar uma idéia exata de quão forte é a senha.

descobri que vários sites diferentes usar vários algoritmos diferentes que eu conseguir diferentes ratings de força senha em sites diferentes.

Foi útil?

Solução

Este tem crescido ao meu despejo geral cérebro das melhores práticas para trabalhar com senhas em PHP / MySQL. As idéias apresentadas aqui geralmente não são minhas, mas o melhor que eu encontrei até agora.


Certifique-se de que você está usando SSL para todas as operações envolvendo informações do usuário. Todas as páginas que envolvem essas formas devem verificar se estão sendo chamados via HTTPS, e se recusam a trabalhar de outra forma.

Você pode eliminar a maioria dos ataques, simplesmente limitando o número de logins falhos permitidos.

Permitir senhas relativamente fracos, mas armazenar o número de logins falhos por usuário e requerem uma verificação captcha ou senha por e-mail se você ultrapassá-lo. Eu definir minhas falhas max a 5.

Apresentando falhas de login para o usuário precisa de ser cuidadosamente pensado para não fornecer informações para os agressores. Um início de sessão falhou devido a um usuário inexistente deve retornar a mesma mensagem como um login falhou devido a uma senha incorreta. Fornecendo uma mensagem diferente vai permitir que atacantes para determinar logins de usuário válidas.

Certifique-se também retornar exatamente a mesma mensagem em caso de um fracasso para muitos logins com uma senha válida, e um fracasso com muitos logins e uma senha inválida. Fornecendo uma mensagem diferente vai permitir que atacantes para determinar as senhas de usuário válidas. Um bom número de utilizadores quando é forçado a redefinir sua senha simplesmente colocá-lo de volta para o que era.

Infelizmente limitando o número de logins permitidos por endereço IP não é prático. Vários provedores como AOL ea maioria das empresas de proxy seus pedidos web. Impondo esse limite será efetivamente eliminar esses usuários.


Eu encontrei a verificação de palavras do dicionário antes de submeter-se ineficaz como quer você tem que enviar um dicionário para o cliente em javascript, ou enviar uma solicitação ajax, por mudança de campo. Eu fiz isso por um tempo e ele funcionou ok, mas não o fez como o tráfego que gerou.

Verificação de senhas inerentemente fracos menos palavras do dicionário é o lado prático cliente com algum javascript simples.

Depois de enviar, eu buscar por palavras do dicionário, e nome de usuário contendo senha e vice-versa lado do servidor. Muito bons dicionários são facilmente descarregáveis ??e os testes contra eles é simples. Uma pegadinha aqui é que para testar uma palavra de dicionário, você precisa enviar uma consulta no banco de dados, que por sua vez contém a senha. A maneira que eu tenho em torno deste foi para criptografar meu dicionário antes da mão com uma criptografia simples e acabam SALT posicionado e, em seguida, teste para a senha criptografada. Não é o ideal, mas melhor do que texto simples e única no fio para as pessoas em suas máquinas físicas e sub-rede.

Uma vez que você está feliz com a senha que você escolheu criptografá-lo com PHP em primeiro lugar, em seguida, armazenar. A seguinte função de criptografia de senha não é minha idéia também, mas resolve uma série de problemas. Criptografar dentro PHP impede as pessoas em um servidor compartilhado de interceptar suas senhas não criptografadas. Adicionando algo por usuário que não vai mudar (eu uso e-mail como este é o nome de usuário para meus sites) e adicionar um hash (SALT é uma pequena cadeia constante I mudança por site) aumenta a resistência a ataques. Porque o SALT está localizado dentro da senha, e a senha pode ser de qualquer comprimento, torna-se quase impossível para atacar isso com uma tabela do arco-íris. Alternadamente Isso também significa que as pessoas não podem mudar seu e-mail e você não pode mudar o SALT sem invalidar a senha de todos embora.

EDIT: Eu agora recomendo usar PhPass em vez do meu rolo de sua própria função aqui, ou apenas esquecer logins de usuário completamente e usar OpenID .

function password_crypt($email,$toHash) {
  $password = str_split($toHash,(strlen($toHash)/2)+1);
  return hash('sha256', $email.$password[0].SALT.$password[1]); 
}

Meu Jqueryish metros senha lado do cliente. -Alvo deve ser uma div. É de largura vai mudar entre 0 e 100 e cor de fundo irá mudar de acordo com as classes denotado in o script. Novamente principalmente roubado de outras coisas que eu encontrei:

$.updatePasswordMeter = function(password,username,target) {
$.updatePasswordMeter._checkRepetition = function(pLen,str) {
res = ""
for ( i=0; i<str.length ; i++ ) {
    repeated=true;
    for (j=0;j < pLen && (j+i+pLen) < str.length;j++)
        repeated=repeated && (str.charAt(j+i)==str.charAt(j+i+pLen));
    if (j<pLen) repeated=false;
    if (repeated) {
        i+=pLen-1;
        repeated=false;
    }
    else {
        res+=str.charAt(i);
    };
};
return res;
};
var score = 0;
var r_class = 'weak-password';
//password < 4
if (password.length < 4 || password.toLowerCase()==username.toLowerCase()) { 
target.width(score + '%').removeClass("weak-password okay-password good-password strong-password"
).addClass(r_class);
  return true;
} 
//password length
score += password.length * 4;
score += ( $.updatePasswordMeter._checkRepetition(1,password).length - password.length ) * 1;
score += ( $.updatePasswordMeter._checkRepetition(2,password).length - password.length ) * 1;
score += ( $.updatePasswordMeter._checkRepetition(3,password).length - password.length ) * 1;
score += ( $.updatePasswordMeter._checkRepetition(4,password).length - password.length ) * 1;
//password has 3 numbers
if (password.match(/(.*[0-9].*[0-9].*[0-9])/))  score += 5; 

//password has 2 symbols
if (password.match(/(.*[!,@,#,$,%,^,&,*,?,_,~].*[!,@,#,$,%,^,&,*,?,_,~])/)) score += 5; 

//password has Upper and Lower chars
if (password.match(/([a-z].*[A-Z])|([A-Z].*[a-z])/))  score += 10; 

//password has number and chars
if (password.match(/([a-zA-Z])/) && password.match(/([0-9])/))  score += 15; 
//
//password has number and symbol
if (password.match(/([!,@,#,$,%,^,&,*,?,_,~])/) && password.match(/([0-9])/))  score += 15; 

//password has char and symbol
if (password.match(/([!,@,#,$,%,^,&,*,?,_,~])/) && password.match(/([a-zA-Z])/))  score += 15; 

//password is just a nubers or chars
if (password.match(/^\w+$/) || password.match(/^\d+$/) )  score -= 10; 

//verifing 0 < score < 100
score = score * 2;
if ( score < 0 )  score = 0;
if ( score > 100 )  score = 100;
if (score > 25 ) r_class = 'okay-password';
if (score > 50  ) r_class = 'good-password';
if (score > 75 ) r_class = 'strong-password';
target.width(score + '%').removeClass("weak-password okay-password good-password strong-password"
).addClass(r_class);
return true;
};

Outras dicas

Fundamentalmente você quer evitar a grandes tipos de ataques

  • ataques de dicionário
  • Brute ataques de força

Para evitar que o primeiro, você quer considerar as senhas que contenham palavras fraco. Para evitar que o segundo, você quer incentivar senhas de comprimento razoável (8 + personagens é comum) e com um razoavelmente grande conjunto de caracteres (incluindo letras, números e caracteres especiais). Se você considerar minúsculas e maiúsculas para ser diferente, que aumenta o conjunto de caracteres substancialmente. No entanto, isso cria um problema de usabilidade para algumas comunidades de usuários, então você precisa para equilibrar essa consideração.

Um rápido Google Search soluções transformaram-se que são responsáveis ??por ataques de força bruta (senha complexa), mas não para ataques de dicionário. PHP Força da senha Medidor de esta lista de damas força corre o server-side cheque, por isso poderia ser estendido para verificar um dicionário.

EDIT:

A propósito ... você também deve limitar o número de tentativas de login por usuário. Isso fará com que ambos os tipos de ataques menos provável. Eficaz, mas não-user-friendly é bloquear uma conta após X maus tentativas e exigem uma redefinição de senha. Mais amigável, mas mais esforço é tempo de aceleração entre tentativas de login. Você também pode exigir CAPTCHA após as primeiras tentativas de login (que é algo que Stack Overflow requer depois de muitas edições ou por muito novos usuários).

Basicamente, você provavelmente vai querer usar expressões regulares para validar o comprimento ea complexidade da senha.

Um bom exemplo fazendo isso usando javascript pode ser encontrada aqui:

http://marketingtechblog.com/programming/javascript-password-strength/

Como Daren Schwenke apontou, é melhor você trabalhar na segurança si mesmo e não colocar isso nas Mãos do usuário .

Mas é bom para fornecer algumas dicas para o usuário de quão forte é sua senha é, porque a melhor maneira de obter uma senha ainda é ENGENERING sociais .

Assim, você pode cortar um roteiro pouco de lado do cliente que verifica a senha strenght usuário como um indicador de cortesia, em tempo real. Ele bloqueia nada, mas dá-lhe uma sensação boa quente quando fica verde: -)

Basicamente o que você deve verificar é sentido commom:. Verificar se a senha contém letras, números e caracters não alfabéticos, em quantidade razoável

Você pode cortar o seu próprio algo muito facilmente: basta fazer 10/10 marca:

  • 0 é uma senha de zero comprimento;
  • +2 para cada 8 caracters na senha (15 é suposto ser um comprimento seguro);
  • +1 para o uso de uma carta, +2 para o uso de 2 letras;
  • 1 para o uso de um número, 2 para o uso de números 2;
  • +1 para o uso de um caracters não alfabéticos, +2 para 2.

Você não precisa verificar se há divinos senhas (existem letras maiúsculas, onde estão posicionados os caracters especiais, etc.), seus usuários não estão em / indústria de serviços / monthy filmes python segredo o banco / militar, são eles?

Você pode codificar que em uma hora em sem habilidades javascript loucos.

E de qualquer maneira, válida a senha e mover todo o código de segurança no lado do servidor. Se você pode delegar autenticação (por exemplo: open ID)., Ainda melhor

Eu não posso pensar de um algoritmo específico para verificar a intensidade de uma senha. O que nós fazemos é definir vários critério e quando a senha de respeitar um critério, acrescentamos 1 à sua pontuação. Quando a senha de atingir um limiar, a senha é forte. Caso contrário, é fraco.

Você pode definir muitos nível diferente de strengh se com throeshold diferente, ou pode definir valor diferente para um critério específico. Por exemplo, se uma senha tiver 5 caracteres, adicionamos 1, mas se ele tem 10, então nós adicionamos 2.

aqui está uma lista de critério para verificar se há

Comprimento (8 a 12 é ok, quanto mais, melhor) Contém letra minúscula Contém letra maiúscula A letra maiúscula não é o primeiro. contém número contém símbolos o último caractere não é um ser humano como símbolo (ex:.! ou) Não parece uma palavra Dictionnary. Alguns sábio crack senha contém biblioteca de substitutos palavra e letra (como Biblioteca -> L1br @ ry)

Hope que ajuda.

Do not Roll-Your-Own!

criptografia especialistas desencorajar roll-seu-próprio criptografia por razões que devem ser óbvias.

Para as mesmas razões, não se deve tentar rolar sua própria solução para o problema de medir a força de um password; é muito mais um problema de criptografia.

Do not entrar no negócio feio da autoria de alguns expressão regular enorme para este fim; você provavelmente vai deixar de conta para vários fatores que influenciam a força global de uma senha.

É um problema difícil

Há considerável dificuldade inerente ao problema de medir a força de um senha. Quanto mais pesquisa que realizar sobre este assunto, mais eu percebo que este é um problema "unidirecional"; isto é, não se pode medir a "dificuldade" (custo computacional) de quebrar uma senha eficientemente . Pelo contrário, é mais eficiente para fornecer requisitos de complexidade e medir a capacidade da senha para encontrá-los.

Quando consideramos o problema logicamente, um "índice de craqueabilidade" não faz muito sentido, tão conveniente quanto parece. Há tantos fatores que impulsionam o cálculo, a maioria dos que se relacionam com os recursos computacionais dedicados ao processo de craqueamento, de modo a ser impraticável.

Imagine-corrosão John the Ripper (ou uma ferramenta similar) contra a senha em questão; isso pode levar dias para quebrar uma senha decente, meses para quebrar uma senha boa, e até o sol queima-out para quebrar uma senha de excepcional. Este não é um meio prático que permitam medir a força da senha.

Aproximando-se o problema de outra direção é muito mais gerenciável: se nós fornecemos um conjunto de requisitos de complexidade, é possível avaliar a força relativa de uma senha muito rapidamente. Obviamente, os requisitos de complexidade fornecidos devem evoluir ao longo do tempo, mas há muito menos variáveis ??para que a conta se abordar o problema desta forma.

Uma solução viável

Há um utilitário independente disponível a partir Openwall direito passwdqc (presumivelmente, em pé de Senha Verificador de qualidade ). Openwall desenvolvedor, Designer Solar, parece ser um autêntico especialista em criptografia (suas obras falam por si), e assim está qualificado para o autor de tal ferramenta.

Para o meu caso de uso particular, esta é uma solução muito mais atraente do que usando um JavaScript mal concebida trecho de viver em algum canto escuro da Web.

O estabelecimento de parâmetros para suas necessidades particulares é a parte mais difícil. A implementação é a parte mais fácil.

A Prática Exemplo

Eu ofereço uma implementação simples em PHP para fornecer um jump-start. renúncias padrão se aplicam.

Este exemplo assume que estamos alimentando toda uma lista de senhas para o script PHP. Escusado será dizer que, se você está fazendo isso com senhas reais (por exemplo, aqueles despejado fora de um gerenciador de senhas), extrema cautela deve ser exercida em conformidade com a senha de manipulação. Basta escrever o despejo de senha não criptografada para o disco coloca em risco a segurança de suas senhas!

passwords.csv:

"Title","Password"
"My Test Password","password123"
"Your Test Password","123456!!!"
"A strong password","NFYbCoHC5S7dngitqCD53tvQkAu3dais"

password-check.php:

<?php

//A few handy examples from other users:
//http://php.net/manual/en/function.str-getcsv.php#117692

$csv = array_map('str_getcsv', file('passwords.csv'), [',']);

array_walk($csv, function(&$a) use ($csv) {
    $a = array_combine($csv[0], $a);
});

//Remove column header.

array_shift($csv);

//Define report column headers.

$results[] = [
    'Title',
    'Result',
    'Exit Code',
];

$i = 1;

foreach ($csv as $p) {
    $row['title'] = $p['Title'];

    //If the value contains a space, it's considered a passphrase.

    $isPassphrase = stristr($p['Password'], ' ') !== false ? true : false;

    $cmd = 'echo ' . escapeshellarg($p['Password']) . ' | pwqcheck -1 min=32,24,22,20,16 max=128';

    if ($isPassphrase) {
        $cmd .= ' passphrase=3';
    }
    else {
        $cmd .= ' passphrase=0';
    }

    $output = null;
    $exitCode = null;

    $stdOut = exec($cmd, $output, $exitCode);

    //Exit code 0 represents an unacceptable password (not an error).
    //Exit code 1 represents an acceptable password (it meets the criteria).

    if ($exitCode === 0 || $exitCode === 1) {
        $row['result'] = trim($stdOut);
        $row['exitCode'] = $exitCode;
    }
    else {
        $row['result'] = 'An error occurred while calling pwqcheck';
        $row['exitCode'] = null;
    }

    $results[$i] = $row;

    $i++;
}

$reportFile = 'report.csv';

$fp = @fopen($reportFile, 'w');

if ($fp !== false) {
    foreach ($results as $p) {
        fputcsv($fp, $p);
    }

    fclose($fp);
}
else {
    die($reportFile . ' could not be opened for writing (destination is not writable or file is in use)');
}

exit;

report.csv Resultante:

Title,Result,"Exit Code"
"My Test Password","Bad passphrase (too short)",1
"Your Test Password","Bad passphrase (too short)",1
"A strong password",OK,0

Embrulho-Up

Eu ainda tenho que encontrar uma solução mais completa na Web; escusado será dizer, congratulo-me com todas as outras recomendações.

Obviamente, esta abordagem não é ideal para certos casos de uso (por exemplo, um "medidor de força da senha" implementado "client-side"). Mesmo assim, seria trivial para fazer uma chamada de AJAX para um recurso do lado do servidor que retorna uma aprovação / reprovação resposta utilizando a abordagem descrita acima, mas tal abordagem deve assumir apotencial de abuso (por exemplo, ataques DoS) e exigiria uma comunicação segura entre cliente e servidor, bem como a aceitação dos riscos associados com a transmissão da senha un-hash.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top