Question

Quel est le meilleur moyen de s'assurer qu'un mot de passe fourni par l'utilisateur est un mot de passe fort dans un formulaire d'inscription ou de changement de mot de passe?

Une idée que j'avais (en python)

def validate_password(passwd):
    conditions_met = 0
    conditions_total = 3
    if len(passwd) >= 6: 
        if passwd.lower() != passwd: conditions_met += 1
        if len([x for x in passwd if x.isdigit()]) > 0: conditions_met += 1
        if len([x for x in passwd if not x.isalnum()]) > 0: conditions_met += 1
    result = False
    print conditions_met
    if conditions_met >= 2: result = True
    return result
Était-ce utile?

La solution

1: Éliminez les mots de passe fréquemment utilisés
Vérifiez les mots de passe entrés par rapport à une liste de mots de passe souvent utilisés (voir par exemple les 100 000 premiers mots de passe figurant dans la liste de mots de passe LinkedIn divulgués: http://www.adeptus-mechanicus.com/codex/linkhap/combo_not.zip ), veillez à inclure substitutions de leetspeek : A @, E3, B8, S5, etc.
Supprimez les parties du mot de passe qui ont heurté cette liste de la phrase entrée, avant de passer à la partie 2 ci-dessous.

2: ne forcez aucune règle sur l'utilisateur

La règle d'or des mots de passe est que plus c'est long, mieux c'est.
Oubliez l'utilisation forcée des majuscules, des chiffres et des symboles car (la grande majorité des) utilisateurs: - Faites de la première lettre une capitale; - Mettez le numéro 1 à la fin; - Placez un ! après si un symbole est requis.

Vérifiez plutôt la force du mot de passe

Pour un bon point de départ, voir: http://www.passwordmeter.com/

Je suggère au minimum les règles suivantes:

Additions (better passwords)
-----------------------------
- Number of Characters              Flat       +(n*4)   
- Uppercase Letters                 Cond/Incr  +((len-n)*2)     
- Lowercase Letters                 Cond/Incr  +((len-n)*2)     
- Numbers                           Cond       +(n*4)   
- Symbols                           Flat       +(n*6)
- Middle Numbers or Symbols         Flat       +(n*2)   
- Shannon Entropy                   Complex    *EntropyScore

Deductions (worse passwords)
----------------------------- 
- Letters Only                      Flat       -n   
- Numbers Only                      Flat       -(n*16)  
- Repeat Chars (Case Insensitive)   Complex    -    
- Consecutive Uppercase Letters     Flat       -(n*2)   
- Consecutive Lowercase Letters     Flat       -(n*2)   
- Consecutive Numbers               Flat       -(n*2)   
- Sequential Letters (3+)           Flat       -(n*3)   
- Sequential Numbers (3+)           Flat       -(n*3)   
- Sequential Symbols (3+)           Flat       -(n*3)
- Repeated words                    Complex    -       
- Only 1st char is uppercase        Flat       -n
- Last (non symbol) char is number  Flat       -n
- Only last char is symbol          Flat       -n

Suivre passwordmeter n'est pas suffisant, car son algorithme naïf est visible Password1! aussi bon, alors qu'il est exceptionnellement faible. Assurez-vous de ne pas tenir compte des majuscules lors de la notation, ainsi que des chiffres et des symboles de fin (conformément aux 3 dernières règles).

Calcul de l'entropie de Shannon
Voir: le moyen le plus rapide de calculer l'entropie en Python

.

3: n'autorisez aucun mot de passe trop faible
. Plutôt que d'obliger l'utilisateur à se plier à des règles auto-destructrices, autorisez tout ce qui donnera un score suffisant. La hauteur dépend de votre cas d'utilisation.

Et surtout
Lorsque vous acceptez le mot de passe et le stockez dans une base de données, assurez-vous de le saler et de le hacher! .

Autres conseils

En fonction de la langue, j'utilise généralement des expressions régulières pour vérifier si elle contient:

  • Au moins une majuscule et une lettre minuscule
  • Au moins un numéro
  • Au moins un caractère spécial
  • une longueur d'au moins six caractères

Vous pouvez exiger tout ce qui précède ou utiliser un type de script de mesure de la force. Pour mon mesureur de force, si le mot de passe a la bonne longueur, il est évalué comme suit:

  • Une condition remplie: mot de passe faible
  • Deux conditions remplies: mot de passe moyen
  • Toutes les conditions sont remplies: mot de passe fort

Vous pouvez adapter ce qui précède à vos besoins.

L’approche orientée objet serait un ensemble de règles. Attribuez un poids à chaque règle et parcourez-la. En code pseudo:

abstract class Rule {

    float weight;

    float calculateScore( string password );

}

Calcul du score total:

float getPasswordStrength( string password ) {     

    float totalWeight = 0.0f;
    float totalScore  = 0.0f;

    foreach ( rule in rules ) {

       totalWeight += weight;
       totalScore  += rule.calculateScore( password ) * rule.weight;

    }

    return (totalScore / totalWeight) / rules.count;

}

Un exemple d'algorithme de règle, basé sur le nombre de classes de caractères présentes:

float calculateScore( string password ) {

    float score = 0.0f;

    // NUMBER_CLASS is a constant char array { '0', '1', '2', ... }
    if ( password.contains( NUMBER_CLASS ) )
        score += 1.0f;

    if ( password.contains( UPPERCASE_CLASS ) )
        score += 1.0f;

    if ( password.contains( LOWERCASE_CLASS ) )
        score += 1.0f;

    // Sub rule as private method
    if ( containsPunctuation( password ) )
        score += 1.0f;

    return score / 4.0f;

}

Les deux métriques les plus simples à vérifier sont:

  1. Longueur. Je dirais au moins 8 caractères.
  2. Nombre de classes de caractères différentes contenues dans le mot de passe. Il s’agit généralement de lettres minuscules, de lettres majuscules, de chiffres, de signes de ponctuation et autres. Un mot de passe fort contiendra des caractères d'au moins trois de ces classes; si vous forcez un nombre ou un autre caractère non alphabétique, vous réduisez considérablement l'efficacité des attaques par dictionnaire.

Cracklib est génial, et dans les nouveaux packages, un module Python est disponible. Cependant, sur les systèmes qui ne l’ont pas encore, comme CentOS 5, j’ai écrit un wrapper ctypes pour la clé de chiffrement système. Cela fonctionnerait également sur un système sur lequel vous ne pouvez pas installer python-libcrypt. nécessite python avec les types de types disponibles, vous devez donc installer et utiliser le paquet python26.

Il présente également l’avantage de pouvoir prendre le nom d’utilisateur et de rechercher les mots de passe qui le contiennent ou qui sont sensiblement similaires, comme le libcrypt " FascistGecos " fonction mais sans exiger que l'utilisateur existe dans / etc / passwd.

Ma bibliothèque de ctypescracklib est disponible sur github

Quelques exemples d'utilisation:

>>> FascistCheck('jafo1234', 'jafo')
'it is based on your username'
>>> FascistCheck('myofaj123', 'jafo')
'it is based on your username'
>>> FascistCheck('jxayfoxo', 'jafo')
'it is too similar to your username'
>>> FascistCheck('cretse')
'it is based on a dictionary word'

après avoir lu les autres réponses utiles, voici ce que je vais faire avec:

-1 identique au nom d'utilisateur
+0 contient le nom d'utilisateur
+1 plus de 7 caractères
+1 plus de 11 caractères
+1 contient des chiffres
+1 mélange de majuscules et de minuscules
+1 contient une ponctuation
+1 caractère non imprimable

pwscore.py:

import re
import string
max_score = 6
def score(username,passwd):
    if passwd == username:
        return -1
    if username in passwd:
        return 0
    score = 0
    if len(passwd) > 7:
        score+=1
    if len(passwd) > 11:
        score+=1
    if re.search('\d+',passwd):
        score+=1
    if re.search('[a-z]',passwd) and re.search('[A-Z]',passwd):
        score+=1
    if len([x for x in passwd if x in string.punctuation]) > 0:
        score+=1
    if len([x for x in passwd if x not in string.printable]) > 0:
        score+=1
    return score

exemple d'utilisation:

import pwscore
    score = pwscore(username,passwd)
    if score < 3:
        return "weak password (score=" 
             + str(score) + "/"
             + str(pwscore.max_score)
             + "), try again."

probablement pas le plus efficace, mais semble raisonnable. pas sûr que FascistCheck = > 'trop similaire à nom d'utilisateur' est ça vaut le coup.

'abc123ABC! @ £' = score 6/6 si ce n'est pas un sur-ensemble de nom d'utilisateur

peut-être que cela devrait marquer moins.

Il existe un pirate de mots de passe John the Ripper ouvert et gratuit, qui est un excellent moyen de vérifier base de données de mots de passe existante.

Eh bien, voici ce que j'utilise:

   var getStrength = function (passwd) {
    intScore = 0;
    intScore = (intScore + passwd.length);
    if (passwd.match(/[a-z]/)) {
        intScore = (intScore + 1);
    }
    if (passwd.match(/[A-Z]/)) {
        intScore = (intScore + 5);
    }
    if (passwd.match(/\d+/)) {
        intScore = (intScore + 5);
    }
    if (passwd.match(/(\d.*\d)/)) {
        intScore = (intScore + 5);
    }
    if (passwd.match(/[!,@#$%^&*?_~]/)) {
        intScore = (intScore + 5);
    }
    if (passwd.match(/([!,@#$%^&*?_~].*[!,@#$%^&*?_~])/)) {
        intScore = (intScore + 5);
    }
    if (passwd.match(/[a-z]/) && passwd.match(/[A-Z]/)) {
        intScore = (intScore + 2);
    }
    if (passwd.match(/\d/) && passwd.match(/\D/)) {
        intScore = (intScore + 2);
    }
    if (passwd.match(/[a-z]/) && passwd.match(/[A-Z]/) && passwd.match(/\d/) && passwd.match(/[!,@#$%^&*?_~]/)) {
        intScore = (intScore + 2);
    }
    return intScore;
} 

En plus de l’approche standard consistant à mélanger des caractères alphanumériques, numériques et des symboles, j’ai remarqué lors de mon inscription à MyOpenId la semaine dernière que le vérificateur de mot de passe vous indique si votre mot de passe est basé sur un mot du dictionnaire, même si vous ajoutez des chiffres ou remplacez des alphas. avec des chiffres similaires (utilisez zéro au lieu de 'o', '1' au lieu de 'i', etc.).

J'ai été très impressionné.

J'ai écrit une petite application Javascript. Jetez un coup d'œil à: Encore un autre indicateur de mot de passe . Vous pouvez télécharger la source et l’utiliser / la modifier sous GPL. Amusez-vous!

Je ne sais pas si quelqu'un trouvera cela utile, mais j'ai vraiment aimé l'idée d'un jeu de règles comme suggéré par phear. Je suis donc allé écrire une règle en classe Python 2.6 (bien que ce soit probablement compatible avec la version 2.5):

import re

class SecurityException(Exception):
    pass

class Rule:
    """Creates a rule to evaluate against a string.
    Rules can be regex patterns or a boolean returning function.
    Whether a rule is inclusive or exclusive is decided by the sign
    of the weight. Positive weights are inclusive, negative weights are
    exclusive. 


    Call score() to return either 0 or the weight if the rule 
    is fufilled. 

    Raises a SecurityException if a required rule is violated.
    """

    def __init__(self,rule,weight=1,required=False,name=u"The Unnamed Rule"):
        try:
            getattr(rule,"__call__")
        except AttributeError:
            self.rule = re.compile(rule) # If a regex, compile
        else:
            self.rule = rule  # Otherwise it's a function and it should be scored using it

        if weight == 0:
            return ValueError(u"Weights can not be 0")

        self.weight = weight
        self.required = required
        self.name = name

    def exclusive(self):
        return self.weight < 0
    def inclusive(self):
        return self.weight >= 0
    exclusive = property(exclusive)
    inclusive = property(inclusive)

    def _score_regex(self,password):
        match = self.rule.search(password)
        if match is None:
            if self.exclusive: # didn't match an exclusive rule
                return self.weight
            elif self.inclusive and self.required: # didn't match on a required inclusive rule
                raise SecurityException(u"Violation of Rule: %s by input \"%s\"" % (self.name.title(), password))
            elif self.inclusive and not self.required:
                return 0
        else:
            if self.inclusive:
                return self.weight
            elif self.exclusive and self.required:
                raise SecurityException(u"Violation of Rule: %s by input \"%s\"" % (self.name,password))
            elif self.exclusive and not self.required:
                return 0

        return 0

    def score(self,password):
        try:
            getattr(self.rule,"__call__")
        except AttributeError:
            return self._score_regex(password)
        else:
            return self.rule(password) * self.weight

    def __unicode__(self):
        return u"%s (%i)" % (self.name.title(), self.weight)

    def __str__(self):
        return self.__unicode__()

J'espère que quelqu'un trouvera cela utile!

Exemple d'utilisation:

rules = [ Rule("^foobar",weight=20,required=True,name=u"The Fubared Rule"), ]
try:
    score = 0
    for rule in rules:
        score += rule.score()
except SecurityException e:
    print e 
else:
    print score

AVERTISSEMENT: pas testé sur l'unité

Si vous avez le temps, lancez un cracker de mots de passe.

Les vérificateurs de la force du mot de passe, et si vous avez le temps + les ressources (sa justification s’applique uniquement si vous vérifiez plusieurs mots de passe), utilisez Rainbow Tables.

Avec une série de vérifications pour s'assurer qu'il répond aux critères minimaux:

  • au moins 8 caractères
  • contient au moins un symbole non alphanumérique
  • ne correspond pas ou ne contient pas nom d'utilisateur / email / etc.
  • etc

Voici un plugin jQuery qui indique la force du mot de passe (non essayé moi-même): http://phiras.wordpress.com / 2007/04/08 / plug-in-force-mètre-à-jquery /

Et la même chose a été portée en PHP: http://www.alixaxel.com/wordpress / 2007/06/09 / algorithme-mot-de-passe-php /

  

Quel est le meilleur moyen de s'assurer qu'un mot de passe fourni par l'utilisateur est un mot de passe fort dans un formulaire d'inscription ou de changement de mot de passe?

N'évaluez pas la complexité et / ou la force, les utilisateurs trouveront un moyen de duper votre système ou seront tellement frustrés qu'ils partiront. Cela ne vous conduira que dans des situations comme celle-ci . Exige juste une certaine longueur et que les mots de passe divulgués ne soient pas utilisés. Points bonus: assurez-vous que ce que vous mettez en place autorise l'utilisation de gestionnaires de mots de passe et / ou de 2FA.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top