Seite 2 von 4
Verfasst: Mittwoch 6. Dezember 2006, 16:44
von jens
Aha! Nun wird es mir klar, was du meinst, nach dem ich es mal in Python code gegossen hab:
Code: Alles auswählen
import time
from md5 import new as md5_new
def md5(txt):
return md5_new(txt).hexdigest()
salt = "s_%s" % time.time()
print "salt ist:", salt
print
print "In der DB ist gespeichert 'md5(salt + password)':"
db_md5pass = md5(salt + "Password")
print "db_md5pass:", db_md5pass
print
print "Server sendet challenge + salt zum client:"
challenge = "c_%s" % time.time()
print "challenge:", challenge
print
print "Client bildet 'md5(challenge + md5(salt + password))':"
client_response = md5(challenge + md5(salt + "Password"))
print "client_response:", client_response
print
print "Der Server vergleicht 'md5(challenge + db_md5pass)' mit 'db_md5pass':"
md5check = md5(challenge + db_md5pass)
print "md5check:", md5check
print
print "Login korrekt? ", md5check == client_response
So wie ich das sehe, hat das ganze allerdings einen Nachteil. In der DB werden zwar keine Klartext Passwörter gespeichert, aber zumindest die vollständigen Informationen mit dem man sich einloggen kann.
Will sagen, wenn jemand an diese Daten herran kommt, kann er sich mit den Informationen einloggen.
Durch den salt funktioniert das aber auch nur dort und nicht woanders. Aber immerhin.
Bei meiner aufwändigeren Variante, kann man mit den DB Daten IMHO nichts anfangen, weil es nur die Hälfte der nötigen Informationen sind.
Verfasst: Mittwoch 6. Dezember 2006, 16:50
von sape
jens hat geschrieben:[...]
Bei meiner aufwändigeren Variante, kann man mit den DB Daten IMHO nichts anfangen, weil es nur die Hälfte der nötigen Informationen sind.
So habe ich das auch verstanden und deshalb finde ich deine Idee auch wirklich super

Hat mMn bisher keine Forensoftware oder CMS so implementiert!
lg
Verfasst: Mittwoch 6. Dezember 2006, 17:56
von BlackJack
jens hat geschrieben:Bei meiner aufwändigeren Variante, kann man mit den DB Daten IMHO nichts anfangen, weil es nur die Hälfte der nötigen Informationen sind.
Solange Du das nicht beweisen kannst, ist diese Aussage "wertlos".
Irgendwie finde ich auch die Diagramme, frühere Beschreibungen und den vorhandenen Quelltext nicht wirklich zusammenpassend. Da ist mal von geraden/ungerade Buchstaben die Rede, mal von den ersten vier und dem Rest und in `userhandling.py` steht im Kommentar, dass das JS-MD-5 noch nicht implementiert ist, aber irgend etwas wird da ja gemacht.
In PyLucid mag ich mich jetzt nicht einarbeiten. Kannst Du das Verfahren mal isoliert als Skript zeigen. Vielleicht mit Anlegen eines Benutzers und Datenspeicherung in einem gepickleten Dictionary oder so.
Verfasst: Mittwoch 6. Dezember 2006, 18:36
von jens
BlackJack hat geschrieben:Kannst Du das Verfahren mal isoliert als Skript zeigen. Vielleicht mit Anlegen eines Benutzers und Datenspeicherung in einem gepickleten Dictionary oder so.
Hervorragende Idee... Werde ich morgen mal machen...
btw. vielen dank für deine Geduld mir das normale Verfahren aufzuzeigen

Verfasst: Mittwoch 6. Dezember 2006, 19:36
von mitsuhiko
Ich werfe mal
HMAC in den Raum.
Verfasst: Donnerstag 7. Dezember 2006, 07:58
von jens
So, ich hab mal mein Verfahren versucht möglichst einfach in Python Code zu gießen. Verständlicher wird es, wenn man sich die Ausgaben dazu anschaut (s.u.):
Code: Alles auswählen
from md5 import new as md5_new
def md5(txt):
return md5_new(txt).hexdigest()
def encrypt(txt, key): # Pseudo encrypt
return "encrypted %s with %s" % (txt, key)
def decrypt(txt, key): # Pseudo decrypt
txt, _, key2 = txt.split(" ", 3)[1:]
assert key == key2
return txt
print "\n\n------------ 1. Ein neuer User in der DB anlegen------------"
print "\n 1.1. Server sendet salt zum Client:",
salt = "s_123"
print "'%s'" % salt
print "\n 1.2. Eingabe des Passwortes auf dem Client:",
password = "Passwort"
print "'%s'" % password
print "\n 1.3. md5(password + salt):",
md5sum = md5(password + salt)
print "'%s'" % md5sum
print "\n 1.4. Übermittlung der MD5 Summe zum Server."
print "\n\n------------ 2. speichern des Users auf dem Server------------"
print "\n 2.1. Server trennt die MD5 in:",
md5_a = md5sum[:16]
md5_b = md5sum[16:]
print "md5_a: '%s' md5_b: '%s'" % (md5_a, md5_b)
print "\n 2.2. encrypt(md5_a, key=md5_b):",
md5checksum = encrypt(md5_a, key=md5_b)
print "'%s'" % md5checksum
print "\n 2.3. Speichern nur der verschlüsselten Checksum + salt\n"
print "_______________________________________________________________________"
print "\n\n------------ 3. Login eines Users------------"
print "\n 3.1. Server sendet salt '%s' + challenge zum client:" % salt,
challenge = "c_123"
print "'%s'" % challenge
print "\n 3.2. Eingabe des Passwortes auf dem Client:",
password = "Passwort"
print "'%s'" % password
print "\n 3.3. md5(password + salt):",
md5sum = md5(password + salt)
print "'%s'" % md5sum
print "\n 3.4. trennen der MD5 in:",
md5_a = md5sum[:16]
md5_b = md5sum[16:]
print "md5_a: '%s' md5_b: '%s'" % (md5_a, md5_b)
print "\n 3.5. md5_a2 = md5(md5_a + challenge):",
md5_a2 = md5(md5_a + challenge)
print "'%s'" % md5_a2
print "\n 3.6. Übermittlung von md5_a2 und md5_b."
print "\n\n------------ 4. check auf dem Server------------"
print "\n 4.1. aus der DB md5checksum: '%s'" % md5checksum
print "\n 4.2. decrypt(md5checksum, key=md5_b):",
md5checksum = decrypt(md5checksum, key=md5_b)
print "'%s'" % md5checksum
print "\n 4.3. md5(md5checksum + challenge):",
md5check = md5(md5checksum + challenge)
print "'%s'" % md5check
print "\n 4.4. Vergleich: %s == %s" % (md5check, md5_a2)
Die Asgaben:
------------ 1. Ein neuer User in der DB anlegen------------
1.1. Server sendet salt zum Client: 's_123'
1.2. Eingabe des Passwortes auf dem Client: 'Passwort'
1.3. md5(password + salt): '7522381eebd7c49a2522d09797ba20d2'
1.4. Übermittlung der MD5 Summe zum Server.
------------ 2. speichern des Users auf dem Server------------
2.1. Server trennt die MD5 in: md5_a: '7522381eebd7c49a' md5_b: '2522d09797ba20d2'
2.2. encrypt(md5_a, key=md5_b): 'encrypted 7522381eebd7c49a with 2522d09797ba20d2'
2.3. Speichern nur der verschlüsselten Checksum + salt
_______________________________________________________________________
------------ 3. Login eines Users------------
3.1. Server sendet salt 's_123' + challenge zum client: 'c_123'
3.2. Eingabe des Passwortes auf dem Client: 'Passwort'
3.3. md5(password + salt): '7522381eebd7c49a2522d09797ba20d2'
3.4. trennen der MD5 in: md5_a: '7522381eebd7c49a' md5_b: '2522d09797ba20d2'
3.5. md5_a2 = md5(md5_a + challenge): 'd3510bc87cf09bd7df69d180805e76fa'
3.6. Übermittlung von md5_a2 und md5_b.
------------ 4. check auf dem Server------------
4.1. aus der DB md5checksum: 'encrypted 7522381eebd7c49a with 2522d09797ba20d2'
4.2. decrypt(md5checksum, key=md5_b): '7522381eebd7c49a'
4.3. md5(md5checksum + challenge): 'd3510bc87cf09bd7df69d180805e76fa'
4.4. Vergleich: d3510bc87cf09bd7df69d180805e76fa == d3510bc87cf09bd7df69d180805e76fa
Zu beachten ist, die verschlüsselte MD5 Summe wird bei Punkt 2.3 und 4.1. anhand des Usernamen in der DB gespeichert bzw. gelesen.
Wie man sieht ist in der DB nur die hälfte der MD5 Summe gespeichert (Punkt 2.3) und das auch noch verschlüsselt mit der anderen hälft.
Wenn jemand also an die DB Daten kommt, kann er damit nichts anfangen. Das wäre anders, wenn ich auf die Verschlüsselung verzichte.
EDIT: Noch ein Hinweis. In genau der Form ist es z.Z. auch in PyLucid nicht implementiert. Zwar sehr ähnlich, aber nicht ganz. Mir ist ja erst durch diesen Thread aufgefallen, das man das Verfahren noch etwas optimieren kann

Ich werde das aber erst so wie hier implementieren, wenn ein "Passwort reset" möglich ist
Im übrigen steht im Wiki unter [wiki]JensDiemer/CryptoIdee[/wiki] noch eine andere Idee, einses noch sicheren Verfahren, was auf
http://de.wikipedia.org/wiki/Diffie-Hellman beruht. Da es Diffie-Hellman nicht als fertiges JavaScript gibt hat sich das aber erledigt. Außerdem ist das Verfahren bei einem man-in-the-middle auch nicht sicher. Zudem kommt noch das es wohl eindeutig Overkill ist, in anbedracht von Session-Hijacking

Verfasst: Donnerstag 7. Dezember 2006, 17:20
von BlackJack
jens hat geschrieben:Wie man sieht ist in der DB nur die hälfte der MD5 Summe gespeichert (Punkt 2.3) und das auch noch verschlüsselt mit der anderen hälft.
Wenn jemand also an die DB Daten kommt, kann er damit nichts anfangen. Das wäre anders, wenn ich auf die Verschlüsselung verzichte.
Kann ich mir, wenn ich die DB-Daten habe, nicht einfach irgendeinen Schlüssel ausdenken? Wenn ich die DB-Daten damit entschlüssele, dann habe ich zwei Hälften die ich für ein Login verwenden kann und die der Prüfung standhalten.
Verfasst: Donnerstag 7. Dezember 2006, 18:00
von jens
BlackJack hat geschrieben:Kann ich mir, wenn ich die DB-Daten habe, nicht einfach irgendeinen Schlüssel ausdenken? Wenn ich die DB-Daten damit entschlüssele, dann habe ich zwei Hälften die ich für ein Login verwenden kann und die der Prüfung standhalten.
Hm. Interessante Frage... Aber ich glaube: "nein".
Es kommt auf das Verschlüsselungsverfahren an. In frage kommen ja DES bzw. Rijndael, siehe:
http://www.python-forum.de/topic-8075.html
Wie soll man also die Daten so einfach entschlüsseln, es dürfte nur der eine richtige Schlüssel passen. Also müsste man ein BruteForce versuchen um den richtigen Key zu finden.
Oder hab ich da einen Denkfehler?
Verfasst: Donnerstag 7. Dezember 2006, 19:36
von BlackJack
jens hat geschrieben:Wie soll man also die Daten so einfach entschlüsseln, es dürfte nur der eine richtige Schlüssel passen. Also müsste man ein BruteForce versuchen um den richtigen Key zu finden.
Es geht ja gar nicht darum das "Original" zu herauszufinden. Ich kann `decrypt()` doch einfach mit einem zufälligen Schlüssel `b` auf den verschlüsselten Eintrag loslassen und bekomme damit etwas das ich mal `a` nenne. Mit diesen beiden Werten müsste jetzt eine Authentifizierung möglich sein. Client bekommt `challenge` und sendet `hash(a + challenge)` und `b` an Server. Der entschlüsselt den Eintrag mit `b`, bekommt `a` heraus und prüft ob `hash(a + challenge)` gleich dem gesendeten ist. Ist es -> Bingo.

Verfasst: Freitag 8. Dezember 2006, 07:40
von jens
BlackJack hat geschrieben:Ich kann `decrypt()` doch einfach mit einem zufälligen Schlüssel `b` auf den verschlüsselten Eintrag loslassen und bekomme damit etwas das ich mal `a` nenne.
Nein. decrypt() sollte eine Exception liefern, wenn der Key nicht der richtige ist.
z.Z. bei meiner XOR Variante, habe ich deswegen ja auch den hash() und jetzt die MD5() in den encrypteten Daten drin.
d.h. es wird zwar die XOR Operartion immer gemacht, egal welcher Key, aber danach muß die checksumme auch stimmen und das tut sie nicht, wenn der Key ein falscher war.
Mit DES bzw. Rijndael statt einem XOR, dürfte IMHO die Entschlüsselung nie mit einem falschen Key gehen. Aber das muß ich noch testen, ob ich da auch mit checksummen arbeiten muß.
Verfasst: Freitag 8. Dezember 2006, 11:25
von BlackJack
jens hat geschrieben:Nein. decrypt() sollte eine Exception liefern, wenn der Key nicht der richtige ist.
z.Z. bei meiner XOR Variante, habe ich deswegen ja auch den hash() und jetzt die MD5() in den encrypteten Daten drin.
d.h. es wird zwar die XOR Operartion immer gemacht, egal welcher Key, aber danach muß die checksumme auch stimmen und das tut sie nicht, wenn der Key ein falscher war.
Ah, okay. Dann ist der einzige Vorteil wenn man den DB-Inhalt kennt, dass man in aller Ruhe lokal/verteilt Schlüssel durchprobieren kann. Direkt mit einem Suchraum von 2**64. Nicht so praktikabel, also wird man am schwächsten Glied, dem Benutzerpasswort angreifen, und es mit einem Wörterbuchangriff versuchen.
Mit DES bzw. Rijndael statt einem XOR, dürfte IMHO die Entschlüsselung nie mit einem falschen Key gehen. Aber das muß ich noch testen, ob ich da auch mit checksummen arbeiten muß.
Doch da musst Du auch ein Signatur irgendwo speichern, wenn Du das Ergebnis der Entschlüsselung testen möchtest.
Verfasst: Freitag 8. Dezember 2006, 12:00
von jens
Ja gut einen Wörterbuchangriff kann man wohl nie verhindern
Du hast recht, es ist "nur" ein Suchraum von 2**64, weil es ja nur eine halbe MD5 Summe ist. Aber egal. Das ist immerhin eine Zahl mit 20 Stellen und dürfte erstmal reichen

Verfasst: Mittwoch 20. Dezember 2006, 08:58
von Leonidas
Irgendwie erinnert mich das ganze Konzept etwas an
aSSL welches Fefe
verrissen hat 
Verfasst: Mittwoch 20. Dezember 2006, 11:21
von jens
Es ist allerdings schon etwas anderes... Dort wird versucht Daten wirklich zu verschlüsseln um diese hin und her schicken zu können.
Ich arbeite dagegen nur an einer sichereren Authentifizierung mit Hilfe von MD5 Checksummen.
Eine Verschlüsselung brauche ich nur auf dem Server und diese dient nur zum vergleichen der MD5 summen. Also um zu prüfen ob das ursprünglich eingegebene Passwort auch wirklich richtig ist.
Im übrigen werde ich die Tage eine erste Alpha Version mit dem neuen auth Modul fertig haben

Verfasst: Mittwoch 20. Dezember 2006, 17:47
von jens
So, in der neuen v0.7.2alpha ist es nun genau so verwirklicht, wie hier skizziert:
http://pylucid.net/trac/browser/trunk/t ... gin_doc.py
Verfasst: Freitag 9. Februar 2007, 15:10
von jens
Was man nicht so alles im Netz findet:
http://pajhome.org.uk/crypt/md5/auth.html
Sehr Interessant... Hätte ich die Seite mal vorher gekannt...
Dort gibt es auch ein SHA-1 in JavaScript...
Verfasst: Freitag 9. Februar 2007, 17:57
von Y0Gi
jens hat geschrieben:Ja gut einen Wörterbuchangriff kann man wohl nie verhindern

Verhindern nicht, aber stark einschränken auf jeden Fall: Nach mehreren fehlgeschlagenen Versuchen kann man den Account für eine gewisse Zeitspanne oder dauerhaft bis zur Freischaltung per Email oder durch einen Administrator sperren.
Und natürlich mit Passwörtern, die nicht in Wordlists stehen (auch nicht teilweise).
jens hat geschrieben:Dort gibt es auch ein SHA-1 in JavaScript...
Wow, interessante Idee einen Sicherheitsmechanismus davon abhängig zu machen, dass etwas anderes aktiviert sein muss, das zudem auch noch die Sicherheit gefährdet.
Edit: Hmm, der gute Autor von aSSL scheint auch ein Problem mit seinen Redirects zu haben. Wenn ich Fefes Link auf
http://assl.sullof.com/assl/howitworks.asp folge, wird die URL zu
dieser (1812 Zeichen lang...) umgewandelt bis es einen Abbruch wegen fehlerhafter Redirection gibt. Na gut.
Verfasst: Montag 12. Februar 2007, 08:56
von jens
Y0Gi hat geschrieben:Nach mehreren fehlgeschlagenen Versuchen kann man den Account für eine gewisse Zeitspanne oder dauerhaft bis zur Freischaltung per Email oder durch einen Administrator sperren.
Das werde ich auf jeden Fall demnächst realisieren. Da PyLucid allerdings es als CGI läuft, gibt es so oder so ein Limit der Request-Anfragen. Somit ist es jetzt auch Sinnlos einen Bruteforce zu versuchen.
Eine grobe Schätzung mit meinem
simple_web_bench zu urteilen, kann der Server ca. 3 Request pro Sekunden verarbeiten. Dabei wird allerdings nur das Login Formular geholt und nicht ausgewertet. Die Auswertung dürfte wahrscheinlich noch etwas weniger sein.
Ich vermute das es eh ein Limit von Apache aus gibt, das bei einem Bruteforce/DOS zum tragen kommt...
Y0Gi hat geschrieben:Und natürlich mit Passwörtern, die nicht in Wordlists stehen (auch nicht teilweise).
Naja, Was soll man machen, wenn die User ein super einfaches Passwort nehmen? Pauschal eine google Suche machen und dann warnen, wenn zuviele Treffe auftauchen???
Das wäre zwar nett, aber dann verrät man das Passwort immer google, was bescheuert wäre
Y0Gi hat geschrieben:jens hat geschrieben:Dort gibt es auch ein SHA-1 in JavaScript...
Wow, interessante Idee einen Sicherheitsmechanismus davon abhängig zu machen, dass etwas anderes aktiviert sein muss, das zudem auch noch die Sicherheit gefährdet.
Hä? Wie meinst du das denn jetzt???
Ich könnte halt das JS-MD5 Skript mit dem SHA-1 tauschen. Bringt zwar auch keinen mehrgewinn, aber ist netter

Verfasst: Montag 12. Februar 2007, 09:56
von N317V
jens hat geschrieben:Naja, Was soll man machen, wenn die User ein super einfaches Passwort nehmen? Pauschal eine google Suche machen und dann warnen, wenn zuviele Treffe auftauchen???
Das wäre zwar nett, aber dann verrät man das Passwort immer google, was bescheuert wäre

Schonmal was von
John, the Ripper gehört?
Verfasst: Montag 12. Februar 2007, 10:21
von jens
Ja, und was willst du mir damit sagen???