Passwort-Verschlüsselung mit JavaScript
lima-city → Forum → Die eigene Homepage → HTML, CSS & Javascript
abfangen
angreifer
anmelden
code
datenbank
datum
http
inhalt
jemand
kennen
klartext
login
message
problem
server
stehen
string
type
url
zugang
-
Hallo Community,
vorab an die Mods und Admins: Das soll hier kein Thread zum Thema "Wir brauchen https: bei Lima" werden. Die Gründe dagegen wurden ausführlich und verständlich diskutiert. Jedoch haben mich die Threads der letzten Tage inspiriert, mal ein wenig nach Alternativen zu suchen. Und da diese Threads ein generelles Interesse zeigen, poste ich hier mal meinen Lösungsansatz.
Ich habe auf meiner Seite ein Login, damit Freunde Zugang zu privateren Daten bekommen. Allerdings wird hier bei der Anmeldung das Passwort durch die fehlende Verschlüsselung im Klartext übertragen und könnte rein theoretisch von anderen mitgelesen werden. Das Passwort ist in der Datenbank als MD5-Hash gespeichert und im Prinzip wurde bislang immer das eingegebene Passwort wie folgt verglichen:
if(md5($_POST['passwd'])==mysql->passwort) $zugang = true;
Das Klartext-Passwort wird zum Abgleich serverseitig mit MD5 umgewandelt. Also habe ich im Internet nach Möglichkeiten gesucht, dieses bereits auf der Clientseite durchzuführen (u.a. auch mit dem Gedanken, dieses mit OpenSSL zu lösen. Das hat aber leider nicht geklappt). Bei SELFHTML bin ich fündig geworden und habe die dort beschriebenen Anleitungen umgesetzt.
Bestandteil ist die MD5-JavaScript Klasse, die bei SELFHTML veröffentlicht ist http://aktuell.de.selfhtml.org/artikel/javascript/md5/
Das Loginformular wandelt das Passwort vor dem Absenden in den passenden MD5 String um, sofern JavaScript aktiviert ist. Wenn nicht, wird es offen übertragen.
loginformular.php
// JavaScript zum verschlüsselten Anmelden aufbauen $javascript_hinweis = ($_GET['plain']==1) ? "Du hast die unverschlüsselte Übertragung Deines Passwortes gewählt. Dieses stellt ein Sicherheitsrisiko dar." : "<a href='".$_SERVER['SCRIPT_NAME']."?aktion=login&plain=1'>Probleme beim Anmelden?<br>Benutze die unsichere, unverschlüsselte Variante!</a>"; $ausgabe = "<html><head> <script language=\"javascript\" type=\"text/javascript\" src=\"md5.js\"></script>\n <script language=\"javascript\" type=\"text/javascript\"> function ersetzeHinweis() { document.getElementById('loginhinweis').innerHTML = \"$javascript_hinweis\"; } </script> </head> <body onload=\" ersetzeHinweis();\"> <form name='login' method='post' action='".$_SERVER['SCRIPT_NAME']."' "; if($_GET['plain']!=1) $ausgabe .= "onsubmit=\"document.login.pass.value = MD5(document.login.pass.value);\""; $ausgabe .=">Nutzername:<input type='text' name='nutzer' value='".$_GET['nutzer']."'size='15'>\n <br> Passwort:<input type='password' name='pass' size='15'>\n <noscript><input type='hidden' name='jscript' value='0'></noscript> <input type='hidden' name='aktion' value='login'>\n"; $ausgabe .= "<div id='loginhinweis'>Du hast JavaScript deaktiviert, Dein Passwort wird unverschlüsselt übertragen. Ich empfehle daher, JavaScript zu aktivieren, damit Dein Passwort noch vor dem Versenden verschlüsselt werden kann.</div></form>";
Die zugehörige login.php vergleicht dann folgendermaßen das Passwort mit dem gespeicherten:
$pass = (isset($_POST['jscript'])) ? md5($_POST['pass']) : $_POST['pass']; if($pass == mysql->passwort) $zugang = true;
Der Nachteil an MD5 ist ja, dass man einen String nicht wieder zurückverwandeln kann. Im Fall der Passwortverschlüsselung ist das kein Problem, da es sowieso in der Datenbank "verschlüsselt" gespeichert ist. Falls jemand aber Informationen wieder in den Klartext verwandeln möchte, kann man eine AES Verschlüsselung wählen.
Hier bin ich auf der Seite movable-type.co.uk fündig geworden. Ein JavaScript übernimmt dabei die Verschlüsselung auf der Clientseite, ein PHP Skript entschlüsselt dann alles auf Serverseite wieder (und umgekehrt). Im Prinzip ist eine gute Anleitung sowie der Source Code auf der Seite veröffentlicht.
Das Javascript ist hier erläutert : http://www.movable-type.co.uk/scripts/aes.html
Das zugehörige PHP Skript ist hier erläutert: http://www.movable-type.co.uk/scripts/aes-php.html
Das Beispiel hatte aber einen kleinen Bug, so dass ich hier den zugehörigen Code nochmal poste:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>AES JavaScript+PHP test harness (client-side encrypt)</title> <script type="text/javascript" src="aes-lib.js">/* from www.movable-type.co.uk/scripts/aes.html */</script> </head> <body> <!-- encrypt the message before submitting the form --> <form name="frm" id="frm" method="post" action="aes-js-php.php" onsubmit="frm.message.value = AesCtr.encrypt(frm.message.value, 'L0ck it up saf3', 256);"> <p>Message: <input type="text" name="message" id="message" size="40" value=""></p> <p><input type="submit" name="encr" value="Encrypt it:"></p> </form> </body> </html>
Im Original wird die Funktion AesEncrypt.Ctr() aufgerufen, diese existiert aber nicht im Paket.
Das PHP Skript sieht folgendermaßen aus:
<?php require 'aes-lib.php' // from www.movable-type.co.uk/scripts/aes-php.html ?> // POST Array ausgeben, so wie es angekommen ist print_r($_POST, true); echo "Plaintext:", AESDecryptCtr($_POST['message'], 'L0ck it up saf3', 256);
Für meine Zwecke reicht das völlig aus. Vielleicht nützt dieser Hinweis dem ein oder anderen. Für (konstruktive) Kritik und Tipps bin ich dankbar! Falls jemand eine bessere Lösung hat (z.B. die Umsetzung mit OpenSSL für PHP auf Serverseite und irgendetwas anderes auf Clientseite) bin ich sehr interessiert daran.
Ich habe den Code auf das wesentliche gekürzt und danach nicht neu getestet. Es kann daher sein, dass zuviel gekürzt wurde. -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage
-
Hi
Ansich ist eine Verschlüsselung nicht schlecht. Da die meisten Javascript aktiviert haben ist es auch hier ganz gut einzusetzen.
Der Punkt das javascript nicht sicher sei kann man hier wohl mal außer Acht lassen.
Allerdings wird MD5 benutzt gerade weil man ihn nicht so leicht entschlüsseln konnte. Allerdings gibt es einige Dienste und auch programme die einfach eine Zeit rechnen und vergleichen bis es entschlüsselt ist.
Wenn du eine Bibliothek nimmst die dir alles verschlüsselt und dann ein PHP script nimmst das dir wieder alles entschlüsselt hast du so oder so fast nix gewonnen.
In dem Fall wäre es doch sicher auch einfacher alle Zeichen mit einem Pseudozeichen zu vertauschen, abzuschicken und es zu entschlüsseln.
Aber das funktioniert eben nur solange bis jemand die verschlüsselten Daten abfängt die er gerade Abgeschickt hat und vergleicht.
Im Grunde hat man dann deinen Schlüssel geknackt. Aber fertige Lösungen sind sicher schon auf die eine Art oder Weise "geknackt" worden.
Villeicht kann man auch einfach mehrere Arrays mit Pseudocode erstellen und dann einfach einen Schlüssel mitschicken, der dem PHP-Script sagt wie nun entschlüsselt werden soll.
Allerdings kann man JS ganz gut auslesen im Quelltext :) daher is auch das wieder hinfällig ^^
Grüsse
Color -
der nachteil dieser Verschlüsselung ist die brachiale laufzeit... schonmal versucht ein 20kb großes dokument zu verschlüsseln?
->das dauert ewig...
und wenn man jetzt die Inhalte eines Community-Boards verschlüsselt überträgt, dann sind 20kb schnell zusammen... -
Kleiner Hinweis: Einem Angreifer reicht der MD5-Hash eines Passworts oft auch. Wenn der Client nämlich immer nur den Hash überträgt um sich einzuloggen, kann der Angreifer das auch mit dem Hash, ohne das eigentliche PW zu kennen.
Abhilfe: Sogenannte "Salted Hashes". D.h. der Server gibt dem Client beim Aufrufen der Loginseite irgendeinen Zufallswert, den er sich selber merkt, und der nur für diesen einen Login gültig ist (und der Login kann auch nur mit genau diesem Wert durchgeführt werden). Dann wird vom Client ein Hash vom Passwort plus diesem Zufallswert berechnet und an den Server gesendet.
Auf diese Art können sogenannte "Replay-Attacken" weitgehend ausgeschlossen werden, aber einen Haken hat's: Das Passwort muss auf dem Server im Klartext vorliegen. Alternativ könnte man hier statt dem Passwort auch wieder überall einen Passwort-Hash einsetzen, um das zu umgehen, d.h. es würde auf dem Client erst ein PW-Hash errechnet, dieser dann mit dem Zufallswert verrechnet und davon wieder ein Hash gebildet und zum Server geschickt.
Und nein, hier wird man sicherlich keine 20KB große Seite, sondern lediglich ein Passwort "verschlüsseln" wollen! -
Vielen Dank schonmal für die Rückmeldungen und Anregungen.
theseven schrieb:
Kleiner Hinweis: Einem Angreifer reicht der MD5-Hash eines Passworts oft auch. Wenn der Client nämlich immer nur den Hash überträgt um sich einzuloggen, kann der Angreifer das auch mit dem Hash, ohne das eigentliche PW zu kennen.
Stimmt, da hatte ich beim Verfassen des Beitrags nicht drüber nachgedacht. Auch wenn das Passwort MD5 kodiert übertragen wird, reicht das aus, um Zugang zu erlangen. Es wird ja dann der MD5 Hash überprüft. Allerdings ist es mir eher wichtig, dass keiner das Passwort im Klartext lesen kann, da vermutlich der ein oder andere Freund dasselbe Passwort noch für e-Mail Accounts o.ä. verwendet. Wenn dann ein Angreifer das Passwort im Klartext abfangen kann, stehen im alle Türen offen. MD5 kodiert ist es zumindest nicht so einfach lesbar.
Bislang melden sich nicht so viele Besucher täglich an. Die Gefahr, dass dort jemand lauert, um den MD5 Hash abzufangen, ist glaub ich eher gering. Wahrscheinlich wäre sowieso die Übertragung nur über ein public- & private key Verschlüsselungsverfahren sicher. Daher hier auch die Frage nach Erfahrungen mit OpenSSL oder anderen Lösungen. Vielleicht kann da jemand noch was beisteuern.
Und nein, hier wird man sicherlich keine 20KB große Seite, sondern lediglich ein Passwort "verschlüsseln" wollen!
Genau! Es geht mir primär darum, dass die Passwörter nicht im Klartext abgefangen werden und evtl. dann anderweitig verwendet werden können. Eine Verschlüsselung der Inhalte wäre vorteilhaft, aber ist hier nicht angestrebt. -
rnitsche schrieb:
... da vermutlich der ein oder andere Freund dasselbe Passwort noch für e-Mail Accounts o.ä. verwendet. Wenn dann ein Angreifer das Passwort im Klartext abfangen kann, stehen im alle Türen offen. MD5 kodiert ist es zumindest nicht so einfach lesbar.
...und die Forensoftware gibt sich dann auch mit einem Hash zufrieden, weil die das Passwort im autologin-Cookie nicht im Klartext speichern wollten und sich aber auch keinen Aufwand für eine gescheite Lösung machen wollten. Du wirst nicht glauben, wo man sich überall mit MD5-Hashes einloggen kann.
Bzgl. asymmetrische Kryptographie: Da bekommst du ein neues Problem, und zwar "man in the middle"-Attacken. Aber langsam wirds echt absurd, weil wenn man die Daten auf der Leitung modifizieren und nicht nur ausspähen kann (da helfen auch salted hashes), dann kann man auch die Seite so umbauen dass sie einem das Passwort gleich im Klartext liefert. Die einzige Lösung hierfür, die sich nicht aushebeln lässt, heißt SSL, weil dies vom Browser verifiziert wird, und nicht von der Website (bei der man die Verifikation als Angreifer einfach entfernen kann). -
Ich werde das Passwort bei meiner Webseite Server- und Clientseitig verschlüsseln. Und nicht immer nur MD5 (Da gibt es schon zu viele Rainbow Tables).
* SHA512
* MD5
* str_replace
* Salt
Das müsste reichen.
Beitrag zuletzt geändert: 2.10.2011 8:55:32 von christcomunity -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage