Passwortstärke ermitteln

chmee

verstaubtes inventar
Premium-User
Hellau, Mädels und Jungs.. Mal wieder ich mit einer übergreifenden Frage:

Wie würdet Ihr die Stärke eines Passworts ermitteln?

Ich hab gestern abend -eher zum Spaß- mal daran gesessen. Wörterbuchvergleiche sollte man wohl vergessen. Jetzt würd ich gerne mal hören, welche Schwerpunkte beim Bemessen der Stärke Ihr einfließen lassen würdet..

Mein Ergebnis ist hier Online : http://www.phreekz.de/DLS/tutorials/pwtest/

Interessante Vergleiche:
Lisa1986 - Wertung 1 - schrecklich
Lisa196 - Wertung 17 - nicht besonders
lisa196 - Wertung 8 - schrecklich
liSa196 - Wertung 113 - recht gut
liSa196D - Wertung 168 - sicher!

Ein Passwort wie ruf12345 bekommt auch nur 6 Punkte.
aje8d629 ist knapp ok mit 19 Punkten, dennoch sieht aje8d629 besser aus als Lisa196.

Der php-code sieht so aus:
PHP:
<?php
if($_POST['pw'])
{ $password=$_POST['pw']; 
 $pw_strength=0;$pw_strength_b=0;$pw_strength_s=0;$pw_strength_c=0;$pw_strength_word=0;
 $length=strlen($password);

// ---- Tastaturreihenabfrage noch nicht eingebaut.
 $typo="qwertzuiopasdfghjklyxcvbnm";
 $typorev=strrev($typo);

 // ----- Vorkommen von Kleinbuchstaben,Großbuchstaben, Zahlen und Sonderzeichen
 preg_match_all ("([A-Z]+)", $password, $matches);
 $pw_strength_b+=count($matches[0]);
 preg_match_all ("([a-z]+)", $password, $matches);
 $pw_strength_s+=count($matches[0]);
 preg_match_all ("([0-9]+)", $password, $matches);
 $pw_strength_c+=count($matches[0]);
 preg_match_all('/[^A-Za-z0-9]+/',$password,$matches);
 $pw_strength_u+=count($matches[0])*2;
 
 // ----- Zeichenvorrat bewerten
 if(	( $pw_strength_b!=0)||($pw_strength_s!=0)||($pw_strength_c!=0)||($pw_strength_u!=0) )
	{ $pw_strength = $pw_strength_b*0.9+$pw_strength_s*0.6+$pw_strength_c*0.6+$pw_strength_u*1.5; }

 if(	(($pw_strength_b!=0)&&($pw_strength_s!=0))&&($pw_strength_c!=0)||($pw_strength_u!=0))
	{ $pw_strength=3.3*($pw_strength_b*1.5+$pw_strength_s*1.2+$pw_strength_c+$pw_strength_u);}

 if(	($pw_strength_b!=0)&&($pw_strength_s!=0)&&($pw_strength_c!=0)&&($pw_strength_u!=0))
	{ $pw_strength=4*($pw_strength_b+$pw_strength_s+$pw_strength_c+$pw_strength_u);}

 if(	(($pw_strength_b!=0)&&($pw_strength_s==0)&&($pw_strength_c==0)&&($pw_strength_u==0))
	||
	(($pw_strength_b==0)&&($pw_strength_s!=0)&&($pw_strength_c==0)&&($pw_strength_u==0))
	||
	(($pw_strength_b==0)&&($pw_strength_s==0)&&($pw_strength_c!=0)&&($pw_strength_u==0))
	||
	(($pw_strength_b==0)&&($pw_strength_s==0)&&($pw_strength_c==0)&&($pw_strength_u!=0)))
	{ $pw_strength=$pw_strength_b+$pw_strength_s+$pw_strength_c+$pw_strength_u*4; }
 if( 	$pw_strength_u!=0)
	{$pw_strength=$pw_strength*2;}

 // ----- Vorkommen von Wiederholungen oder Aufzaehlungen (Zahlen schwaecher bewertet)
 $nexloop=0;$sameloop=0;$decloop=0;
 if($length>1){
  for($i=1;$i<$length;$i++)
  { 	$zeichen_j=ord($password[$i]);
	$zeichen_d=ord($password[$i-1]);
	if($zeichen_j==$zeichen_d){if(ord($password[$i])>64){$sameloop=$sameloop+2;}else{$sameloop++;}}
   	if($zeichen_j==(1+$zeichen_d)){if($zeichen_j>64){$nexloop=$nexloop+3;}else{$nexloop++;}}
   	if($zeichen_j==($zeichen_d-1)){if($zeichen_j>64){$decloop=$decloop+2;}else{$decloop++;}}
  }
 }
 $loop=1+($sameloop*0.2+$nexloop*0.1+$decloop*0.1);

// ----- Wörter mit Großbuchstaben und mind 3.kleinbuchstaben negativ werten
	preg_match_all('/[A-Z]{1}+[a-z]{3,}+/', $password, $matches);
	$pw_strength_word=count($matches[0])*5;
	if($pw_strength_word!=0){$pw_strength=$pw_strength/$pw_strength_word;} 


if($loop>0)
 { $pw_strength=$length*$pw_strength/$loop;} 
 else
 { $pw_strength=$length*$pw_strength; }

// ----- Länge bewerten
 if($length<4){$pw_strength=$pw_strength/2;}
 if($length<7){$pw_strength=$pw_strength/2;}
 if($length>9){$pw_strength=$pw_strength*1.4;}

// ----- Jahreszahl enthalten
 for($jahr=1910;$jahr<2010;$jahr++){if(strpos($password,(string)$jahr)!=null){$pw_strength=$pw_strength/10;$jahr=2011;}}
}
else
{$pw_strength=0;}

echo $pw_strength;
?>


Andere Codes zB

Schloebe - Test - Source
Andere Codes - Hier - Hier - Hier

mfg chmee
 
Hi,

puh, schwer zu lesen der Code. :)
Was mir fehlt ist eine Bewertung von Sonderzeichen, falls vorhanden. Oder übersehe ich dies?

//edit

Ok, das habe ich in der Tat übersehen, nachdem ich den Code etwas aufgeräumt habe.


Die Bewertung derPasswortlänge könntest du noch erweitern für >12 und >18 oder so.


(Für alle die auch Probleme mit dem Code haben)
PHP:
<?php
if ($_POST['pw']) {
	$password = $_POST['pw'];
	$pw_strength = 0;
	$pw_strength_b = 0;
	$pw_strength_s = 0;
	$pw_strength_c = 0;
	$pw_strength_word = 0;
	$length = strlen($password);

	// ---- Tastaturreihenabfrage noch nicht eingebaut.
	$typo = 'qwertzuiopasdfghjklyxcvbnm';
	$typorev = strrev($typo);

	// ----- Vorkommen von Kleinbuchstaben,Großbuchstaben, Zahlen und Sonderzeichen
	preg_match_all('([A-Z]+)', $password, $matches);
	$pw_strength_b += count($matches[0]);
	preg_match_all('([a-z]+)', $password, $matches);
	$pw_strength_s += count($matches[0]);
	preg_match_all('([0-9]+)', $password, $matches);
	$pw_strength_c += count($matches[0]);
	preg_match_all('/[^A-Za-z0-9]+/', $password, $matches);
	$pw_strength_u += count($matches[0]) * 2;

	 // ----- Zeichenvorrat bewerten
	if (($pw_strength_b != 0)
			|| ($pw_strength_s != 0)
			|| ($pw_strength_c != 0)
			|| ($pw_strength_u != 0)) {
		$pw_strength = $pw_strength_b * 0.9 + $pw_strength_s * 0.6 + $pw_strength_c * 0.6 + $pw_strength_u * 1.5;
	}
	if ((($pw_strength_b != 0)
			&& ($pw_strength_s != 0))
		&& ($pw_strength_c != 0)
			|| ($pw_strength_u != 0)) {
		$pw_strength = 3.3 * ($pw_strength_b * 1.5 + $pw_strength_s * 1.2 + $pw_strength_c + $pw_strength_u);
	}
	if (($pw_strength_b != 0)
			&& ($pw_strength_s != 0)
			&& ($pw_strength_c != 0)
			&& ($pw_strength_u != 0)) {
		$pw_strength = 4 * ($pw_strength_b + $pw_strength_s + $pw_strength_c + $pw_strength_u);
	}
	if ((($pw_strength_b != 0)
			&& ($pw_strength_s == 0)
			&& ($pw_strength_c == 0)
			&& ($pw_strength_u == 0))
		|| (($pw_strength_b == 0)
			&& ($pw_strength_s != 0)
			&& ($pw_strength_c == 0)
			&& ($pw_strength_u == 0))
		|| (($pw_strength_b == 0)
			&& ($pw_strength_s == 0)
			&& ($pw_strength_c != 0)
			&& ($pw_strength_u == 0))
		|| (($pw_strength_b == 0)
			&& ($pw_strength_s == 0)
			&& ($pw_strength_c == 0)
			&& ($pw_strength_u != 0))) {
		$pw_strength = $pw_strength_b + $pw_strength_s + $pw_strength_c + $pw_strength_u * 4;
	}
	if ($pw_strength_u != 0) {
		$pw_strength = $pw_strength * 2;
	}

	// ----- Vorkommen von Wiederholungen oder Aufzaehlungen (Zahlen schwaecher bewertet)
	$nexloop = 0;
	$sameloop = 0;
	$decloop = 0;
	if ($length > 1) {
		for ($i=1; $i < $length; $i++) {
			$zeichen_j = ord($password[$i]);
			$zeichen_d = ord($password[$i - 1]);
			if ($zeichen_j == $zeichen_d) {
				if (ord($password[$i]) > 64) {
					$sameloop = $sameloop + 2;
				} else {
					$sameloop++;
				}
			}
			if ($zeichen_j == (1 + $zeichen_d)) {
				if ($zeichen_j > 64) {
					$nexloop = $nexloop + 3;
				} else {
					$nexloop++;
				}
			}
			if ($zeichen_j == ($zeichen_d - 1)) {
				if ($zeichen_j > 64) {
					$decloop = $decloop + 2;
				} else {
					$decloop++;
				}
			}
		}
	}
	$loop = 1 + ($sameloop * 0.2 + $nexloop * 0.1 + $decloop * 0.1);

	// ----- Wörter mit Großbuchstaben und mind 3.kleinbuchstaben negativ werten
	preg_match_all('/[A-Z]{1}+[a-z]{3,}+/', $password, $matches);
	$pw_strength_word = count($matches[0]) * 5;
	if ($pw_strength_word != 0) {
		$pw_strength = $pw_strength / $pw_strength_word;
	} 
	if ($loop > 0) {
		$pw_strength = $length * $pw_strength / $loop;
	} else {
		$pw_strength = $length * $pw_strength;
	}

	// ----- Länge bewerten
	if ($length < 4) {
		$pw_strength = $pw_strength / 2;
	}
	if ($length < 7) {
		$pw_strength = $pw_strength / 2;
	}
	if ($length > 9) {
		$pw_strength = $pw_strength * 1.4;
	}

	// ----- Jahreszahl enthalten
	for ($jahr = 1910; $jahr < 2010; $jahr++) {
		if (strpos($password, (string)$jahr) != null) {
			$pw_strength = $pw_strength / 10;
			$jahr = 2011;
		}
	}
} else {
	$pw_strength = 0;
}

echo $pw_strength;
?>

Hoffe ich habe keine Copy&Paste Fehler gemacht :p
 
Zuletzt bearbeitet:
Im ersten Block letztes preg_match Nicht-Buchstaben&&Zahlen = alle übrigen Zeichen. Und im darauf folgenden If-Block pw_strength_u, das sind die Sonderzeichen.

Aber Du hast Recht, besonders gut zu lesen ist es nicht. Jedenfalls geht es mir nicht nur um meinen Code, sondern eher um Algorithmen, wie man zB Worte ohne Wörterbuch erkennen könnte.

Ich habe hier etwas eingebaut, dass 1. nach Buchstabenfolgen länger 3 mit erstem Großbuchstaben sucht und 2. auch Jahreszahlen zwischen 1915 und 2012 negativ bewertet, somit werden Passworte wie Julia1995 schlecht bewertet (typische Merkpassworte von Nachfahren). In einer Registriermaske würde auch der Username/Vor-Nachname in die Bewertung als Negativfolge reinfallen.

mfg chmee
 
Ich werd mal grad n bissel aufhübschen. Hoffe, es wird schöner :D

So, Code n bissel nachgebessert, essentiell sieht das schon ganz gut aus:
PHP:
<?php
// -------- pw strength -----------
// -- Input pw POST string --------
// -- Output $pw_strength int 0+ --

if($_POST['pw'])
{ $password=$_POST['pw']; 
  $length=strlen($password);
  
  $pw_strength=0;
  $pw_grossb=0;
  $pw_kleinb=0;
  $pw_zahlen=0;
  $pw_sonderz=0;
  $pw_strength_word=0;

// ----- Tastaturfolgen noch nicht benutzt  
  $typo="qwertzuiopasdfghjklyxcvbnm";
  $typorev=strrev($typo);

// ----- Vorkommen von Kleinbuchstaben,Großbuchstaben, Zahlen und Sonderzeichen
  preg_match_all ("([A-Z]+)", $password, $matches);
  $pw_grossb+=count($matches[0]);
  
  preg_match_all ("([a-z]+)", $password, $matches);
  $pw_kleinb+=count($matches[0]);
  
  preg_match_all ("([0-9]+)", $password, $matches);
  $pw_zahlen+=count($matches[0]);
  
  preg_match_all('/[^A-Za-z0-9]+/',$password,$matches);
  $pw_sonderz+=count($matches[0])*2;
 
 // ----- Existenz überpüfen
 $ist_gross=$pw_grossb!=0;
 $ist_klein=$pw_kleinb!=0;
 $ist_zahl=$pw_zahlen!=0;
 $ist_sonder=$pw_sonderz!=0;

 // ----- Alle Zeichenarten ODER
 if(($ist_gross)||($ist_klein)||($ist_zahl)||($ist_sonder) )
	{ $pw_strength = $pw_grossb+$pw_kleinb+$pw_zahlen+$pw_sonderz*1.5; }

 // ----- Gross UND Klein ODER zahl ODER sonder
 if( (($ist_gross)&&($ist_klein))||($ist_zahl)||($ist_sonder))
	{ $pw_strength = 1.5*($pw_grossb+$pw_kleinb+$pw_zahlen+$pw_sonderz*1.5);}

 // ----- Alle Zeichenarten UND
 if(($ist_gross)&&($ist_klein)&&($ist_zahl)&&($ist_sonder))
	{ $pw_strength = 3*($pw_grossb+$pw_kleinb+$pw_zahlen+$pw_sonderz+1.5);}

 // ----- Nur eine Zeichenart
 if(	
   (($ist_gross)&&(!$ist_klein)&&(!$ist_zahl)&&(!$ist_sonder))
	||
   ((!$ist_gross)&&($ist_klein)&&(!$ist_zahl)&&(!$ist_sonder))
	||
   ((!$ist_gross)&&(!$ist_klein)&&($ist_zahl)&&(!$ist_sonder))
	||
   ((!$ist_gross)&&(!$ist_klein)&&(!$ist_zahl)&&($ist_sonder))
   )
     {
	$pw_strength = $pw_grossb+$pw_kleinb+$pw_zahlen+$pw_sonderz*4;
     }
 
 // ----- Sonderzeichen nochmal belohnen
 if($ist_sonder)
	{
	$pw_strength=$pw_strength*2;
	}

 // ----- Vorkommen von Wiederholungen oder Aufzaehlungen (Zahlen schwaecher bewertet)
 $nexloop=0;$sameloop=0;$decloop=0;
 
 // Wenn Länge höher 1 -> Folgezeichen bewerten 
 // aa,2222, bc,234, cba,87 negative Bewertung
 if($length>1){
    for($i=1;$i<$length;$i++)
    { 	
	$zeichen_j=ord($password[$i]);
	$zeichen_d=ord($password[$i-1]);
	if($zeichen_j==$zeichen_d)
		{
		if($zeichen_j>64)
			{$sameloop=$sameloop+2;}
			else
			{$sameloop++;}
		}
   	if($zeichen_j==($zeichen_d-1))
		{
		if($zeichen_j>64)
			{$nexloop=$nexloop+3;}
			else
			{$nexloop++;}
		}
   	if($zeichen_j==(1+$zeichen_d))
		{
		if($zeichen_j>64)
			{$decloop=$decloop+2;}
			else
			{$decloop++;}
		}
    }
 }
 $loop=1+($sameloop*0.2+$nexloop*0.1+$decloop*0.1);
 $pw_strength=$length*$pw_strength/$loop;

// ----- Wörter mit Großbuchstaben und mind 3.kleinbuchstaben besonders werten
   preg_match_all('/[A-Z]{1}+[a-z]{3,}+/', $password, $matches);
   $pw_strength_word=count($matches[0])*5;
   if($pw_strength_word!=0)
	{
	$pw_strength=$pw_strength/$pw_strength_word;
	} 

// ----- Länge bewerten
 if($length<4)
	{
	$pw_strength=$pw_strength/2;
	}
 if($length<8)
	{
	$pw_strength=$pw_strength/2;
	}
 if($length>12)
	{
	$pw_strength=$pw_strength*2;
	}

// ----- Jahreszahl enthalten?
 for($jahr=1920;$jahr<2010;$jahr++)
	{
	if(strpos($password,(string)$jahr)!=null)
		{
		$pw_strength=$pw_strength/10;
		$jahr=2011;
		}
	}
}
else
{
 $pw_strength=0;
}

echo (int)$pw_strength;
?>
Der Link immer noch : http://www.phreekz.de/DLS/Tutorials/pwtest

Lisa1986 - Wertung 0 - schrecklich
Lisa196 - Wertung 3 - schrecklich
lisa196 - Wertung 10 - schrecklich
liSa196 - Wertung 21 - mittel
liSa196D - Wertung 60 - recht gut

ruf12345 - Wertung 17 - naja
aje8d629 - Wertung 48 - ok
iMaN740D! - Wertung 512 - absolut sicher
chmee74$tutAdMin - Wertung 1016 - absolut sicher

mfg chmee
 
Ich halte von solchen Analysen nicht viel. Allein die Länge eines Passworts und das Vermeiden von bekannten Wörtern verringert die Möglichkeit eines erfolgreichen Angriffs.

Und auch das Authentifizierungssystem selbst muss gegen Angriffe gewappnet sein. So sollten etwa Massen-Authentifizierungsanfragen erkannt und blockiert werden. Eine gute Vorgehensweise ist es beispielsweise, für jedes Konto eine Wartezeit zwischen Authentifizierungsanfragen einzustellen, die mit der Anzahl der Fehlschläge exponentiell wächst (also etwa 2^n Sekunden).

Lesenswert in diesem Zusammenhang:
 
Ja, Begründung ist klar (und ist im Stärkemeter ja nicht das Thema an sich). Der Stärkemeter ist lediglich eine visuelle Lehrinstanz für jene, die bis Dato schwache Passwörter benutzt haben und bis Dato keinen Wert darauf gelegt haben - weiterhin ist sowas nett anzuschauen. Alle weiteren Mechanismen, Wartezeitverlängerung exponentiell oder Bot-Aktivität mit Image-Captchas abfangen sind weitere - in der Tat wichtige Werkzeuge.

Habe mal testweise die Passwörter aus dem 2. Beitrag bei mir getestet :D Da ist meiner aber n bissel happiger. ergs43 gehört bei mir noch zu den riskanten Passwörtern (wobei es praktisch sicherlich schon stark genug ist). Und auch die Grundaussage - ein schwer hackbares Passwort kann auch lesbar sein - unterschreibe ich vollkommen. Nur das ist die Aufgabe des Formdesigners, so eine Kurzinfo reinzuhauen, die solche Tipps gibt. this is fun bekommt bei mir auch das Prädikat secure.

mfg chmee
 
Der Stärkemeter ist lediglich eine visuelle Lehrinstanz für jene, die bis Dato schwache Passwörter benutzt haben und bis Dato keinen Wert darauf gelegt haben - weiterhin ist sowas nett anzuschauen.
Hier gehst du wieder davon aus, dass ein Kennwort nur dann gut ist, wenn das Kennwort jeweils mindestens ein Kleinbuchstabe, Großbuchstabe, Zahlzeichen und ein sonstiges Symbol enthält. Aber das ist nicht unbedingt der Fall.

Nehmen wir mal „Aa0,“ als Beispiel, das alle genannten Kriterien erfüllt und dadurch 78 Punkte erreicht. Das ist aber keinesfalls besser als etwa ein einfaches fünfstelliges Kennwort wie „qinud“ (2 Punkte), das rein statistisch gesehen bei einem Brute-Force-Angriff länger braucht berechnet zu werden.

Der Ratschlag, mindestens jeweils ein Zeichen der Zeichengruppen zu verwenden, hilft nur für den Fall eines Bulk-Guessing-Angriffs, bei dem also ein beliebiges Kennwort auf alle Benutzer geprüft wird. Denn wer hier die Zeichen streut, sich also einer größeren Zeichenmenge bedient, läuft auch weniger Gefahr, dass sein gewähltes Kennwort ebenfalls vom Angreifer gewählt wird, da dieser – wenn wir mal alle bekannten Wörter von Vornherein außen vor lassen – wohl eher eine kleine Zeichenmenge zur Generierung seines Kennworts verwendet, um damit die Chance einer Kollision zu erhöhen. Schließlich gibt es eine Menge Leute, die dennoch nur Kleinbuchstaben verwenden. Ein solcher Angriff sollte aber vom System erkannt werden.
 
Hm, Deine Ausführungen sind absolut ok. Wenn ich in meinem Meter Aa0 eingebe erscheint 3. Bei qinud lediglich 2. Beide sind nach meiner Scriptbewertung absolut kritisch. Ganz ok wird hingegen SeBaStIaN bewertet. Nach meinem Script müssen also nicht alle "Symbolformen" gemischt werden, aber gemischte Passphrasen ergeben einen sichere(re)n Schutz bei kürzerer Phrasenwahl.

mfg chmee
 

Neue Beiträge

Zurück