Como verificar a força da senha [duplicada]

4

Eu escrevi esse script, mas [:alnum:] não funciona. Alguém ajuda?

echo -n "Enter a password : "
read password

LEN=$(echo ${#password})

if [ $LEN -lt 10 ]; then

       echo "$password is smaller than 10 characters"
else
     if ! [ -z 'echo $password | tr -d "[:alnum:]"' ]; then
        echo "$password is a weak password"
     else
        echo "$password is a strong password"
     fi
fi
echo 
    
por Panos Mikael 10.11.2017 / 11:27

7 respostas

14

Se você realmente deseja verificar a força das senhas, você deve usar cracklib-check do pacote cracklib-runtime (deve ser instalado por padrão):

$ echo foo | cracklib-check
foo: it is WAY too short
$ echo foobar | cracklib-check
foobar: it is based on a dictionary word
$ echo foobared | cracklib-check
foobared: it is based on a dictionary word
$ echo foobared123 | cracklib-check
foobared123: it is too simplistic/systematic
$ echo '!'foobared123 | cracklib-check
!foobared123: OK
    
por muru 10.11.2017 / 12:31
13

Problemas superficiais

Existem vários problemas com o seu script. Ele quebra se a senha contiver um número de caracteres especiais. Tente inserir entradas como:

a space
two  spaces
a * star                            ← try this one in different directories
bbbbbbbbbb                          ← try this one in a directory containing a file called a
endswithabackslash\

Leia Por que meu script de shell sufoca em espaço em branco ou outros caracteres especiais? . Tudo isso. Não escreva scripts de shell que estejam remotamente relacionados à segurança até que você entenda tudo isso.

Ah, e [:alnum:] funciona perfeitamente. Você provavelmente pretendia escrever if [ -z … ou if ! [ -n … em vez de if ! [ -z … .

Não existe a força de uma senha

A ideia de "força de senha" é um mito. É um mito que é espalhado por muitos sites, mas ainda é um mito. Não existe a força de uma senha, existe apenas a força de um processo de geração de senha .

Ter caracteres especiais em uma senha não o torna mais strong. Uma senha é um compromisso entre a facilidade de memorização e a facilidade de quebrar, e os caracteres especiais tornam as senhas significativamente mais difíceis de memorizar, mas não são significativamente mais difíceis de decifrar , conforme analisado em este tópico no Security Stack Exchange ( o conto , a matemática , alguns complementos - exercise: em esta resposta errada , quais partes ignoram completamente os fatos?). A ideia de que os caracteres especiais tornam uma senha mais strong baseia-se no pressuposto de que as pessoas que escrevem crackers de senha são idiotas. Adivinha o quê: eles não são. Há dinheiro para ganhar com a quebra de senhas, então você pode apostar que há pessoas que investem em fazê-lo bem.

Então, como devo escolher senhas?

Aleatoriamente . Se o seu método para escolher uma senha não incluir uma fonte de aleatoriedade (com um computador ou lançar um dado se você gostar da velha guarda), não é bom.

Diceware é uma escolha popular, mas qualquer método que siga o XKCD - escolhe várias “palavras” aleatoriamente de algum dicionário - é bom.

Um script correto

#!/bin/sh
echo -n "Enter a password : "
IFS= read -r password

LEN=${#password}

if [ "$LEN" -lt 10 ]; then
  printf "%s is smaller than 10 characters\n" "$password"
fi
if [ -z "$(printf %s "$password" | tr -d "[:alnum:]")" ]; then
  printf "%s only contains ASCII letters and digits\n" "$password"
else
  printf "%s contains characters other than ASCII letters and digits\n" "$password"
fi

Usar tr desse modo supercomplica as coisas. O shell é perfeitamente capaz de verificar se uma string contém caracteres entre um determinado conjunto.

#!/bin/sh
echo -n "Enter a password : "
IFS= read -r password

LEN=${#password}

if [ "$LEN" -lt 10 ]; then
  printf "%s is smaller than 10 characters\n" "$password"
fi
case "$password" in
  *[![:alnum:]]*)
    printf "%s contains characters other than ASCII letters and digits\n" "$password";;
  *)
    printf "%s only contains ASCII letters and digits\n" "$password";;
esac

(Observe que a declaração sobre ASCII letras e dígitos é verdadeira para /bin/sh do Ubuntu, mas no bash [:alnum:] inclui todas as letras e dígitos na localidade atual, não apenas os ASCII. )

    
por Gilles 10.11.2017 / 22:11
8

Cheira muito a um problema XY para mim. Nunca, nunca, escreva suas próprias ferramentas para trabalhar com senhas. Pelo menos você não está lidando com armazenamento de senhas aqui, mas a primeira coisa que vem à mente com seu código é que eu poderia inserir um -numérica senha e tê-lo considerado "strong" (quando, na realidade, seria muito mais fraco do que uma senha todo-alfabética). Se você continuar com essa abordagem de segurança / manipulação de senha, você vai cair mais cedo ou mais tarde e não será bonito quando acontecer.

A solução correta é usar uma biblioteca externa ou aplicativo auxiliar para determinar a força da senha (e executar outras tarefas relacionadas à senha). Atualmente, a maioria dos sistemas Linux tem PAM que pode executar todas as tarefas relacionadas à autenticação de maneira segura (como bônus você obtém suporte para outros métodos de autenticação além de senhas, dependendo de como o sistema do usuário está configurado) e muru já sugeriu um aplicativo auxiliar que determina a força da senha.

    
por Micheal Johnson 10.11.2017 / 14:53
1
td -d "[:alnum:]"

funciona para mim:

$> echo '123§45!67M89(0' | tr -d  "[:alnum:]"
§!(   

Você pode usá-lo como

#!/bin/bash

echo -n "Enter a password : "
read password
LEN=$(echo ${#password})

if [ $LEN -lt 10 ]; then
    echo "$password is smaller than 10 characters"
else
    if [ $(echo $password | tr -d "[:alnum:]" | wc -w) -eq 0 ]; then
        echo "$password is a weak password"
    else
        echo "$password is a strong password"
    fi
fi                                                                                                                      echo

wc -w conta as palavras.

  • Portanto, se você remover todos os alnum e a contagem de palavras for 0 = > verdadeiro = > senha fraca

  • se a contagem de palavras for 1 (ou mais, se espaços forem usados) = > false = > senha strong

por derHugo 10.11.2017 / 12:05
1

Se você quiser um bom método para criar senhas

Veja

Palavras cruzadas combinando palavras reais

"Senhas strongs" ou "Força de um processo de geração de senha"

Sua pergunta: Como verificar a força da senha?

Como faço para impor uma política de complexidade de senhas?

Você só pode verificar certos aspectos da senha ou usar uma ferramenta específica para cada método para criar a senha ou um método geral de força bruta (se o invasor não conhecer o método).

Shellscript pwdcheck usando cracklib-check

#!/bin/bash

# setting variables

usage="Use 4 words chosen randomly, see this link:
https://security.stackexchange.com/questions/6095/xkcd-936-short-complex-password-or-long-dictionary-passphrase"

minlen=20  # can be modified here
short="is shorter than $minlen characters"
goodmix="is long enough"
badmix="is too short
$usage"
separator="-------"

# checking parameter

if [ "$1" == "-h" ] || [ "$1" == "--help" ] || [ $# -gt 1 ]; then
 echo "${0##*/} uses 'cracklib-check'"
 echo "----------------------------------------------------------------"
 echo "Usage:   $0 CandidateContaining4DifferentWords"
 echo "Example: $0 At-least-$minlen-char"
 echo "         $0 'Should.be.selected.via.*random*.process'"
 echo "         $0 'Single-quote-for-1-special-character!'"
 echo "         $0 'FindPatternByDigitalTest123'"
 echo "         $0 'Provoke1pattern2search3by4separating5words'"
 echo "$usage"
 exit
elif [ $# -eq 0 ]; then
 echo "$usage"
 echo "----------------------------------------------------------------"
 read -p "Enter a password : " password
elif [ $# -eq 1 ]; then
 password="$1"
fi

# checking and installing if necessary

which cracklib-check > /dev/null
if [ $? -eq 1 ]; then
 read -p "Do you want to install 'cracklib-runtime' to get 'cracklib-check'? (y/N) " ans
 if [ "$ans" == "y" ]; then
  sudo apt-get update && sudo apt-get install cracklib-runtime
 fi
fi

if [ ${#password} -lt $minlen ]; then
 result="$short"
else
 result="$goodmix"
 case "$password" in
  *[![:alnum:]]*)
     alnm="'$password' contains characters other than ASCII letters and digits";;
#     result="$badmix";;
  *)
    alnm="$password contains only ASCII letters and digits";;
 esac
fi

echo "Test 1 - size&mix: '$password' $result"
test ${#password} -lt $minlen || echo "$alnm"
if [ "$result" == "$badmix" ] || [ "$result" == "$short" ]; then
 total="is bad"
else
 total='is good'
fi

echo "$separator"
echo "Test 2 - lexicon: '$password'"
sed -e 's/[0-9]/123\n/g' -e 's/$//' -e 's/[§!@£$€#¤%/()=?*,;.:_-~ ]/123\n/g' -e 's/$/123/g' \
<<< "$password" | LANG=C cracklib-check |sed 's/123: /: /'| \
grep 'it is based on a dictionary word'
if [ $? -ne 0 ]; then
 echo 'no comment'
fi

echo "$separator"
echo "Test 3 - digital: '$password'"
sed -e 's/[[:alpha:]]//g' -e 's/[§!@£$€#¤%/()=?*,;.:_-~ ]//g' -e 's/$/xyz/' \
<<< "$password" | LANG=C cracklib-check |sed 's/xyz: /: /'| \
grep 'it is too simplistic/systematic'
if [ $? -eq 0 ]; then
 total='is bad'
else
 echo 'is good'
fi

echo "$separator"
echo "Test 4 - cracklib-check: '$password'"
LANG=C cracklib-check <<< "$password" | tee /dev/stderr | grep ': OK' > /dev/null
if [ $? -eq 0 ]; then
 echo='is good'
else
 total='is bad'
fi

if [ "$total" == "is good" ]; then
 echo "$separator"
 ans=
 while [ "$ans" != "g" ] && [ "$ans" != "b" ]
 do
  read -p "Test 5 - manual: Is '$password' a good or bad password? (g/b) " ans
  if [ "$ans" == "g" ]; then
   echo 'is good'
  elif [ "$ans" == "b" ]; then
   total='is bad'
   echo "$total"
  fi
 done
fi

echo "$separator"
if [ "$total" == "is good" ]; then
 echo "Every test result for '$password' $total: No weakness found :-)"
else
 echo "Some test result for '$password' $total: Some weakness found :-("
fi

Texto de ajuda

Executando no diretório atual, um diretório de teste. onde você tem o arquivo shellscript,

$ ./pwdcheck -h
pwdcheck uses 'cracklib-check'
----------------------------------------------------------------
Usage:   ./pwdcheck CandidateContaining4DifferentWords
Example: ./pwdcheck At-least-20-char
         ./pwdcheck 'Should.be.selected.via.*random*.process'
         ./pwdcheck 'Single-quote-for-1-special-character!'
         ./pwdcheck 'FindPatternByDigitalTest123'
         ./pwdcheck 'Provoke1pattern2search3by4separating5words'
Use 4 words chosen randomly, see this link:
https://security.stackexchange.com/questions/6095/xkcd-936-short-complex-password-or-long-dictionary-passphrase

O pacote de programas do cracklib

$ apt-cache policy cracklib-runtime 
cracklib-runtime:
  Installerad: 2.9.2-1ubuntu1
  Kandidat:    2.9.2-1ubuntu1
  Versionstabell:
 *** 2.9.2-1ubuntu1 500
        500 http://se.archive.ubuntu.com/ubuntu xenial-updates/main i386 Packages
        100 /var/lib/dpkg/status
     2.9.2-1build2 500
        500 http://se.archive.ubuntu.com/ubuntu xenial/main i386 Packages

Testando os diferentes exemplos do texto de ajuda

Teste manual importante, mas use com sabedoria

Sua inspeção manual e 'teste' podem ser importantes para evitar senhas realmente ruins, mas se você usou um método aleatório automático com uma boa reputação, você deve confiar sobre isso e evitar adulterar o resultado , porque você provavelmente fará a senha mais fácil de quebrar.

$ ./pwdcheck CandidateContaining4DifferentWords
Test 1 - size&mix: 'CandidateContaining4DifferentWords' is long enough
CandidateContaining4DifferentWords contains only ASCII letters and digits
-------
Test 2 - lexicon: 'CandidateContaining4DifferentWords'
no comment
-------
Test 3 - digital: 'CandidateContaining4DifferentWords'
is good
-------
Test 4 - cracklib-check: 'CandidateContaining4DifferentWords'
CandidateContaining4DifferentWords: OK
-------
Test 5 - manual: Is 'CandidateContaining4DifferentWords' a good or bad password? (g/b) b
is bad
-------
Some test result for 'CandidateContaining4DifferentWords' is bad: Some weakness found :-(
# comment: This password is published here!

##### Short password #####

$ ./pwdcheck At-least-20-char
Test 1 - size&mix: 'At-least-20-char' is shorter than 20 characters
-------
Test 2 - lexicon: 'At-least-20-char'
least: it is based on a dictionary word
char: it is based on a dictionary word
-------
Test 3 - digital: 'At-least-20-char'
is good
-------
Test 4 - cracklib-check: 'At-least-20-char'
At-least-20-char: OK
-------
Some test result for 'At-least-20-char' is bad: Some weakness found :-(

##### Reminder about random process #####

$ ./pwdcheck 'Should.be.selected.via.*random*.process'
Test 1 - size&mix: 'Should.be.selected.via.*random*.process' is long enough
'Should.be.selected.via.*random*.process' contains characters other than ASCII letters and digits
-------
Test 2 - lexicon: 'Should.be.selected.via.*random*.process'
Should: it is based on a dictionary word
selected: it is based on a dictionary word
via: it is based on a dictionary word
random: it is based on a dictionary word
process: it is based on a dictionary word
-------
Test 3 - digital: 'Should.be.selected.via.*random*.process'
is good
-------
Test 4 - cracklib-check: 'Should.be.selected.via.*random*.process'
Should.be.selected.via.*random*.process: OK
-------
Test 5 - manual: Is 'Should.be.selected.via.*random*.process' a good or bad password? (g/b) g
is good
-------
Every test result for 'Should.be.selected.via.*random*.process' is good: No weakness found :-)
# comment: Do not use the password literally ;-)

##### Single quote the password, if you intend to use special characters   #####
##### Words are found by lexicon test (using cracklib-check), and accepted #####

$ ./pwdcheck 'Single-quote-for-1-special-character!'
Test 1 - size&mix: 'Single-quote-for-1-special-character!' is long enough
'Single-quote-for-1-special-character!' contains characters other than ASCII letters and digits
-------
Test 2 - lexicon: 'Single-quote-for-1-special-character!'
Single: it is based on a dictionary word
quote: it is based on a dictionary word
for: it is based on a dictionary word
special: it is based on a dictionary word
character: it is based on a dictionary word
-------
Test 3 - digital: 'Single-quote-for-1-special-character!'
is good
-------
Test 4 - cracklib-check: 'Single-quote-for-1-special-character!'
Single-quote-for-1-special-character!: OK
-------
Test 5 - manual: Is 'Single-quote-for-1-special-character!' a good or bad password? (g/b) b
is bad
-------
Some test result for 'Single-quote-for-1-special-character!' is bad: Some weakness found :-(

##### Showing how the digital test works (it uses cracklib-check) #####

$ ./pwdcheck 'FindPatternByDigitalTest123'
Test 1 - size&mix: 'FindPatternByDigitalTest123' is long enough
FindPatternByDigitalTest123 contains only ASCII letters and digits
-------
Test 2 - lexicon: 'FindPatternByDigitalTest123'
no comment
-------
Test 3 - digital: 'FindPatternByDigitalTest123'
123: it is too simplistic/systematic
-------
Test 4 - cracklib-check: 'FindPatternByDigitalTest123'
FindPatternByDigitalTest123: OK
-------
Some test result for 'FindPatternByDigitalTest123' is bad: Some weakness found :-(

##### Showing the lexicon test and the digital test #####

$ ./pwdcheck 'Provoke1pattern2search3by4separating5words'
Test 1 - size&mix: 'Provoke1pattern2search3by4separating5words' is long enough
Provoke1pattern2search3by4separating5words contains only ASCII letters and digits
-------
Test 2 - lexicon: 'Provoke1pattern2search3by4separating5words'
Provoke: it is based on a dictionary word
pattern: it is based on a dictionary word
search: it is based on a dictionary word
separating: it is based on a dictionary word
words: it is based on a dictionary word
-------
Test 3 - digital: 'Provoke1pattern2search3by4separating5words'
12345: it is too simplistic/systematic
-------
Test 4 - cracklib-check: 'Provoke1pattern2search3by4separating5words'
Provoke1pattern2search3by4separating5words: OK
-------
Some test result for 'Provoke1pattern2search3by4separating5words' is bad: Some weakness found :-(

##### Run interactively without any parameter #####

$ ./pwdcheck
Use 4 words chosen randomly, see this link:
https://security.stackexchange.com/questions/6095/xkcd-936-short-complex-password-or-long-dictionary-passphrase
----------------------------------------------------------------
Enter a password : CandidateContaining4DifferentWords
Test 1 - size&mix: 'CandidateContaining4DifferentWords' is long enough
CandidateContaining4DifferentWords contains only ASCII letters and digits
-------
Test 2 - lexicon: 'CandidateContaining4DifferentWords'
no comment
-------
Test 3 - digital: 'CandidateContaining4DifferentWords'
is good
-------
Test 4 - cracklib-check: 'CandidateContaining4DifferentWords'
CandidateContaining4DifferentWords: OK
-------
Test 5 - manual: Is 'CandidateContaining4DifferentWords' a good or bad password? (g/b) g
is good
-------
Every test result for 'CandidateContaining4DifferentWords' is good: No weakness found :-)
sudodus@xenial32 /media/multimed-2/test/test0/pwdstrength $ 
    
por sudodus 10.11.2017 / 11:45
-3

Eu encontrei o script correto e funciona:

echo -n "Enter a password : "
read password

LEN=$(echo ${#password})

if [ $LEN -lt 10 ]; then

       echo "$password is smaller than 10 characters"
else
     if  [ -z 'echo $password | tr -d '[:alpha:]' | tr -d '[:upper:]' | tr -d '[:lower:]' ' ]; then
        echo "$password is a weak password"
     else
        echo "$password is a strong password"
     fi
fi
echo 
    
por Panos Mikael 10.11.2017 / 11:58
-3

Por fim, o seguinte script que escrevi resolveu meu problema:

echo -n "Enter a password : "
read password

LEN=$(echo ${#password})

if [ $LEN -lt 10 ]; then

   echo "$password is smaller than 10 characters"

else

 if  [ -z 'echo $password | tr -d '[:alpha:]' | tr -d '[:upper:]' | tr -d '[:lower:]' ' ] || [ -z 'echo $password | tr -d '[:upper:]' | tr -d '[:digit:]' '] || [ -z 'echo $password | tr -d '[:lower:]' | tr -d '[:digit:]' '] ; then

    echo "$password is a weak password"

 else

    echo "$password is a strong password"

 fi

fi

echo 

Obrigado pelas suas respostas!

    
por Panos Mikael 10.11.2017 / 21:51