Phil Z.: Was haltet ihr von meinem User-Login-System?

Hallo,
was haltet ihr von diesem System?

Auf der Seite index.php gibt es ein Anmeldeformular, ist man angemeldet ist es nicht sichtbar, ist man nicht angemeldet, ist es sichtbar.

Grundvorraussetzung:
Sobald man auf die Seite kommt, wird eine Session gestartet mit der Variable $_SESSION['logg']=false.

Name und Passwort stehen in einer MySQL Datenbank.
Das Passwort ist stark verschlüsselt: md5(sha1(md5(PASSWORT.anhängsel)))

Zum Login:
1. Der Besucher gibt Namen und Passwort in ein Formular(index.php) ein. Wenn man will, kann man die Checkbox "Angemeldet bleiben" anklicken, so bleibt man beim nächsten Besuch der Seite angemeldet.

2. Name und Passwort werden per $_POST an "login.php" übergeben.

3. Beide eingaben werden "gesichert" mit
mysql_real_escape_string(trim(PASSWORT bzw NAME))

4. Das Passwort wird verschlüsselt md5(sha1(md5(PASSWORT.anhängsel)))

5. In der Datenbank wird nachgeguckt ob der Name mit dem Passwort vorhanden ist.

6. Falls ja wird der vorhandenen Session folgendes beigefügt:

  • Benutzername $_SESSION['name']=name
  • IP $_SESSION['ip']=ip des besuchers
  • $_SESSION['logg']=true;

7. Ein Cookie wird gesetzt mit den Werten:

  • $_COOKIE['logg']=true
  • $_COOKIE['name']=name

8. Es wird auf index.php zurückgeleitet.

Auf der index.php wird folgendes Überprüft und gemacht

  • sind die session variablen ip, name und logg vorhanden
  • entspricht die variable ip der aktuellen ip des besuchers
  • ist der wert der variablen name in der datenbank vorhanden
  • ist der wert der variable logg = true

FALLS das nicht vorhanden ist, wird folgendes gemacht:

  • ist das Cookie vorhanden?
  • steht der wert von $_COOKIE['name'] in der db?
  • ist $_COOKIE['logg']=true?
    Falls ja wird der vorhandenen Session folgendes beigefügt:
  • Benutzername $_SESSION['name']=name
  • IP $_SESSION['ip']=ip des besuchers
  • $_SESSION['logg']=true;

Was haltet ihr davon?

mfg

Phil Z.

  1. Moin,

    Auf der index.php wird folgendes Überprüft und gemacht

    • sind die session variablen ip, name und logg vorhanden
    • entspricht die variable ip der aktuellen ip des besuchers

    Schlechter Ansatz, eine IP-Addresse sagt nichts über die Identität eines Users aus. Beispielsweise kann es durchaus sein, dass mehrere User _gleichzeitig_ mit ein und dieselben IP-Adresse ankommen (requesten), weil sie den gleichen Proxie-Server benutzen.

    Tipp: Lasse den User seine Credentials (Name, Password), eingeben, erzeuge nach einer erfolgreichen Authentifizierung einen eindeutigen Session-Key, speichere diesen Key in einem Cookie und gleichermaßen serverseitig. Zur Prüfung, ob die Session gültig ist, muss Deine Anwendung nur schauen, ob es den Session-Key, der mit einem Request über den Cookie mitgeschickt wird, auch serverseitig gibt. Basta.

    roro

    1. Moin!

      Tipp: Lasse den User seine Credentials (Name, Password), eingeben, erzeuge nach einer erfolgreichen Authentifizierung einen eindeutigen Session-Key, speichere diesen Key in einem Cookie und gleichermaßen serverseitig. Zur Prüfung, ob die Session gültig ist, muss Deine Anwendung nur schauen, ob es den Session-Key, der mit einem Request über den Cookie mitgeschickt wird, auch serverseitig gibt. Basta.

      Danke.
      Meinst du das ich danach auch die anderen Variablen nicht mehr abfragen muss? Also ob z.B. logg=on ist oder ob der Name in der DB vorhanden ist? Und wie erstell ich den key am besten?
      etwa so?
      md5(sha1(ip.name.IRGENDEINWERT))
      speicher ihn in eienr Session und einer Cookie Variable und checke dann auf jeder Seite
      if(SESSIONVAR = COOKIEVAR){
      ZEIGE INHALT;
      }

      ?

      mfg

      Danke

      Phil Z.

      1. Moin!

        Meinst du das ich danach auch die anderen Variablen nicht mehr abfragen muss? Also ob z.B. logg=on ist oder ob der Name in der DB vorhanden ist? Und wie erstell ich den key am besten?

        etwa so?
        md5(sha1(ip.name.IRGENDEINWERT))

        Sorry Phil, mit PHP kenn' ich mich nicht so gut aus. Aber tröste Dich, es ist tatsächlich nicht einfach, einen weltweit absolut eindeutigen Key zu erzeugen, egal in welcher Script- oder Programmiersprache.

        Als Hinweise vielleicht um Duplikate zu vermeiden:

        Benutze die Prozess-ID und den Time-Stamp und irgendeinen Zufalls-Wert zur Erzeugung eines Session-Keys und MD5 oder andere Einweg-Encryption-Mechanism.

        Begrenze die Gültigkeitsdauer von Sessions und bereinige die Tabellen, in denen Session-Key's gespeichert werden regelmäßig, auf jeden Fall nach Ablauf einer jeden Session.

        Die Variablen zum Speichern einer Session sind somit der Key und der Timestamp, um auf Deine Frage von weiter oben zurückzukommen.

        Viel Spaß beim Programmieren!

        roro

      2. hi,

        Meinst du das ich danach auch die anderen Variablen nicht mehr abfragen muss? Also ob z.B. logg=on ist oder ob der Name in der DB vorhanden ist?

        Wenn du das vorher bereits abgefragt hast - wofür solltest du es dann immer wieder abfragen wollen?

        Und wie erstell ich den key am besten?
        etwa so?
        md5(sha1(ip.name.IRGENDEINWERT))

        Oder bspw. mit uniqid().

        gruß,
        wahsaga

        --
        /voodoo.css:
        #GeorgeWBush { position:absolute; bottom:-6ft; }
        1. Hi,
          danke. Aber wie mache ich es nun am besten/sichersten/empfehlenswerten mit der "Angemeldet bleiben" Funktion?

          mfg

          Phil Z.

          1. Hi,

            danke. Aber wie mache ich es nun am besten/sichersten/empfehlenswerten mit der "Angemeldet bleiben" Funktion?

            Nicht angemeldet bleiben: Cookie gilt nur für eine Browser-Sitzung,
            angemeldet bleiben: Cookie gilt länger (wie Du festlege wolle).

            roro

          2. Moin!

            danke. Aber wie mache ich es nun am besten/sichersten/empfehlenswerten mit der "Angemeldet bleiben" Funktion?

            Simpel: Setze ein Cookie, in dem Benutzername und Passwort stehen.

            Jemand, der auf deine Seite kommt, kriegt dann ein Session-Cookie, und du guckst nach, ob das permanente Cookie schon Username und Passwort mitschickt. Wenn ja, ist er mit diesen Daten anzumelden, wenn nein, kriegt er ein Loginformular.

            Was die Sicherheit angeht: Cookiedaten und Formulardaten werden gleichermaßen unverschlüsselt übertragen. Und der Browser des Benutzers ist natürlich grundsätzlich gefährdet. Wer sich daher für diese Funktion entscheidet, der wird abgewogen haben, dass er das zusätzliche Risiko seines dauerhaft im Cookie gespeicherten Passwortes tragen will.

            Und da hilft auch verschlüsseltes Passwortspeichern nichts, denn es reicht ja, mit dem Browser auf deine Seite zu gehen, schon ist man angemeldet drin.

            - Sven Rautenberg

            --
            "Love your nation - respect the others."
  2. was haltet ihr von diesem System?

    Schrott (aber das haben Dir andere ja schon gesagt)

    Das Passwort ist stark verschlüsselt: md5(sha1(md5(PASSWORT.anhängsel)))

    1. NUR md5 ist sicher genug. Wenn Du aber unbedingt SHA1 willst, kannst Du es gerne benutzen, die beiden MD5-Aufrufe fressen aber nur unnötigerweise Rechenzeit.
    2. MD5 als auch SHA1 sind keine Verschlüsselungsalgorithmen.

    "Angemeldet bleiben"

    [...] der vorhandenen Session [wird] folgendes beigefügt:

    • Benutzername $_SESSION['name']=name
    • IP $_SESSION['ip']=ip des besuchers
    • $_SESSION['logg']=true;

    Schritt 1:
    vi /etc/hosts, umlenken Deiner Domain auf 127.0.0.1
    Schritt 2:
    Eigenes PHP-Skript über Deine Domain aufrufen (landet auf meinem Rechner). Diese setzt Deine Cookies auf von mir zu wählende Werte.
    Schritt 3:
    vi /etc/hosts, Umlenkung Deiner Domain auf 127.0.0.1 rückgängig machen
    Schritt 4:
    Als beliebiger Benutzer Deinen Webservice nutzen und dabei beliebige Mengen Schaden anrichten.

    • entspricht die variable ip der aktuellen ip des besuchers

    Wie soll dann das Angemeldet bleiben funktionieren?

    • ist der wert der variable logg = true

    Muß eigentlich, wenn obige Voraussetzungen erfüllt sind auch zutreffen.

    Vorschlag:

    Nach dem Senden von Benutzername + Passwort wird "Benutzername-MD5(Benutzername+Passwort+Magic)" in Form eines Session-Cookies an den Benutzer zurückgesendet. Bei jedem Request wird geprüft, ob der Session-Cookie vorhanden ist. Wenn ja, wird der Benutzername isoliert, in der Datenbank das Passwort abgerufen und dann wieder "Benutzername-MD5(Benutzername+Passwort+Magic)" berechnet. Stimmt das mit dem vom Benutzer übergebenen Wert überein, ist er eingeloggt, sonst nicht. Ob man den Magic global für alle Benutzer konstant setzt, oder ob man diesen Wert pro Benutzer beim Login zufällig generiert, bleibt sich erstmal relativ gleich. Das Argument Plaintext-passwort-equivalent zählt auch nicht, da auch das Übertragen des Passwortes beim Login unverschlüsselt passiert. Soll das Passwort SHA1-Codiert in der Datenbank gespeichert sein, so muß natürlich auch die SHA1-Codierte Version in den Session-Cookie eingerechnet werden.

    Wenn du es jetzt noch ganz sauber machen möchtest, baust Du noch eine Codierungsstufe auf JavaScript-Basis ein:

    Im Login-Formular kommt noch ein type=hidden, name=challeng, value=zufall rein, der submit-button bekommt noch ein onclick verpasst. Dort steht eine Funktion, die das Passwort zusammen mit dem Challenge md5summiert, und das Ergebnis dieser md5sum-Berechnung statt des Klartextpasswortes als Passwort übermittelt (zusammen mit dem Challenge, das Du natürlich vorher in der Datenbank gespeichert hattest). Auf diese Weise wird das Passwort nicht mehr im Klartext übertragen.

    Ich denke, so funktioniert das, werde das demnächst mal selber zusammen programmieren.

    Gruß, Bodo

    1. Hallo!

      Schrott (aber das haben Dir andere ja schon gesagt)

      Okay ich werds ändern.^^

      1. NUR md5 ist sicher genug. Wenn Du aber unbedingt SHA1 willst, kannst Du es gerne benutzen, die beiden MD5-Aufrufe fressen aber nur unnötigerweise Rechenzeit.
      2. MD5 als auch SHA1 sind keine Verschlüsselungsalgorithmen.

      Okay da sha1 40 Bit Hash und md5 einen 32 Bit Hash erzeugt ist es doch okay wenn ich das Passwort mit sha1(PW.Salt) kodiere.

      Als beliebiger Benutzer Deinen Webservice nutzen und dabei beliebige Mengen Schaden anrichten.
      -< Verdammt!

      Nach dem Senden von Benutzername + Passwort wird "Benutzername-MD5(Benutzername+Passwort+Magic)" in Form eines Session-Cookies an den Benutzer zurückgesendet.

      Ich nehme an das "Magic" ein Salt sein soll. Und das ich einfach Eine Session starte mit der Sesseion Variable z.b. $_SESSION['geheim'] = Benutzername-MD5(Benutzername+Passwort+Magic)

      Bei jedem Request wird geprüft, ob der Session-Cookie vorhanden ist. Wenn ja, wird der Benutzername isoliert, in der Datenbank das Passwort abgerufen und dann wieder "Benutzername-MD5(Benutzername+Passwort+Magic)" berechnet.

      Jetzt versteh ich das ganze nicht mehr.

      Stimmt das mit dem vom Benutzer übergebenen Wert überein, ist er eingeloggt, sonst nicht. Ob man den Magic global für alle Benutzer konstant setzt, oder ob man diesen Wert pro Benutzer beim Login zufällig generiert, bleibt sich erstmal relativ gleich. Das Argument Plaintext-passwort-equivalent zählt auch nicht, da auch das Übertragen des Passwortes beim Login unverschlüsselt passiert.

      ??

      Soll das Passwort SHA1-Codiert in der Datenbank gespeichert sein, so muß natürlich auch die SHA1-Codierte Version in den Session-Cookie eingerechnet werden.

      OKay das ist logisch.

      Wenn du es jetzt noch ganz sauber machen möchtest, baust Du noch eine Codierungsstufe auf JavaScript-Basis ein:

      Im Login-Formular kommt noch ein type=hidden, name=challeng, value=zufall rein, der submit-button bekommt noch ein onclick verpasst. Dort steht eine Funktion, die das Passwort zusammen mit dem Challenge md5summiert, und das Ergebnis dieser md5sum-Berechnung statt des Klartextpasswortes als Passwort übermittelt (zusammen mit dem Challenge, das Du natürlich vorher in der Datenbank gespeichert hattest). Auf diese Weise wird das Passwort nicht mehr im Klartext übertragen.

      Auch das stößt ein wenig ans Ende meiner Vorstellungskraft.

      Ich denke, so funktioniert das, werde das demnächst mal selber zusammen programmieren.

      Muss man dir das dann abkaufen, kriegt man es kostenlos, garnicht oder hilfst du mir jetzt hier weiter, was sehr sehr toll wäre =) .

      MfG

      Phil Z.

      1. Hallo Phil

        Okay da sha1 40 Bit Hash und md5 einen 32 Bit Hash erzeugt ist es doch okay wenn ich das Passwort mit sha1(PW.Salt) kodiere.

        Also, MD5 ist meiner Meinung nach sicher genug. Die berichtete Unsicherheit ist folgende: Gegeben sein eine MD5-Prüfsumme, z.B. 5d05d2f5b461d9c93a84067013959ec9 (erzeugt aus dem Text "Bodo Thiesen" oder anders ausgedrückt: Diese Prüfsumme ist die MD5-Prüfsumme über meinen Namen). MD5 gilt nun als geknackt, wenn Du weniger als 2^128 Versuche brauchst, einen anderen Text als "Bodo Thiesen" zu finden, der genau diese Prüfsumme ergibt. Das ist für das Login-System aber nicht relevant. Für das Login-System wäre relevant, ob Du die richtige Zahl aus 2^128 erraten kannst, um die Sitzung zu klauen. Klar, bei SHA1 ist die Wahrscheinlichkeit geringer (2^160) aber die Wahrscheinlichkeit ist bei 2^128 schon hinreichend gering, daß MD5 für diese Zwecke als ausreichend sicher betrachtet werden kann.

        Ok, egal, Back to Topic.

        Nach dem Senden von Benutzername + Passwort wird "Benutzername-MD5(Benutzername+Passwort+Magic)" in Form eines Session-Cookies an den Benutzer zurückgesendet.

        Ich nehme an das "Magic" ein Salt sein soll. Und das ich einfach Eine Session starte mit der Sesseion Variable z.b. $_SESSION['geheim'] = Benutzername-MD5(Benutzername+Passwort+Magic)

        Der Magic ist eine Zufalls-Zeichenkette, die entweder Global für alle Sitzungen gilt, oder Pro Benutzer für ewig festgeschrieben wird - oder eben bei jedem Login neu vergeben wird (dann konsequenterweise aber auch für jeden Benutzer getrennt bleibt).

        Bei jedem Request wird geprüft, ob der Session-Cookie vorhanden ist. Wenn ja, wird der Benutzername isoliert, in der Datenbank das Passwort abgerufen und dann wieder "Benutzername-MD5(Benutzername+Passwort+Magic)" berechnet.

        Jetzt versteh ich das ganze nicht mehr.

        Also: Du willst wissen, ob der Benutzer, der Dich (Deinen Server) kontaktiert, tatsächlich der ist, der er zu sein vorgibt. Einmal beweist er Dir das beim Login (durch mehr oder weniger direkte Übertragung von Benutzername+Passwort), später macht er es, in dem er den Session-Cookie immer wieder übermittelt, der für die Dauer seiner Gültigkeit gleichwertig zu Benutzername und Passwort ist.

        Denke bitte daran, daß HTTP ein statusloses Protokoll ist. Jeder Zugriff muß sich selbst erneut authentisieren.

        Letztlich wirst Du einfach als ersten Aufruf eines jeden PHP-Skriptes, das vom Web aus erreichbar ist, ein 'include "login_check.php";' einbauen. Dieses Skript überprüft dann nur, ob der Benutzer eingeloggt ist, und gibt andernfalls eine Fehlermeldung aus und beendet sich. Ist der Benutzer eingeloggt, setzt es wohl noch ein paar Variablen, damit man z.B. direkt über $uid an die Benutzer-ID heran kommt, und nicht ständig nochmal in der Tabelle nachschauen muß.

        Stimmt das mit dem vom Benutzer übergebenen Wert überein, ist er eingeloggt, sonst nicht. Ob man den Magic global für alle Benutzer konstant setzt, oder ob man diesen Wert pro Benutzer beim Login zufällig generiert, bleibt sich erstmal relativ gleich. Das Argument Plaintext-passwort-equivalent zählt auch nicht, da auch das Übertragen des Passwortes beim Login unverschlüsselt passiert.

        ??

        Worauf genau beziehen sich Deine Fragezeichen?

        1. Magic global: Wenn ja, ist es möglich, browserübergreifend eingeloggt zu bleiben. Wenn nein, wird man jedes mal, wenn man sich mit einem anderen Browser neu einloggt, beim anderen Browser, bei dem man bereits eingeloggt ist, ausgeloggt.
        2. Plaintext-passwort-equivalent: Wenn Du Dich einloggst, wirst Du Benutztername+Passwort normalerweise im Klartext (oder engl. Plaintext) übertragen. Wenn der Server Dir nun einen Cookie zurückschickt, ist dieser genauso gut, wie die Kombination Benutztername+Passwort. Also ist der Cookie "Plaintext-passwort-equivalent". Weil es einem Angreifer reicht, den Cookie zu kennen, um in Deinem Namen auf den Dienst zuzugreifen, er muß nicht unbedingt Dein Passwort kennen.

        Wenn du es jetzt noch ganz sauber machen möchtest, baust Du noch eine Codierungsstufe auf JavaScript-Basis ein:

        Im Login-Formular kommt noch ein type=hidden, name=challeng, value=zufall rein, der submit-button bekommt noch ein onclick verpasst. Dort steht eine Funktion, die das Passwort zusammen mit dem Challenge md5summiert, und das Ergebnis dieser md5sum-Berechnung statt des Klartextpasswortes als Passwort übermittelt (zusammen mit dem Challenge, das Du natürlich vorher in der Datenbank gespeichert hattest). Auf diese Weise wird das Passwort nicht mehr im Klartext übertragen.

        Auch das stößt ein wenig ans Ende meiner Vorstellungskraft.

        Punkt 2 aus letztem Absatz: Nehmen wir an, mein Benutzername lautet bodo, und mein Passwort lautet 123. Wenn ich nun vom Server die Aufforderung erhalte MD5(Benutzername+Passwort+abc) zu generieren, wobei abc das vom Server generierte Magic ist, und ich (also das JavaScript meines Browsers) nun die Prüfsumme errechnet, dann wird das Passwort im Login-Vorgang überhaupt nicht an den Server übertragen. Ergo kann man es auch unterwegs nicht klauen. Wir hatten hier vor einiger Zeit mal eine Diskussion laufen, ich weiß nicht wer es war, aber einer sagte, daß häufig das Passwort eine wesentlich schützenswertere Information ist, als was durch das Passwort geschützt wird. Das ist nämlich genau dann der Fall, wenn Du Dein Passwort für 1000 Dienste verwendest. Dann schützt Du damit vielleicht diesen SELFHTLM-Forenaccount mit dem gleichen Passwort, wie Dein E-Mail-Account. Ich glaube, wir beide sind uns einig, daß in diesem Falle die Tatsache, daß Du hier im Forum authentisiert bist (daß ist die Durch Dein Passwort geschützte Information), nicht so wichtig ist, als die Geheimhaltung des Passwortes vor einem potentiellen Angreifer (weil man damit Zugriff auf Dein E-Mail Account erhält). Richtig? Deswegen mein Vorschlag mit dem JavaScript.

        Ich denke, so funktioniert das, werde das demnächst mal selber zusammen programmieren.

        Muss man dir das dann abkaufen, kriegt man es kostenlos, garnicht oder hilfst du mir jetzt hier weiter, was sehr sehr toll wäre =) .

        Da jeder, der im Programmieren geübt ist, dieses ganze System in wenigen Tagen (an einem Tag?) selber auf die Beine stellen kann, glaube ich nicht, daß man damit ernsthaft Geld verdienen kann. Ich für meinen Teil beginnen das in den nächsten Tagen umzusetzen, wenn Du noch etwas warten kannst, dann schick mir mal eine E-Mail und ich benachrichtige Dich, sobald ich fertig bin, dann kannst Du Dir das mal anschauen und ggf selber verwenden.

        Gruß, Bodo

        1. Hallo Bodo,

          danke für deine Hilfe,
          ich habe mich mal an so einer Javascript Funktion probiert, wäre diese ausreichend?

          [code=html]<form method='post' action='index.php?p=login&act=yes' name='myForm'onSubmit='return myJavaScript()'>
          Benutzername:<input name='name' type='text'/>
          Passwort:<input name='pw' type='password'/>
          Angemeldet bleiben?<input type='checkbox' value='setc' name='setc'/>
          <input name='Einloggen' type='submit' value='Anmelden'/></form>[/code]

          [code=javascript]function myJavaScript() {
          $x = 1 + (999999999) * Math.random();
          $x= Math.round($x);
              document.myForm.pw.value = MD5(document.myForm.pw.value + $x);
          }[/code]

          Worauf genau beziehen sich Deine Fragezeichen?

          Auf den gesamten Abschnitt ;) - habs aber jetzt verstanden.

          Da jeder, der im Programmieren geübt ist, dieses ganze System in wenigen Tagen (an einem Tag?) selber auf die Beine stellen kann, glaube ich nicht, daß man damit ernsthaft Geld verdienen kann. Ich für meinen Teil beginnen das in den nächsten Tagen umzusetzen, wenn Du noch etwas warten kannst, dann schick mir mal eine E-Mail und ich benachrichtige Dich, sobald ich fertig bin, dann kannst Du Dir das mal anschauen und ggf selber verwenden.

          Danke das wäre gut, ich werd es auf jeden Fall gebrauchen können.
          Meine E-Mail: phil-z@online.ded
          Ich werde allerdings weiter versuchen es auch hinzukriegen.

          mfg

          Phil Z.