web-dev-qa-db-fra.com

Comment vérifier la force du mot de passe

J'ai écrit ce script mais [:alnum:] ne fonctionne pas. Quelqu'un aide?

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 
4
Panos Mikael

Si vous voulez vraiment vérifier la force des mots de passe, vous devriez utiliser cracklib-check du paquetage cracklib-runtime (devrait être installé par défaut):

$ 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
14
muru

Problèmes superficiels

Il y a plusieurs problèmes avec votre script. Il se brise si le mot de passe contient un certain nombre de caractères spéciaux. Essayez d'entrer des entrées telles que:

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\

Lire Pourquoi mon script Shell s'étouffe-t-il avec des espaces ou d'autres caractères spéciaux?. Tout. N'écrivez aucun script Shell lié à la sécurité à distance tant que vous ne comprenez pas tout.

Oh, et [:alnum:] fonctionne parfaitement. Vous avez probablement eu l'intention d'écrire if [ -z … ou if ! [ -n … au lieu de if ! [ -z ….

La force d'un mot de passe n'existe pas

L'idée de "force du mot de passe" est un mythe. C'est un mythe qui est répandu par beaucoup de sites Web, mais c'est toujours un mythe. La force d'un mot de passe n'existe pas il n'y a que la force d'un processus de génération de mot de passe .

Avoir des caractères spéciaux dans un mot de passe ne le rend pas plus fort. Un mot de passe est un compromis entre facilité de mémorisation et facilité de craquage, et les caractères spéciaux rendent les mots de passe beaucoup plus difficiles à mémoriser mais pas beaucoup plus difficiles à déchiffrer , comme analysé dans ce fil sur Security Stack Exchange ( la nouvelle , le calcul , quelques compléments - exercice: dans cette réponse fausse , lequel les parties ignorent complètement les faits?). L'idée que les caractères spéciaux renforcent un mot de passe repose sur l'hypothèse que les auteurs de piratages de mots de passe sont des idiots. Devinez quoi: ils ne sont pas. En déchiffrant des mots de passe, il y a de l'argent à gagner. Vous pouvez donc parier que des gens investissent pour le faire correctement.

Alors, comment dois-je choisir les mots de passe alors?

Au hasard. Si votre méthode pour choisir un mot de passe n'inclut pas de source aléatoire (avec un ordinateur, ou si vous aimez lancer les dés si vous l'aimez à l'ancienne), c'est inutile.

Diceware est un choix courant, mais toute méthode qui suit le motif XKCD - choisissez plusieurs "mots" au hasard dans un dictionnaire - est bonne.

Un script correct

#!/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

Utiliser tr de cette manière complique les choses. Le shell est parfaitement capable de vérifier si une chaîne contient des caractères appartenant à un certain ensemble.

#!/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

(Notez que la déclaration à propos de ASCII lettres et chiffres est vraie pour le /bin/sh d'Ubuntu, mais dans bash [:alnum:] inclut toutes les lettres et tous les chiffres de l'environnement local actuel, pas seulement ceux ASCII .)

13
Gilles

Ça sent terriblement comme un problème XY pour moi. Jamais, jamais, écrivez vos propres outils pour travailler avec des mots de passe. Au moins vous ne faites pas ici avec le stockage de mot de passe, mais la première chose qui me vient à l’esprit avec votre code est que je pourrais entrer un tout. -numeric password et le considérer comme "fort" (alors qu'en réalité, il serait beaucoup plus faible qu'un mot de passe alphabétique). Si vous continuez avec cette approche de la sécurité/gestion des mots de passe, vous allez tomber tôt ou tard et ce ne sera pas beau quand cela se produira.

La solution correcte consiste à utiliser une bibliothèque externe ou une application auxiliaire pour déterminer la force du mot de passe (et effectuer d'autres tâches associées à un mot de passe). De nos jours, la plupart des systèmes Linux ont PAM qui peut effectuer toutes les tâches liées à l'authentification de manière sécurisée (en prime, vous bénéficiez d'une assistance pour d'autres méthodes d'authentification en plus des mots de passe, en fonction de la configuration du système de l'utilisateur) et muru a déjà suggéré une application d'assistance qui détermine la force du mot de passe.

8
Micheal Johnson

Si vous voulez une bonne méthode pour créer des mots de passe

Voir

Générateur de mot de passe combinant des mots réels

"Mots de passe forts" ou "Force du processus de génération de mot de passe"

Votre question: Comment vérifier la force du mot de passe?

Comment puis-je appliquer une politique de complexité de mot de passe?

Vous pouvez uniquement vérifier certains aspects du mot de passe ou utiliser un outil spécifique à chaque méthode pour créer le mot de passe ou une méthode générale de force brute (si l'attaquant ne connaît pas la méthode).

Shellscript pwdcheck utilisant 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

Texte d'aide

En cours d'exécution dans le répertoire en cours, un répertoire de test. où vous avez le fichier 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

Le package du programme 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

Test des différents exemples du texte d'aide

Test manuel important mais à utiliser judicieusement

Votre inspection manuelle et votre "test" peuvent être importants pour éviter les mots de passe vraiment mauvais, mais si vous utilisiez une méthode aléatoire automatique avec une bonne réputation, vous devriez vous y fier et éviter de falsifier le résultat , car vous ferez probablement en sorte que le mot de passe soit plus facile à déchiffrer.

$ ./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 $ 
1
sudodus
td -d "[:alnum:]"

travaille pour moi:

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

Vous pouvez l'utiliser comme

#!/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 compte les mots.

  • Donc, si vous supprimez tous les alnum et que le nombre de mots est 0 => true => mot de passe faible

  • si le nombre de mots est 1 (ou plus si des espaces sont utilisés) => false => mot de passe fort

1
derHugo