Malcolm Beck`s: Ein Loginscript

0 58

Ein Loginscript

Malcolm Beck`s
  • datenbank
  • php
  1. -2
    pl
    1. 0
      Orlok
      • perl
      • zu diesem forum
  2. 0
    Jörg Reinholz
    1. 0
      Jörg Reinholz
      1. 0
        Malcolm Beck`s
        1. 0
          Jörg Reinholz
          1. 0
            woodfighter
            1. 0
              Auge
              • datenbank
              • menschelei
              • php
              1. 0
                Christian Kruse
                1. 0
                  Jörg Reinholz
          2. 0
            Malcolm Beck`s
            1. 2
              Auge
              • php
              • sicherheit
              1. 0
                Malcolm Beck`s
                1. 2
                  Jörg Reinholz
                  1. 0

                    Ein Loginscript - so weit, so gut

                    Malcolm Beck`s
                    1. 0
                      Matthias Apsel
                      1. 0
                        Malcolm Beck`s
                        1. 1
                          Auge
                          • internet-anbindung
                          • sicherheit
                          1. 0
                            woodfighter
                            • internet-anbindung
                            1. 0
                              Auge
                              1. 0
                                woodfighter
                                1. 0
                                  Auge
                      2. 0
                        woodfighter
                        1. 0
                          Jörg Reinholz
                        2. 0
                          Matthias Apsel
                          1. 0
                            woodfighter
                            • internet-anbindung
                    2. 1
                      Jörg Reinholz
                      • php
                      • programmiertechnik
                      • programmiertechnik
                      1. 0

                        Ein Loginscript - so weit geklärt

                        Malcolm Beck`s
                    3. 1
                      Jörg Reinholz
                      1. 0
                        Malcolm Beck`s
            2. 1
              woodfighter
    2. 0
      Malcolm Beck`s
      1. 0
        woodfighter
      2. 1
        Jörg Reinholz
    3. 3
      1unitedpower
  3. 2
    Felix Riesterer
    1. 4
      Christian Kruse
      1. 0
        Malcolm Beck`s
        1. 1
          Christian Kruse
          1. 0
            Malcolm Beck`s
            1. 0
              Christian Kruse
              1. 0
                Malcolm Beck`s
            2. 2
              woodfighter
              1. 0
                woodfighter
                • sicherheit
            3. 1
              Tabellenkalk
              1. 0
                Auge
                • datenbank
                • menschelei
                • php
              2. 0
                Jörg Reinholz
      2. 0
        Felix Riesterer
        1. 0
          Christian Kruse
      3. -2
        pl
        1. 0
          woodfighter
    2. 0
      Malcolm Beck`s
      1. 3
        Christian Kruse
        1. 0
          Malcolm Beck`s
          1. 0
            Christian Kruse
            1. 0
              Malcolm Beck`s
              1. 0
                Christian Kruse

Hallo werte Freunde,

Ich habe mir vor kurzem eine Klasse für ein rudimentäres Login geschrieben, welches auf das Sessionbasierte Loginscript vom Benjamin beruht (finde es leider nicht mehr). Ich hab's nur um Cookies erweitert, so das User eingeloggt bleiben können, wenn sie sich nicht explizit ausloggen. Und hierzu habe ich eine kleine Frage.

Ich speichere die Logindaten in Form von:

userid | Pass (gehasht) 1 | 4a4350df2403b94a13304ee88b861041

Beim Login versuche ich 2 Cookies zu setzen. Ein SESSION-Cookie und einen normalen. Beide erhalten den folgenden Wert:

// userid mit irgendwas multipliziert
$_SESSION['USER'] = '541 4a4350df2403b94a13304ee88b861041';
$_COOKIE['USER']  = '541 4a4350df2403b94a13304ee88b861041';

Und dann prüfe ich:

// Wenn Session, aber kein Cookie, Loginformular - damit ist schonmal Session Hijacking unterbunden
if $_SESSION['USER'] AND !$_COOKIE['USER']
  exit()

// Wenn Session und Cookie vorhanden sind, Datenbankabfrage sparen, da die Sessiondaten auf dem Server liegen und vom Nutzer nicht geändert werden können
if $_SESSION['USER'] AND $_COOKIE['USER']

  // Sessiondaten mit Cookiedaten vergleichen, wenn beide richtig, ist User eingeloggt
  // Kann ich das so machen?
  $_COOKIE['USER'][0] == $_SESSION['USER'][0]
  $_COOKIE['USER'][1] == $_SESSION['USER'][1]

// Automatisches Login: Datenbank mit den Daten im Cookie abfragen, wenn keine Session vorhanden ist
if $_COOKIE['USER'] AND !$_SESSION['USER']

  // wenn beide Daten im Cookie richtig sind, ist User authentifiziert
  $_COOKIE['USER'][0] == $_USERINDB
  $_COOKIE['USER'][1] == $_USERPASSINDB

Ich könnte das ganze jetzt um eine weitere Prüfung erweitern, in dem ich einfach alle vom User genutzten IPs beim Login checke, ob die aktuell nur mit Cookie aufrufende IP schon einmal genutzt wurde, wenn nicht, Login erzwingen. Ohne diese Prüfung könnte ein Hacker, wenn er die Userid und das gehashte Passwort richtig errät, das Profil kapern. Was aber ja auch schon schwierig genug sein dürfte.

Ich komme mit derzeit rund 1000 Zeilen Code aus (ohne IP-Check, mit wären's vllt. 30 - 40 mehr), da habe ich irgendwie bedenken, ob das wirklich so sicher sein kann (fühlt sich zumindest halbwegs sicher an, und etwas Weltbewegendes ist das ganze ja auch nicht unbedingt). Hier könnt ihr das ganze Live testen. Email ist nicht zwingend erforderlich, ihr könnt euch auch mit einzelnen Buchstaben registrieren.

Was passiert denn in grossen Frameworks, dass die teilweise tausende Zeilen Code benötigen? Selbst wenn ich jetzt noch eine Tabelle mit Userrechten laden würde, wären es lediglich ein paar Zeilen mehr. Was prüfen die noch alles, was wäre noch möglich oder ratsam?

Bis bald

--
Hosen sind Blau
  1. Was passiert denn in grossen Frameworks, dass die teilweise tausende Zeilen Code benötigen? Selbst wenn ich jetzt noch eine Tabelle mit Userrechten laden würde, wären es lediglich ein paar Zeilen mehr. Was prüfen die noch alles, was wäre noch möglich oder ratsam?

    Bei meinem Login steht die Session schon vorher (gefühlte 5 Zeilen handeln einen Cookie aus). Beim Login wird nur geprüft, ob auf den eingegebene Username das Passwort passt (3 Zeiler). Und Wenns gepasst hat:

    $SESSION{LOGINTAB}{user}  = $user;
    $SESSION{LOGINTAB}{group} = $group;
    $SESSION{LOGINTAB}{time}  = time();
    
    tied(%SESSION)->write; 
    # automatisch im Destroy der Response-Instanz
    
    

    mfg

    --
    Ich finde es gut, dass Parteien in Wort, Bild und Taten darüber aufklären was sie tun (Danke Frau Steinbach).
    1. Hallo pl

      Bei meinem Login steht die Session schon vorher (gefühlte 5 Zeilen handeln einen Cookie aus). Beim Login wird nur geprüft, ob auf den eingegebene Username das Passwort passt (3 Zeiler). Und Wenns gepasst hat:

      $SESSION{LOGINTAB}{user}  = $user;
      $SESSION{LOGINTAB}{group} = $group;
      $SESSION{LOGINTAB}{time}  = time();
      
      tied(%SESSION)->write; 
      # automatisch im Destroy der Response-Instanz
      

      BTW: Hier im Forum gibt’s wie du siehst übrigens auch Syntaxhervorhebung für Perl sowie ein entsprechendes Tag. – Nur Automatic Explanation Insertion ist leider noch nicht implementiert…

      Viele Grüße,

      Orlok

      --
      „Das Wesentliche einer Kerze ist nicht das Wachs, das seine Spuren hinterlässt, sondern das Licht.“ Antoine de Saint-Exupéry
  2. Moin!

    Ich speichere die Logindaten in Form von:

    userid | Pass (gehasht) 1 | 4a4350df2403b94a13304ee88b861041

    Oh. Ist das etwa MD5?

    Das genügt nicht. Ist unsicher..

    Jörg Reinholz

    1. Moin!

      Das genügt nicht. Ist unsicher..

      Für das Langzeit-Login kann man ausgehend von vom Code im Artikel die Session-Daten natürlich auch in eine DB kopieren und diese beim Wiederauftauchen des Cookies auslesen, die Session dann nachbauen. Alternative: Die Session-Datei in einen anderen Ordner kopieren und beim Auftauen des Cookies und die Session also wiederherstellen. Löschen der "Langzeitsession" genau wie die normale, die ist ja auch in einem Extra-Verzeichnis, weil eine Anpassung der Gültigkeit der Session für manche nicht möglich ist.

      Jörg Reinholz

      1. Hi Jörg,

        Für das Langzeit-Login kann man ausgehend von vom Code im Artikel die Session-Daten natürlich auch in eine DB kopieren und diese beim Wiederauftauchen des Cookies auslesen, die Session dann nachbauen. Alternative: Die Session-Datei in einen anderen Ordner kopieren und beim Auftauen des Cookies und die Session also wiederherstellen.

        Warum die Session nachbauen? Ich dachte, die ist immer einmalig? Was spricht denn dagegen, das gehashte Passwort im Cookie zu speichern? Es sind ja nicht direkt die richtigen Daten, sondern alles verfremdet.

        Bis bald

        --
        Hosen sind Blau
        1. Moin!

          Was spricht denn dagegen, das gehashte Passwort im Cookie zu speichern?

          Du kannst auch am Sonntag morgen mit 180 Sachen über die Alleen in Mecklenburg brettern. Der Effekt ist der gleiche: Du kommst in die Zeitung.

          Anders gesagt: Du stellst ja auch nicht eine Kiste mit Deinem gesamten Vermögen auf die Straße, weil Du denkst, dass das Schloss sicher ist. Soll heisen: Mit dem Cookie reist der Hash um die Welt und wenn sich eines Tages - wie ausgerechnet schon seit Jahren von dem von Dir auch noch benutzen MD5 schon längst bekannt - herausstellt: "Ups! Ist knackbar!" dann ist die Kacke am dampfen.

          Dann kann nämlich das eingesetzte Passwort ermittelt werden - und Dein Benutzer hat ein Problem.

          Jörg Reinholz

          1. Tach,

            Mit dem Cookie reist der Hash um die Welt und wenn sich eines Tages - wie ausgerechnet schon seit Jahren von dem von Dir auch noch benutzen MD5 schon längst bekannt - herausstellt: "Ups! Ist knackbar!" dann ist die Kacke am dampfen.

            der Preimage-Angrriff auf md5 ist m.w. immer noch nicht praktisch umsetzbar, ganz so schlimm ist es dann zum Glück noch nicht.

            mfg
            Woodfighter

            1. Hallo

              Mit dem Cookie reist der Hash um die Welt und wenn sich eines Tages - wie ausgerechnet schon seit Jahren von dem von Dir auch noch benutzen MD5 schon längst bekannt - herausstellt: "Ups! Ist knackbar!" dann ist die Kacke am dampfen.

              der Preimage-Angrriff …

              Jawoll, Herr Oberstleutnant! *scnr*

              … auf md5 ist m.w. immer noch nicht praktisch umsetzbar, ganz so schlimm ist es dann zum Glück noch nicht.

              Braucht man bei einem MD5-gehashten Passwort einen Angriff auf das Passwort? Da wird doch nur noch in die Rainbow-Tabelle geschaut und irgendein zum Hash passender String gesucht. oder habe ich das falsch verstanden?

              Tschö, Auge

              --
              Wir hören immer wieder, dass Regierungscomputer gehackt wurden. Ich denke, man sollte die Sicherheit seiner Daten nicht Regierungen anvertrauen.
              Jan Koum, Mitgründer von WhatsApp, im Heise.de-Interview
              1. Hallo Auge,

                … auf md5 ist m.w. immer noch nicht praktisch umsetzbar, ganz so schlimm ist es dann zum Glück noch nicht.

                Braucht man bei einem MD5-gehashten Passwort einen Angriff auf das Passwort? Da wird doch nur noch in die Rainbow-Tabelle geschaut und irgendein zum Hash passender String gesucht. oder habe ich das falsch verstanden?

                Er verwendet Salts, da müsste man zu jedem Passwort eine neue Tabelle erstellen.

                LG,
                CK

                1. Moin!

                  Er verwendet Salts, da müsste man zu jedem Passwort eine neue Tabelle erstellen.

                  Hab ich grad für was anderes getestet:

                  <?php
                  $txt='';
                  for ($i=1; $i<10000000; $i++) {
                      $txt.= 'insert into `test`.`big_test` (`nr`, `text`) values(' . $i . ', "' . md5($i.'hallo') . '");';
                  }
                  file_put_contents('test2.sql', $txt);
                  
                  fastix@trainer:/tmp$ time php test_sql.php 
                  
                  real    0m18.644s
                  user    0m11.432s
                  sys     0m6.020s
                  fastix@trainer:/tmp$ ls -lh test2.sql
                  -rw-rw-r-- 1 fastix fastix 925M Mär  1 16:19 test2.sql
                  

                  Der nicht mehr ganz taufrische Rechner (AMD Athlon(tm) II X4 631 Quad-Core Processor) hat aber gerade damit zu tun, die früher erzeugte Datei in die DB einzulesen ... Nehmen wir jetzt eine staatliche oder kriminelle Organisation (manche sind beides zu gleich) mit Geld, dann erzeugen und speichern die nicht 10 Millionen sondern Quintillionen von Hashes mit MD5 in ein paar Minuten ...

                  Jörg Reinholz

          2. Hi Jörg,

            Du kannst auch am Sonntag morgen mit 180 Sachen über die Alleen in Mecklenburg brettern. Der Effekt ist der gleiche: Du kommst in die Zeitung.

            Wenn ich im Auto sitze, bin ja auch ich es, der da sitzt und fährt. Aber das,w as ich im Cookie speichere, hat ja so mit dem eigentlichen Passwort nichts mehr zutun. Es ist quasi doppelt und dreifach gehashed. Und wenn man den Cookie richtig benennt, dann könnte eh keiner daraus schliessen, was die ganzen Werte in den Cookies zu bedeuten haben. Gut, das wäre dann wieder Security through obscurity. Aber ein doppelt, von mir aus 3 mal gehashter String? Um diese zu knacken, müsste ja erstmal festgestellt werden, wie oft ich es gehasht habe, um daraus dann das Passwort zu errechnen. Da nutzen Rainbowtable nicht viel.

            Anders gesagt: Du stellst ja auch nicht eine Kiste mit Deinem gesamten Vermögen auf die Straße

            Naja, viel wäre das ohnehin nicht ;)

            Mit dem Cookie reist der Hash um die Welt und wenn sich eines Tages - wie ausgerechnet schon seit Jahren von dem von Dir auch noch benutzen MD5 schon längst bekannt - herausstellt: "Ups! Ist knackbar!" dann ist die Kacke am dampfen.

            Meinst du, das folgende könnte geknackt werden?

            password = 4a4350df2403b94a13304ee88b861041
            
            // Im Cookie z.B.
            md5( md5(password ) )
            

            Für mich ist es ja egal, wie oft ich die Strings hashe.

            Bis bald

            --
            Hosen sind Blau
            1. Hallo

              … das,w as ich im Cookie speichere, hat ja so mit dem eigentlichen Passwort nichts mehr zutun. Es ist quasi doppelt und dreifach gehashed. Und wenn man den Cookie richtig benennt, dann könnte eh keiner daraus schliessen, was die ganzen Werte in den Cookies zu bedeuten haben. Gut, das wäre dann wieder Security through obscurity.

              Ja, das ist es in jeglicher Hinsicht. Warum du das Passwort überhaupt an den Benutzer übermitteln willst, hast du noch nicht erklärt. Der Benutzer soll die Kennung seiner Session angepappt bekommen, damit man ihn bei weiteren Requests auf dem Server wiedererkennt. Das ist klar. Aber wozu zum Deibel nochmal braucht er das Passwort im Cookie, das bei jedem Request an den Server übermittelt wird?

              Es wird unnütz in die Welt hinausposaunt und seine Speicherung ist auf Clientseite auch völlig unnütz.

              Aber ein doppelt, von mir aus 3 mal gehashter String? Um diese zu knacken, müsste ja erstmal festgestellt werden, wie oft ich es gehasht habe, um daraus dann das Passwort zu errechnen. Da nutzen Rainbowtable nicht viel.

              Weißt du es oder vermutest du es, zumal bei einer bekanntermaßen geknackten Methode? Selbst wenn das Cookie abgefangen wird, aber nicht in Echtzeit geknackt werden kann, liegt es dann doch für einen späteren Angriff bereit. Auch wenn du das Passwort 10 mal mit Salz und Pfeffer hashst, irgendwann ist es in endlicher und überschaubarer Zeit ermittelbar. Wohl dem deiner Benutzer, der bis dann sein Passwort geändert hat und so einen neuen Angriff nötig macht. Der hat noch ein wenig Zeit gewonnen, der Rest ist am Arsch.

              Tschö, Auge

              --
              Wir hören immer wieder, dass Regierungscomputer gehackt wurden. Ich denke, man sollte die Sicherheit seiner Daten nicht Regierungen anvertrauen.
              Jan Koum, Mitgründer von WhatsApp, im Heise.de-Interview
              1. Hi Auge,

                Aber wozu zum Deibel nochmal braucht er das Passwort im Cookie, das bei jedem Request an den Server übermittelt wird?

                Um ein automatisches Login zu ermöglichen, falls ein User den Browser schliesst und wieder startet. Da dachte ich mir, wenn ich das Passwort gehasht in einem Cookie speichere, ist es quasi so, als ob der User die Daten in ein Formular eingibt.

                Und wenn ein User die Seite nur mit dem besagten Cookie aufruft, ohne gültige Session, könnte ich noch die IP prüfen, ob der User sich schonmal mit dieser IP eingeloggt hat. Wenn ja, kann ich mit dem Cookie eine Session starten und der User ist eingeloggt. Wenn die IP, mit der die Seite aufgerufen wird, dem User nicht zugeschrieben werden kann, wird er automatisch ausgeloggt und zum regulären Login gezwungen. Dann kann ich die neue IP speichern, und diese quasi in die Whitelist des Users aufnehmen. Beim nächsten Autologin hätte er dann keine Probleme. Natürlich nur sofern die IP sich nicht ändert.

                Weißt du es oder vermutest du es,

                Ich vermute.

                Selbst wenn das Cookie abgefangen wird, aber nicht in Echtzeit geknackt werden kann, liegt es dann doch für einen späteren Angriff bereit. Auch wenn du das Passwort 10 mal mit Salz und Pfeffer hashst, irgendwann ist es in endlicher und überschaubarer Zeit ermittelbar.

                Das ist ein Argument.

                Bis bald

                --
                Hosen sind Blau
                1. Moin!

                  Und wenn ein User die Seite nur mit dem besagten Cookie aufruft, ohne gültige Session, könnte ich noch die IP prüfen, ob der User sich schonmal mit dieser IP eingeloggt hat. Wenn ja, kann ich mit dem Cookie eine Session starten und der User ist eingeloggt.

                  Damit macht Du das kaputt, was Du erreichen willst. Der User hat inzwischen nämlich eine neue IP, weil sein ISP ihm die neue nach 24h verpasst hat. Hint: Das kann auch um 14:23 erfolgen.

                  Das gehaschte Passwort im Cookie ist so unnötig wie ein Kropf und ist potentiell geeignet, die Sicherheit noch mehr zu beschädigen als es die Langzeitsession so oder so schon tut.

                  Im übrigen lässt sich die Session-ID ohnehin auch generell in einem Cookie ablegen. Das muss dann eben nicht die Browsersitzung überstehen oder nicht. Dazu den Benutzername und meinetwegen (um das Geheimnis zu vergrößern) den Zeitpunkt des eigentlichen Logins, die bei einer Wiederkehr mit der alten Session verglichen werden.

                  session_id() liest und setzt eine session_id, der Inhalt von $_SESSION ist ein "named array", kann also dank json_encode / json_decode jederzeit aus der Session gelesen, in einer Textdatei gespeichert und aus einer solchen ausgelesen werden und in der Sessionvariable gespeichert werden. Für das maximale Alter gibt das Dateisystem den Zeitpunkt der letzten Änderung raus, den kann man auch benutzen um überalterte regelmäßig zu löschen. Einfacher geht es kaum.

                  Dann wäre also nur noch das Cookie mit der session_id zu senden und bei der Wiederkehr zu verwenden.

                  Jörg Reinholz

                  1. Hi Jörg,

                    Damit macht Du das kaputt, was Du erreichen willst. Der User hat inzwischen nämlich eine neue IP, weil sein ISP ihm die neue nach 24h verpasst hat. Hint: Das kann auch um 14:23 erfolgen.

                    Sind viele Nutzer von solchen ISPs betroffen? Ich hatte sowas meine ich noch nie. Aber ich hab mir leider auch nicht immer angeguckt, welche IPs ich so hatte.

                    Das gehaschte Passwort im Cookie ist so unnötig wie ein Kropf und ist potentiell geeignet, die Sicherheit noch mehr zu beschädigen als es die Langzeitsession so oder so schon tut.

                    Ok, ihr habt mich überzeugt. Hattet ihr eigentlich schon viel Früher geschafft, aber ich wollte auf Nummer sicher gehen :)

                    Wie wäre folgendes: Statt das ich das Passwort im Cookie speichere, speichere ich bei einem regulären Login einfach einen Token in der DB (evtl. die IP in gehashter Form?), quasi eine Passwort-Alternative. Es sollte doch kein Problem darstellen? Für jedes Login an einem Client ein eigener Token, und auf Userseite noch die Datenbank-ID des Tokens im Cookie festhalten. Ich möchte auf gar keinen Fall selber irgendwelche Textdateien erstellen und speichern müssen, weil das meist der Anfang vom Ende ist :)

                    Es geht mir eigentlich nur darum, den User zu erkennen, bei dem keine Session mehr ist, um die Session neu starten zu können. Denn die Session wird ja zerstört, sobald der User den Browser schliesst. Daher muss ich ja irgendeine Info beim User lassen, die keiner so leicht erraten kann. Daher kam ich überhaupt erst auf den Klopps mit dem Passwort im Cookie.

                    Die meisten Tipps von euch waren schon sehr hilfreich für mich. Damit kann ich was anfangen, nur dieser eine Punkt gibt mir noch etwas zu denken. Oder ich verstehe eure Lösungsvorschläge nicht.

                    Was ich schon mal in die Klasse übernehme, also abgehakt sind.

                    session.regenerate // nach dem ersten Login
                    Cookie             // httponly und flags setzen
                    password_hash      // ich muss öfter mal wieder lesen, ich programmiere auf dem Stand von 2012 :)
                    password_verify    // antworten auf nie gestellte Fragen sind immer noch die besten :)
                    

                    Was mache ich nun mit dem Cookie?

                    Bis bald

                    --
                    Hosen sind Blau
                    1. Hallo Malcolm Beck`s,

                      Damit macht Du das kaputt, was Du erreichen willst. Der User hat inzwischen nämlich eine neue IP, weil sein ISP ihm die neue nach 24h verpasst hat. Hint: Das kann auch um 14:23 erfolgen.

                      Sind viele Nutzer von solchen ISPs betroffen? Ich hatte sowas meine ich noch nie. Aber ich hab mir leider auch nicht immer angeguckt, welche IPs ich so hatte.

                      ISP steht für InternetServiceProvider. Eigentlich sind alle™ Nutzer von einer Zwangstrennung gegen Mitternacht betroffen.

                      Bis demnächst
                      Matthias

                      --
                      Das Geheimnis des Könnens liegt im Wollen. (Giuseppe Mazzini)
                      1. Hi Matthias,

                        ISP steht für InternetServiceProvider. Eigentlich sind alle™ Nutzer von einer Zwangstrennung gegen Mitternacht betroffen.

                        Ich bin bei Unitymedia, und ich habe teilweise über Wochen hinweg die gleiche IP. Oder kommt mir das nur so vor? Ich werde es die Tage im Auge behalten. Ich mein, ich hatte bisher immer relativ gleiche IPs, egal, bei welchem Anbieter ich war. Oder ich habe immer nur auf die ersten 2 Blöcke geachtet, und es kam mir nur so vor. Mal sehen.

                        Bis bald

                        --
                        Hosen sind Blau
                        1. Hallo

                          ISP steht für InternetServiceProvider. Eigentlich sind alle™ Nutzer von einer Zwangstrennung gegen Mitternacht betroffen.

                          @Matthias Apsel: Nein.

                          Ich bin bei Unitymedia, und ich habe teilweise über Wochen hinweg die gleiche IP. Oder kommt mir das nur so vor? Ich werde es die Tage im Auge behalten. Ich mein, ich hatte bisher immer relativ gleiche IPs, egal, bei welchem Anbieter ich war. Oder ich habe immer nur auf die ersten 2 Blöcke geachtet, und es kam mir nur so vor. Mal sehen.

                          Du hast das bei dir selbst schon richtig beobachtet. Kunden von Internetzugängen bei Kabel-TV-Anbietern kennen keine 24-stündliche Zwangstrennung [1]. Eine Trennung erfolgt dort nur bei technischen Problemen oder Provisionierungen des Modems, z.B. bei einer Vertragsumstellung. Somit behalten diese Kunden die ihnen einmal zugewiesene IP bis zu einem solchen Ereignis. Zumindest für Kabel Deutschland kann ich aus Erfahrung sagen, dass es recht wahrscheinlich ist, dass dem Modem, bei einer Wiederverbindung binnen kurzer Zeit nach der Trennung, die schon vorher zugewiesene IP erneut zugewiesen wird. Verlassen kann man sich als Kunde darauf aber nicht.

                          Das alles gilt aber nicht für Kunden von Internetzugängen über die Telefonleitung. Die haben in Deutschland fast ausnahmslos eine Zwangstrennung pro 24 Stunden. Dieser Mumpitz stammt aus der Zeit, als praktisch nur IPv4-Adressen zugewiesen wurden und es noch nicht üblich war, dauerhaft online zu sein. Auf diese Art konnte man 100 IP-Adressen, über die Zeit verteilt, an mehr als 100 Kunden vergeben. Heute ist das DSL-Modem typischerweise dauerhaft online und belegt die zugewiesene IP dementsprechend auch dauerhaft. Es bekommt aber jeden Tag eine mit großer Wahrscheinlichkeit andere IP zugewiesen, die es ebenso dauerhaft bis zur nächsten Zwangstrennung belegt. Der ursprünglich angestrebte Effekt ist so also nicht vorhanden.

                          Tschö, Auge

                          --
                          Wir hören immer wieder, dass Regierungscomputer gehackt wurden. Ich denke, man sollte die Sicherheit seiner Daten nicht Regierungen anvertrauen.
                          Jan Koum, Mitgründer von WhatsApp, im Heise.de-Interview

                          1. Ich kann natürlich nicht für alle Kabel-TV-Anbieter sprechen, aber für Kabel Deutschland respektive Vodafone Kabel und offensichtlich auch Unitymedia, also die in Deutschland größten Anbieter, gilt die Aussage. ↩︎

                          1. Tach,

                            danke für die ausführliche Erklärung.

                            Das alles gilt aber nicht für Kunden von Internetzugängen über die Telefonleitung.

                            mal abgesehen von den genannten Ausnahmen (ich hatte noch nie eine Zwangstrennung bei meinem Internetanschluss), noch eine pingelige Anmerkung: Das Wort Telefonleitung inzwischen auch eher problematisch; die Telekom stellt inzwischen agressiv (sie kündigen Anschlüsse, die das nicht mitmachen wollen) Anschlüsse auf VoIP um, ich vermute mal andere Anbiter machen das ähnlich bzw. haben nie etwas anderes angeboten. In einem größeren Teil der Haushalte sind die Zweidraht-Kupferkabel, die im Flur ankommen und auf einer TAE enden, Internetleitungen.

                            mfg
                            Woodfighter

                            1. Hallo

                              danke für die ausführliche Erklärung.

                              Bitteschön. Muss ja auch im Nachhinein zu irgendwas gut sein, für einen solchen Anbieter gearbeitet zu haben.

                              Das alles gilt aber nicht für Kunden von Internetzugängen über die Telefonleitung.

                              … Das Wort Telefonleitung inzwischen auch eher problematisch; die Telekom stellt inzwischen agressiv (sie kündigen Anschlüsse, die das nicht mitmachen wollen) Anschlüsse auf VoIP um, ich vermute mal andere Anbiter machen das ähnlich bzw. haben nie etwas anderes angeboten.

                              Viele Anbieter sind „spät genug“ in den Markt eingestiegen, um gleich auf VoIP zu setzen. Ich selbst habe noch einen analogen Telefonanschluss mit echter™ Tonübertragung und Splitter vor dem DSL-Modem.

                              In einem größeren Teil der Haushalte sind die Zweidraht-Kupferkabel, die im Flur ankommen und auf einer TAE enden, Internetleitungen.

                              Das ist die Beschreibung, wie die Leitung tatsächlich (jetzt schon „meist“ und zukünftig „nur noch“) genutzt wird. Dennoch würde ich weiterhin von der Telefonleitung reden wollen, als die sie einstmals verbuddelt wurde und wozu sie, wenngleich auf anderer technischer Grundlage, unter Anderem auch weiterhin dient. Vielleicht ist's auch nur die Macht der Gewohnheit, von der ich nicht lassen mag.

                              Tschö, Auge

                              --
                              Wir hören immer wieder, dass Regierungscomputer gehackt wurden. Ich denke, man sollte die Sicherheit seiner Daten nicht Regierungen anvertrauen.
                              Jan Koum, Mitgründer von WhatsApp, im Heise.de-Interview
                              1. Tach,

                                Ich selbst habe noch einen analogen Telefonanschluss mit echter™ Tonübertragung und Splitter vor dem DSL-Modem.

                                und ich hatte noch nie einen eigenen Telefonanschluss, sondern seit knapp 15 Jahren einen reinen Internetanschluss, an dem auch nie etwas, das „normale“ Leute als Telefon erkennen würden, angeschlossen war.

                                Dennoch würde ich weiterhin von der Telefonleitung reden wollen, als die sie einstmals verbuddelt wurde und wozu sie, wenngleich auf anderer technischer Grundlage, unter Anderem auch weiterhin dient. Vielleicht ist's auch nur die Macht der Gewohnheit, von der ich nicht lassen mag.

                                Von einer Telefonleitung würde ich erwarten, dass ich damit telefonieren kann, wenn das „Internet ausfällt“, und dieses Bild wird nicht aus den Köpfen der Menschen verschwinden, solange wir den alten Begriff weiterverwenden; aber ich weiß, was du meinst.

                                mfg
                                Woodfighter

                                1. Hallo

                                  Dennoch würde ich weiterhin von der Telefonleitung reden wollen, als die sie einstmals verbuddelt wurde und wozu sie, wenngleich auf anderer technischer Grundlage, unter Anderem auch weiterhin dient. Vielleicht ist's auch nur die Macht der Gewohnheit, von der ich nicht lassen mag.

                                  Von einer Telefonleitung würde ich erwarten, dass ich damit telefonieren kann, wenn das „Internet ausfällt“, und dieses Bild wird nicht aus den Köpfen der Menschen verschwinden, solange wir den alten Begriff weiterverwenden; aber ich weiß, was du meinst.

                                  Ich weiß auch, waovon du sprichst. In der Störungsannahme bei KDG, also auch bei mir, schlugen ja z.B. jene auf, bei denen „das Internet und das Telefon ausgefallen!!!!1!!!!11!elf“ waren. Des technischen Zusammenhangs, dass das Erste zwangsläufig das Zweite mitreißt, war sich kaum jemand bewusst. Ich bezweifle aber, dass das Weglassen oder die Ersetzung des alten Begriffs „Telefonleitung“ irgendwas bringt. Telefon bleibt im Bewusstsein der Menschen Telefon, egal, wie es realisiert wird. Derzeit heißt das Buzzword „VoIP“, der technische Hintergrund, besonders eben der Unterschied zur klassischen Telefonie, bleibt den meisten Nutzern aber dennoch verborgen. Vom fehlenden technischen Verständnis, was ja zur Nutzung nicht vorausgesetzt werden kann, will ich erst garnicht anfangen.

                                  In der hiesigen Diskussion sehe ich das aber nicht so eng. Es geht hier ja nicht darum, dass das Telefonieren heutzutage meist ein Internetdienst wie z.B. Musikstreaming, nur mit zwei Richtungen des Datenverkehrs, ist und kein Zweirichtungsradio mit direkter physikalischer Verbindung der Beteiligten, wie früher. Hier geht's nur um die Unterscheidung der Wege (Zweidrahtleitung [1] vs. Breitbandkabel [2]), auf denen der Internetzugang erfolgen kann.

                                  Tschö, Auge

                                  --
                                  Wir hören immer wieder, dass Regierungscomputer gehackt wurden. Ich denke, man sollte die Sicherheit seiner Daten nicht Regierungen anvertrauen.
                                  Jan Koum, Mitgründer von WhatsApp, im Heise.de-Interview

                                  1. Um das Telefonwort zu vermeiden ;-) ↩︎

                                  2. Glasfaser und andere Wege mal außen vor gelassen ↩︎

                      2. Tach,

                        ISP steht für InternetServiceProvider. Eigentlich sind alle™ Nutzer von einer Zwangstrennung gegen Mitternacht betroffen.

                        das alle kann man mindestens auf ADSL einschränken (bei anderen Verbindungstypen habe ich zumindest bisher keine gesehen) und da betrifft es auch nicht alle Anbieter, z.B. Vodafone hat es IIRC abgeschafft und QSC hatte es nie.

                        mfg
                        Woodfighter

                        1. Moin!

                          O2 hat es, ich fliege aller 24h zwecks Neueinwahl raus. (Und das ist nur zum Teil schlecht... sonst würde ich darauf bestehen, dass mein Router in der Admin-Oberfläche eine Taste für "Neue IP anfordern" hat.)

                          Jörg Reinholz

                        2. Hallo woodfighter,

                          Eigentlich sind alle™ Nutzer von einer Zwangstrennung gegen Mitternacht betroffen.

                          das alle kann man mindestens auf ADSL einschränken (bei anderen Verbindungstypen habe ich zumindest bisher keine gesehen) und da betrifft es auch nicht alle Anbieter, z.B. Vodafone hat es IIRC abgeschafft und QSC hatte es nie.

                          Telekom LTE (Call und Surf via Funk) führt auch eine Zwangstrennung durch.

                          Bis demnächst
                          Matthias

                          --
                          Das Geheimnis des Könnens liegt im Wollen. (Giuseppe Mazzini)
                          1. Tach,

                            das alle kann man mindestens auf ADSL einschränken (bei anderen Verbindungstypen habe ich zumindest bisher keine gesehen) und da betrifft es auch nicht alle Anbieter, z.B. Vodafone hat es IIRC abgeschafft und QSC hatte es nie.

                            Telekom LTE (Call und Surf via Funk) führt auch eine Zwangstrennung durch.

                            ok, gut zu wissen.

                            mfg
                            Woodfighter

                    2. Moin!

                      Ich möchte auf gar keinen Fall selber irgendwelche Textdateien erstellen und speichern müssen, weil das meist der Anfang vom Ende ist :)

                      Kleine Einrede:
                      Du willst nicht ernsthaft "was mit login" machen und hast beim Umgang mit Dateien Probleme? Oi oi!

                      Zum Stoff:

                      Wenn Du an Deinem PHP nicht herumgespielt hast, dann wird die Session im /tmp/ gespeichert. Es ist eine Textdatei mit der Session-ID im Name.

                      Ich geh mal kucken ...

                      Ah! Da ist eine:

                      -rw------- 1 www-data www-data 112 Feb 29 12:06 sess_mdtta7ok5l0id56cep4qvcoln0
                      

                      Inhalt:

                      username|s:3:"foo";groups|a:3:{s:13:"standard-user";b:1;s:4:"test";b:1;s:4:"user";b:1;}last_action|i:1456743973;
                      

                      (Eine Zeile...)

                      Das ist die serialisierte Session, aber das muss Dich nicht kümmern.

                      In PHP sieht die so aus:

                      $_SESSION['id']|mdtta7ok5l0id56cep4qvcoln0|#Der Dateiname ohne den Vorbau 'sess_'  
                      $_SESSION['username']|foo|
                      $_SESSION['groups'][0]|standard-user|
                      $_SESSION['groups'][1]|test|
                      $_SESSION['groups'][2]|user|
                      $_SESSION['last_action']|1456743973|#Sekunden. seit 1.1.1970 00:00
                      

                      Wenn Du genau diese Daten nochmal speichern willst, dann mach nach dem Login einfach:

                      $_SESSION['sess_id']=session_id();
                      $sessJSON = json_encode($_SESSION);
                      $cookieFile = $deinSessionDir . '/' . $_SESSION['sess_id'];
                      file_put_contents($cookieFile, $sessData);
                      $_COOKIE['LoginToken'] = $_SESSION['sess_id'];
                      

                      Wie gesagt, ein eigener Ordner. Diesen Spaß machst Du Dir bei jedem erfolgreichen Login.

                      Den hechelst Du regelmäßig durch um zu alte Daten zu löschen:

                      <?php
                      ## file: delete_old_extrasessions.php
                      
                      delete_old_extrasessions('/tmp', 10) { # 10 Tage, nicht drei ...
                      function delete_old_extrasessions( $deinSessionDir = '/tmp', $maxTage = 3 ) {
                        $d = dir($deinSessionDir);
                        while (false !== ($entry = $d->read())) {
                         if ( '.' != substr ( $entry , 0, 1) ) { # kein dir - Eintrag, keine versteckte Datei .htaccess!
                          $mtime = filemtime($entry); # letzte Änderung! Sek. seit 1.1.1970
                          if ( date('U')-($maxTage * 24 * 60 * 60)) > $mtime ) { # wenn die Datei vor n tagen geändert wurde
                           unlink($entry); # weg damit!
                         }
                       }
                      }
                      

                      Das kann z.B. ein cronjob erledigen: crontab -e und das hier eintragen:

                      #m h  dom mon dow command
                       * \1 *   *   *   /usr/bin/php /pfad/zu/delete_old_extrasessions.php
                      

                      Sonst irgendwo includieren, was einmal am Tag aber nicht aller 2 Sekunden aufgerufen wird.

                      So. Jetzt kommt ein Benutzer vorbei.

                      1. Prüfung: hat er eine Session-ID?

                      wenn ja -> wie gehabt.

                      wenn nein:

                      2. Prüfung: Sendet er ein Cookie mit einem Token (die sess_id reicht...?

                      wenn nein -> login();

                      wenn ja:

                      3. Prüfung: Gibt es die Datei mit dem Token als Dateiname?

                      wenn nein -> login();

                      wenn ja:

                      $json = file_get_contents($_COOKIE['Token']);
                      session start();
                      $_SESSION = json_decode($json);
                      $_SESSION['last_action']=date('U');
                      

                      Und das war es... behandle den Benutzer wie soeben eingeloggt. Speichere also auch die Datei für den Cookie-Abgleich neu ($_SESSION['last_action'] sei jetzt und hier der Zeitpunkt des letzten Logins) und sende auch das Cookie neu um dessen Gültigkeitsfrist neu zu setzen.

                      Jörg Reinholz

                      1. Hi Jörg,

                        Kleine Einrede:
                        Du willst nicht ernsthaft "was mit login" machen und hast beim Umgang mit Dateien Probleme? Oi oi!

                        Nein, das nicht. Aber ich würde lieber alles in der Datenbank speichern. Damit komme ich gut zurecht. Aber ich probiere es mal so, wie du hier beschrieben hast, ist ja nicht viel Aufwand. Danke dir für die Hilfe. Ich habe jedenfalls verstanden, was ich tun muss. Ich probiere deine Variante, und werde auch mal meine Variante antesten. Also Token in DB. Ich guck einfach mal, was dabei rauskommt.

                        Danke euch allen vorerst hier im Thread.

                        Bis bald

                        --
                        Hosen sind Blau
                    3. Moin!

                      password_verify    // antworten auf nie gestellte Fragen sind immer noch die besten :)
                      

                      Du hast password_needs_rehash($hash) vergessen. Wenn das true zurück gibt, dann kannst Du bei jedem Login den gespeicherten Passwort-Hash durch den neuen Hash des soeben übermittelten Passworts ersetzen und so werden nach und nach alle Benutzerpasswörter mit der sichersten (im installierten und upgedateten PHP möglichen) Methode gehasht.

                      Deswegen auch keine eigene Methode implementieren....

                      Jörg Reinholz

                      1. Hi Jörg,

                        password_verify    // antworten auf nie gestellte Fragen sind immer noch die besten :)
                        

                        Du hast password_needs_rehash($hash) vergessen.

                        Ja, soweit war ich noch nicht. Aber tatsache, das sollte ich wirklich nicht vergessen. Danke!

                        Bis bald

                        --
                        Hosen sind Blau
            2. Tach,

              Aber das,w as ich im Cookie speichere, hat ja so mit dem eigentlichen Passwort nichts mehr zutun.

              Jörg hat durch draufschauen erkannt, was es ist.

              Es ist quasi doppelt und dreifach gehashed. Und wenn man den Cookie richtig benennt, dann könnte eh keiner daraus schliessen, was die ganzen Werte in den Cookies zu bedeuten haben. Gut, das wäre dann wieder Security through obscurity. Aber ein doppelt, von mir aus 3 mal gehashter String? Um diese zu knacken, müsste ja erstmal festgestellt werden, wie oft ich es gehasht habe, um daraus dann das Passwort zu errechnen. Da nutzen Rainbowtable nicht viel.

              Wenn es einen praktikablen Preimage-Angriff gibt, brauche ich keine Rainbow-Tables mehr; dann erzeuge ich passende Strings für einen Hash und kann vermutlich auch passende erzeugen, so dass sie mit deinem Salt beginnen; der Rest ist dann das Klartext-Passwort oder der Klartext-md5-Hash, der dann wieder erkennbar ist…

              Weiterhin gehst du davon aus, dass ein Angreifer keinen Zugriff auf den genau von dir verwendeten Algorithmus hat; erfahrungsgemäß ist das ein Fehlschluss und es gibt Algorithmen, die diese Voraussetzung nicht brauchen, also verwende einfach diese. Crypt selber machen ist immer eine schlechte Idee.

              Meinst du, das folgende könnte geknackt werden?

              password = 4a4350df2403b94a13304ee88b861041
              
              // Im Cookie z.B.
              md5( md5(password ) )
              

              Für mich ist es ja egal, wie oft ich die Strings hashe.

              Für den Angreifer auch.

              mfg
              Woodfighter

    2. Hi Jörg,

      userid | Pass (gehasht) 1 | 4a4350df2403b94a13304ee88b861041

      Oh. Ist das etwa MD5?

      Ja.

      md5 (irgendeinstring.USEREINGABE.nocheinstring)
      

      Ist das auch unsicher?

      Bis bald

      --
      Hosen sind Blau
      1. Tach,

        md5 (irgendeinstring.USEREINGABE.nocheinstring)
        

        Ist das auch unsicher?

        ja, Salts helfen gegen Rainbow-Tables nicht gegen schwache Hash-Funktionen.

        mfg
        Woodfighter

      2. Moin!

        md5 (irgendeinstring.USEREINGABE.nocheinstring)
        

        Ist das auch unsicher?

        Das ist sowas von 1990, das will man gar nicht mehr diskutieren. Natürlich kannst Du die Passwörter auch mit einer Enigma verschlüsseln, was 1943 noch ganz gut funktioniert hat - oder etwas wie rot13() verwenden, was bei den Römern in diversen Abwandlungen beliebt war!

        Benutze password_hash(), password_verify() und password_needs_rehash(). Oder ist das zu einfach?

        Jörg Reinholz

    3. Das genügt nicht. Ist unsicher..

      Ich spiele in diesem Fall nur sehr ungern die Rolle des Kritikers, insbeondere in Ermangelung anzubietender Alternativen. Ich habe fernen überhaupt keinen Zweifel daran, dass die Intention des Autors durchweg positiv ist und viel Mühe und Arbeit in den Wiki-Artikel geflossen ist. Das macht mir die folgenden Worte umso schwieriger. Der Artikel ist nun leider von diversen technischen und didaktischen Problemen übersäht, dadurch sehe ich die Computersicherheit unserer Leserschaft gefährdet. Bei diesem heiklen Thema möchte ich deshalb keine falsche Zurückhaltung üben.

      Zum einen denke ich, dass der verlinkte Artikel seiner didaktischen Aufgabe nicht gerecht wird. Unsere Leserschaft und Zielgruppe sind lernende Anfänger. Dieser Personengruppe bleibt mangels Erfahrung und Fachkenntniss nicht viel mehr übrig als den Autoren einen Vertrauensvorschuss zu gewähren. Ein Artikel über Computersicherheit sollte deshalb hauptsächlich für die Komplexität und potenzielle Gefahren dieses Themas sensibilisieren. Der Artikel macht das nicht, er stumpft sogar dagegen ab: Beispielsweise empfiehlt der Artikel bei veralteten PHP-Versionen, die crypt-Funktion mit einer eigenen Implementation nachzurüsten. Dabei ist bekannt, dass PHP-Versionen kleiner als 5.4 selber keine Security-Patches mehr erhalten. Darauf aufbauend ist es defakto unmöglich ein sicheres Authentifizierungssystem zu entwickeln.

      Weiterhin ist der Artikel in dem Bereich Anwendung und Praxis angesiedelt. Das beschriebene Loginsystem weicht allerdings vollkommen von der Architektur professioneller Systeme ab. Das ist deshalb schlecht, weil es den Leser nicht auf den Umgang mit solchen Systemen vorbereitet und dadurch zum Selbermachen animiert - und gerade in puncto Sicherheit ist das in 99,99% aller Fälle die schlechtere Alternative.

      Zum anderen birgt der Artikel auch technische Fehler und Gefahren. So benutzt der bereits angesprochene Polyfill die PHP-Funktion rand. Diese Funktion berechnet allerdings nur Pseudozufallszahlen und ist für kryptographische Zwecke daher vollkommen ungeeignet. Das PHP-Manual warnt deswegen ausdrücklich vor Einsätzen dieser Art. Mathematisch betrachtet ist die daraus resultierende Hashfunktion genauso sicher zu bewerten wie eine Hashfunktion ganz ohne Salt. Der sicherheitsrelevante Beitrag ist maximal durch security-by-obscurity gegeben, dessen Nutzen auch stark angezweifelt wird.

      Ferner fehlt es dem Code an jeglicher Strukturierung und Modularität. Bei deraritgen Sicherheitssystemen will man die Korrektheit und Zuverlässigkeit auf gar keinen Fall dem Zufall überlassen. Es ist deshalb in besonders hohem Maße wichtig den Quellcode so zu strukturieren, dass er in vorhersehbarer Art und Weise agiert. Meistens geht man sogar einen Schritt weiter und verifiziert die (partielle) Korrektheit mittels formaler Methoden. Mit so sündhaften Konstrukten wie das Einstreuen von die()-Anweisungen, das Mischen von Programmlogik mit Ausgabe und der Synthese von einander abhängigen Speicherzuständen ist das nicht durchführbar.

      Mir fällt es schwer das zu sagen, aber der Artikel sollte unbedingt aus dem Wiki entfernt werden. Auch wenn das bedeutet, dass dadurch eine Lücke ensteht. Mindestens jedoch sollte eine riesieges Wanrschild darüber prangern.

  3. Lieber Malcolm Beck`s,

    wenn Du PHP nutzt, dann solltest Du das Generieren einer Session-ID den Automatismen von PHP überlassen. Die machen das im Regelfall besser als eine handgeschöpfte oder mundgeblasene Lösung von Dir.

    Ich speichere die Logindaten in Form von:

    userid | Pass (gehasht) 1 | 4a4350df2403b94a13304ee88b861041

    Für den Hash verwendest Du password_hash()? Sieht nicht so aus, solltest Du aber. Aus der Kombination von password_hash() und password_verify() solltest Du ausreichend sichere Hashes bekommen.

    Beim Login versuche ich 2 Cookies zu setzen. Ein SESSION-Cookie und einen normalen.

    Was bitte ist ein "normales" Cookie? Zu Deiner Domain legt der Browser ein Cookie ab, in welches Du Daten schreiben lassen kannst. Es empfiehlt sich sehr, dass Da nur und ausschließlich die Session-ID steht. Alles andere speicherst Du in der Session. Wenn der User keine Cookies zulässt, dann brauchst Du einen URL-Parameter mit der Session-ID, was noch ein Grund mehr ist, überhaupt nur diese Information an den User auszugeben. Auch für diesen Fall bietet PHP diverse Voreinstellungen an, die Du nutzen (oder selbst implementieren) kannst.

    // userid mit irgendwas multipliziert
    $_SESSION['USER'] = '541 4a4350df2403b94a13304ee88b861041';
    $_COOKIE['USER']  = '541 4a4350df2403b94a13304ee88b861041';
    

    Das bedeutet, dass die Passwort-Informationen im Cookie des Users auf dessen Computer abgelegt werden. Das willst Du nicht, da bin ich mir sicher, denn Du weißt, dass die Cookie-Daten unverschlüsselt durchs Netz gehen, wenn Du keine https-Verbindung hast. Und selbst wenn, könnten eventuelle XSS-Attacken die Cookie-Daten herausleiten und so eventuell die Passwortdaten "befreien".

    // Wenn Session, aber kein Cookie, Loginformular - damit ist schonmal Session Hijacking unterbunden
    if $_SESSION['USER'] AND !$_COOKIE['USER']
      exit()
    

    Ein Session-Hijacking unterbindest Du sinnvollerweise dadurch, dass Du bei jedem Request eine neue Session-ID generieren lässt. Diese Herangehensweise stört sich allerdings mit der Idee, die Session-ID über einen URL-Parameter zu übertragen (denke an AJAX-Calls und die href- bzw. action-Werte im Dokument). Eventuell ist ein Cookie-Zwang für diverse Bereiche Deiner Seite Grundvoraussetzung.

    // Wenn Session und Cookie vorhanden sind, Datenbankabfrage sparen, da die Sessiondaten auf dem Server liegen und vom Nutzer nicht geändert werden können
    if $_SESSION['USER'] AND $_COOKIE['USER']
    
      // Sessiondaten mit Cookiedaten vergleichen, wenn beide richtig, ist User eingeloggt
      // Kann ich das so machen?
      $_COOKIE['USER'][0] == $_SESSION['USER'][0]
      $_COOKIE['USER'][1] == $_SESSION['USER'][1]
    
    // Automatisches Login: Datenbank mit den Daten im Cookie abfragen, wenn keine Session vorhanden ist
    if $_COOKIE['USER'] AND !$_SESSION['USER']
    
      // wenn beide Daten im Cookie richtig sind, ist User authentifiziert
      $_COOKIE['USER'][0] == $_USERINDB
      $_COOKIE['USER'][1] == $_USERPASSINDB
    

    Entweder der User kommt mit einer gültigen Session-ID an, oder nicht. Sollten seine Session-Daten in Ordnung sein, ist er auch eingeloggt. Das kannst Du damit überprüfen, indem Du in den Session-Daten (aber nicht im Cookie und schon gar nicht in irgendeinem URL-Parameter!!) das Passwort des Users (gerne als Hash aus der DB) ablegst und bei einem Request gegen den Hash aus der DB abgleichst.

    Ich könnte das ganze jetzt um eine weitere Prüfung erweitern, in dem ich einfach alle vom User genutzten IPs beim Login checke, ob die aktuell nur mit Cookie aufrufende IP schon einmal genutzt wurde, wenn nicht, Login erzwingen. Ohne diese Prüfung könnte ein Hacker, wenn er die Userid und das gehashte Passwort richtig errät, das Profil kapern. Was aber ja auch schon schwierig genug sein dürfte.

    Warum? Du hast bei manchen Providern den Fall, dass Leute bei einem Seitenaufruf die einzelnen Dateien mit unterschiedlichen IP-Adressen aufrufen, da der Provider die Requests über einen Pool an IP-Adressen leitet. Das würde die User-Experience im Zweifelsfall empfindlich behindern!

    Um Deine Sicherheit zu erhöhen, kannst Du beim Einloggen mit einer Zwei-Faktor-Authentifizierung arbeiten: Nach dem Login mit Usernamen und Passwort verschickst Du eine Mail mit einem Zufallswert, der ergänzend eingegeben werden muss, der nur etwa fünf Minuten lang gültig ist und nach der ersten Verwendung sofort ungültig wird, bevor die Session einen vollständigen Login speichert. Danach hast Du Deine Session, deren "Sicherheit" Du nur durch eine sich bei jedem Request ändernde Session-ID gegen Session-Hijacking härten kannst (bedeutet Cookie-Pflicht). Sonst gibt es da meines Wissens nichts, was Du noch tun könntest.

    Liebe Grüße,

    Felix Riesterer.

    1. Hallo Felix,

      Beim Login versuche ich 2 Cookies zu setzen. Ein SESSION-Cookie und einen normalen.

      Was bitte ist ein "normales" Cookie? Zu Deiner Domain legt der Browser ein Cookie ab, in welches Du Daten schreiben lassen kannst. Es empfiehlt sich sehr, dass Da nur und ausschließlich die Session-ID steht. Alles andere speicherst Du in der Session.

      Am besten speichert man nur das in der Session, was sich nicht umgehen lässt. Z.B. die ID des Users, der sich eingeloggt hat. Nicht aber das User-Objekt aus der Datenbank.

      Wenn der User keine Cookies zulässt, dann brauchst Du einen URL-Parameter mit der Session-ID […]

      Diese Technik ist veraltet und sollte nicht mehr verwendet werden, sie birgt zahlreiche Fallstricke. Der offensichtliche Grund ist, dass Links dann nicht mehr kopiert und an dritte weitergeschickt werden können. Wenn der User keine Cookies zulässt, sollte er keinen Zugriff bekommen.

      was noch ein Grund mehr ist, überhaupt nur diese Information an den User auszugeben. Auch für diesen Fall bietet PHP diverse Voreinstellungen an, die Du nutzen (oder selbst implementieren) kannst.

      Von der Verwendung von session.use_trans_sid wird abgeraten, sie vereinfacht session fixation stark.

      // userid mit irgendwas multipliziert
      $_SESSION['USER'] = '541 4a4350df2403b94a13304ee88b861041';
      $_COOKIE['USER']  = '541 4a4350df2403b94a13304ee88b861041';
      

      Das bedeutet, dass die Passwort-Informationen im Cookie des Users auf dessen Computer abgelegt werden. Das willst Du nicht, da bin ich mir sicher, […]

      Urgh, ja, das will man definitiv nicht.

      // Wenn Session, aber kein Cookie, Loginformular - damit ist schonmal Session Hijacking unterbunden
      if $_SESSION['USER'] AND !$_COOKIE['USER']
        exit()
      

      Ein Session-Hijacking unterbindest Du sinnvollerweise dadurch, dass Du bei jedem Request eine neue Session-ID generieren lässt.

      Diese Aussage halte ich nicht für haltbar.

      Schauen wir uns mal an, welche Angriffsvektoren es für Session Hijacking gibt:

      • Cookie mitschnüffeln über eine unverschlüsselte Verbindung. Da hilft das Vergeben einer neuen Session-ID gar nichts, denn ich bekomme ja auch immer die Antwort des Servers mit. Das einzige, was hier hilft, ist HTTPS; die Cookies sollten dann mit force SSL flag gesetzt werden.
      • Die Leute sitzen an einem öffentlich zugänglichen Gerät und loggen sich nicht aus wenn sie gehen; hier hilft das vergeben einer neuen Session-ID gar nichts, denn der Angreifer ist ja am selben Rechner wie die Person zuvor. Hier hilft es nur, einen Logout-Button anzubieten, möglichst prominent.
      • Der Cookie wird über XSS erschnüffelt. Hier hilft es am ehesten, den Cookie JS nicht zugänglich zu machen. secure, wie oben schon erwähnt, und httponly sollten in jedem Fall gesetzt werden.
      • Session Fixation. Der Angreifer erstellt sich ein valides Session-Token (z.B. indem er die Login-Seite besucht) und schiebt dieses Token dem User unter, z.B. über XSS. Der wiederum loggt sich mit diesem Session-Token ein. Hier hilft es tatsächlich, eine neue Session-ID zu erstellen, das ist auch gängige Praxis: nach der Authentifizierung wird eine neue Session-ID generiert, so dass der Angreifer nicht mehr die alte Session-ID nutzen kann.

      Entweder der User kommt mit einer gültigen Session-ID an, oder nicht. Sollten seine Session-Daten in Ordnung sein, ist er auch eingeloggt. Das kannst Du damit überprüfen, indem Du in den Session-Daten (aber nicht im Cookie und schon gar nicht in irgendeinem URL-Parameter!!) das Passwort des Users (gerne als Hash aus der DB) ablegst und bei einem Request gegen den Hash aus der DB abgleichst.

      Welche zusätzliche Sicherheit bietet das? Entweder die Session ist im Cookie gespeichert, dann ist sie prinzipiell auch manipulierbar. Wenn nicht bei der User-ID, dann ggfls woanders. Hier nutzt man aus genau diesem Grund kryptografisch signierte Session-Daten.

      Oder die Session-Daten sind, wie z.B. bei PHP üblich, in der Datenbank oder in Session-Dateien gespeichert, dann kann die Session auch nicht manipuliert werden.

      Eine „Absicherung“ über eine erneute Prüfung des Hashes ist nicht sinnvoll, denn es greift zu wenig weit im ersten Fall oder ist überflüssig im zweiten Fall.

      Ich könnte das ganze jetzt um eine weitere Prüfung erweitern, in dem ich einfach alle vom User genutzten IPs beim Login checke, ob die aktuell nur mit Cookie aufrufende IP schon einmal genutzt wurde, wenn nicht, Login erzwingen. Ohne diese Prüfung könnte ein Hacker, wenn er die Userid und das gehashte Passwort richtig errät, das Profil kapern. Was aber ja auch schon schwierig genug sein dürfte.

      Warum? Du hast bei manchen Providern den Fall, dass Leute bei einem Seitenaufruf die einzelnen Dateien mit unterschiedlichen IP-Adressen aufrufen, da der Provider die Requests über einen Pool an IP-Adressen leitet. Das würde die User-Experience im Zweifelsfall empfindlich behindern!

      Das ist zwar prinzipiell richtig, aber fehlendes Rate Limiting ermöglicht auch einen Brute-Force-Angriff. Deshalb ist es heutzutage eher üblich, den Zugriff durchaus zu beschränken. Welches Kriterium dort herangezogen wird ist allerdings unterschiedlich; häufig wird trotzdem die IP benutzt, manche nutzen eine Session-ID, manche andere Kriterien.

      LG,
      CK

      1. Hi Christian,

        Am besten speichert man nur das in der Session, was sich nicht umgehen lässt. Z.B. die ID des Users, der sich eingeloggt hat. Nicht aber das User-Objekt aus der Datenbank.

        Aber für einen Angreifer wäre es doch einfacher, irgendeine UserID zu erraten. Mit dem gehashten Passwort dahinter wird es etwas schwieriger.

        Ich frage mich gerade, warum ich gehashte Passwörter nicht in einem Cookie speichern soll. Also ich verstehe es Praktisch nicht. Würde etwas weiterhin dagegen sprechen, wenn ich password_hash() nutze? Dann sind die Daten ja noch mehr verunstaltet. password_hash() werde ich auf jedenfall schon mal implementieren.

        Das bedeutet, dass die Passwort-Informationen im Cookie des Users auf dessen Computer abgelegt werden. Urgh, ja, das will man definitiv nicht.

        Auch nicht, wenn die Daten gehashed und verunstaltet sind?

        secure, wie oben schon erwähnt, und httponly sollten in jedem Fall gesetzt werden.

        Ja, httponly hatte ich auch noch nicht ganz verstanden.

        nach der Authentifizierung wird eine neue Session-ID generiert, so dass der Angreifer nicht mehr die alte Session-ID nutzen kann.

        Wie mach ich das? Wenn ich den Sessionwert im Cookie nach dem Login ändere, passiert irgendwie nichts. Ich werde nicht mal ausgeloggt. Wonach richtet sich die Session? Ich dachte, der Wert im Cookie für die Session ist das wichtige zur erkennung des Users, aber selbst wenn ich diesen Wert ändere, ist die Session noch Aktiv. Ist die Session an die IP des Users gebunden?

        Bis bald

        --
        Hosen sind Blau
        1. Hallo Malcolm,

          Am besten speichert man nur das in der Session, was sich nicht umgehen lässt. Z.B. die ID des Users, der sich eingeloggt hat. Nicht aber das User-Objekt aus der Datenbank.

          Aber für einen Angreifer wäre es doch einfacher, irgendeine UserID zu erraten.

          Das erraten bringt ihm aber doch nichts. Die Session verlässt den Server nicht, siehe auch mein voriges Posting.

          Ich frage mich gerade, warum ich gehashte Passwörter nicht in einem Cookie speichern soll. Also ich verstehe es Praktisch nicht. Würde etwas weiterhin dagegen sprechen, wenn ich password_hash() nutze?

          Du kannst doch nie wissen, ob der verwendete Hashing-Algorithmus nicht doch eine Lücke hat, die einem das erraten/errechnen des Passworts erlauben. Passwörter sind das Geheimnis, dass man benötigt, um Zugriff zu erhalten. Die schreibt man nicht an die Pinwand.

          nach der Authentifizierung wird eine neue Session-ID generiert, so dass der Angreifer nicht mehr die alte Session-ID nutzen kann.

          Wie mach ich das?

          Mit session_regenerate_id (natürlich mit $delete_old_session auf true gesetzt).

          Wonach richtet sich die Session? Ich dachte, der Wert im Cookie für die Session ist das wichtige zur erkennung des Users

          Die Session-ID wird verwendet, um die Session wiederzuerkennen, richtig.

          aber selbst wenn ich diesen Wert ändere, ist die Session noch Aktiv. Ist die Session an die IP des Users gebunden?

          Die oben erwähnte Funktion erzeugt eine neue Session-ID, so dass ein potentieller Angreifer nicht dieselbe Session-ID verwenden kann, mit der er den User zum Login-Form geschickt hat (Stichwort Session Fixation). Die alte Session-ID ist dann schlicht und ergreifend nicht länger mit der Session des Users verknüpft.

          LG,
          CK

          1. Hi Christian,

            Mit session_regenerate_id (natürlich mit $delete_old_session auf true gesetzt).

            Würde es genügen, wenn ich nach dem Login session-regenerate-id einmalig starte und im späteren Scriptverlauf wieder deaktiviere? dauerhaft nutzen möchte ich es nicht wirklich.

            Die oben erwähnte Funktion erzeugt eine neue Session-ID, so dass ein potentieller Angreifer nicht dieselbe Session-ID verwenden kann, mit der er den User zum Login-Form geschickt hat (Stichwort Session Fixation). Die alte Session-ID ist dann schlicht und ergreifend nicht länger mit der Session des Users verknüpft.

            Nach dreimaligem lesen habe ich es verstanden, klingt Logisch.

            Machen Hacker das so? Also das sie die User zu meinem Formular schicken?

            Achso, Hacker rufen die Seite auf, generieren so eine Session-ID, und schicken dann den User mit dieser Session auf meine Seite. Und wenn der User sich dann mit dieser Session anmeldet, ist der Hacker automatisch auch eingeloggt? Können wir auf meiner Seite probieren, ob das geht? Du kannst dich mit einzelnen Buchstaben registrieren und sofort einloggen. Auf der Seite stehen auch alle benötigten Daten, bspw. was in der Session und was in den Cookies gespeichert ist. Können wir mich hacken?

            Bis bald

            --
            Hosen sind Blau
            1. Hallo Malcolm,

              Mit session_regenerate_id (natürlich mit $delete_old_session auf true gesetzt).

              Würde es genügen, wenn ich nach dem Login session-regenerate-id einmalig starte und im späteren Scriptverlauf wieder deaktiviere? dauerhaft nutzen möchte ich es nicht wirklich.

              Ja. Es langt, das einmal direkt nach dem erfolgreichen Login zu machen, allerdings bevor eine Antwort an den User geschickt wird.

              Die oben erwähnte Funktion erzeugt eine neue Session-ID, so dass ein potentieller Angreifer nicht dieselbe Session-ID verwenden kann, mit der er den User zum Login-Form geschickt hat (Stichwort Session Fixation). Die alte Session-ID ist dann schlicht und ergreifend nicht länger mit der Session des Users verknüpft.

              Nach dreimaligem lesen habe ich es verstanden, klingt Logisch.

              Es tut mir leid, dass das so schwer verständlich war; darf ich fragen, woran es lag? Dann wäre ich beim nächsten mal vielleicht in der Lage mich verständlicher auszudrücken.

              Machen Hacker das so? Also das sie die User zu meinem Formular schicken?

              Achso, Hacker rufen die Seite auf, generieren so eine Session-ID, und schicken dann den User mit dieser Session auf meine Seite.

              Richtig.

              Und wenn der User sich dann mit dieser Session anmeldet, ist der Hacker automatisch auch eingeloggt?

              Naja, da er die Session-ID des Users kennt: ja. Er muss ja nur die gleiche Session-ID zum Server schicken.

              Können wir auf meiner Seite probieren, ob das geht? Du kannst dich mit einzelnen Buchstaben registrieren und sofort einloggen. Auf der Seite stehen auch alle benötigten Daten, bspw. was in der Session und was in den Cookies gespeichert ist. Können wir mich hacken?

              Ehrlich gesagt geht mir das jetzt ein wenig zu weit.

              LG,
              CK

              1. Hi Christian,

                Es tut mir leid, dass das so schwer verständlich war; darf ich fragen, woran es lag? Dann wäre ich beim nächsten mal vielleicht in der Lage mich verständlicher auszudrücken.

                Es lag nicht an dir. Ich weiss nicht, wie Hacker arbeiten. Ich konnte mir nicht vorstellen, wie Hacker dabei vorgehen. Ich kannte Session Hijacking, ahtte mich sogar selber schon gehackt^^ Aber das Hacker die User auf mein Formular umleiten, um sie zu hacken, ist mir komplett Neu.

                Und wenn der User sich dann mit dieser Session anmeldet, ist der Hacker automatisch auch eingeloggt? Naja, da er die Session-ID des Users kennt: ja. Er muss ja nur die gleiche Session-ID zum Server schicken.

                Das mit dem Session-regenerate werde ich auf jedenfall umsetzen, danke für den Tipp.

                Ehrlich gesagt geht mir das jetzt ein wenig zu weit.

                Schade, aber kein Problem :)

                Bis bald

                --
                Hosen sind Blau
            2. Tach,

              Machen Hacker das so?

              auf diese Frage ist die Antwort allgemein immer ja. Jede noch so abwegige scheinende Möglichkeit etwas zu brechen wird ausgenutzt. Wir reden hier über Menschen, die Ideen haben, wie Verschlüsselung über die Geräusche des Prozessors zu brechen oder RAM tiefzukühlen, um den Inhalt nach dem Stromabschalten zu erhalten; und die natürlich auch Ideen entwickeln, wie man solche Dinge verhindern kann.

              Können wir auf meiner Seite probieren, ob das geht? […] Können wir mich hacken?

              Das wäre nur so semi-hilfreich; hinterher wüßtest du dann, dass Christian, Jörg, ich oder wer auch immer dein System nicht brechen können, aber ob wir die nötigen Kompetenzen hatten, um genau die noch vorhandenen Lücken zu sehen, weißt du nicht. Penetration Testing ist ein kopliziertes Feld.

              mfg
              Woodfighter

              1. Tach,

                Jede noch so abwegige scheinende Möglichkeit etwas zu brechen wird ausgenutzt. Wir reden hier über Menschen, die Ideen haben, wie Verschlüsselung über die Geräusche des Prozessors zu brechen oder RAM tiefzukühlen, um den Inhalt nach dem Stromabschalten zu erhalten; und die natürlich auch Ideen entwickeln, wie man solche Dinge verhindern kann.

                und weil es so schön ist noch ein aktuelles Beispiel für einen Sidechannel, User-Identifikation über (u.a.) Mausbewegungen im Browser: Advanced Tor Browser Fingerprinting

                mfg
                Woodfighter

            3. Hallo,

              Können wir mich hacken?

              Ok, dann gieb mal dein IP, meine ist übrigens 127.0.0.1...

              Gruß
              Kalk

              1. Hallo

                Ok, dann gieb mal dein IP, meine ist übrigens 127.0.0.1...

                Hehe, hab' ich ja seit Jahren nicht mehr gelesen. :-)

                Tschö, Auge

                --
                Wir hören immer wieder, dass Regierungscomputer gehackt wurden. Ich denke, man sollte die Sicherheit seiner Daten nicht Regierungen anvertrauen.
                Jan Koum, Mitgründer von WhatsApp, im Heise.de-Interview
              2. Moin!

                Ok, dann gieb mal dein IP, meine ist übrigens 127.0.0.1...

                Das ist ja ein Ding! Wir sind im gleichen Klasse-A-Netz! Meine ist 127.128.129.130! Kannst Du etwa auf meinen Rechner zugreifen?

                Jörg Reinholz

      2. Lieber Christian,

        Am besten speichert man nur das in der Session, was sich nicht umgehen lässt. Z.B. die ID des Users, der sich eingeloggt hat. Nicht aber das User-Objekt aus der Datenbank.

        stellen wir uns das einmal vor: Der Account ist via Session-Hijacking kompromittiert. Der böse Hacker kann nun den Account nutzen, da er eine alte Session übernommen hat. Der eigentliche User hat sich neu angemeldet und eine neue Session begonnen. Nehmen wir an, dass der User nun das Passwort ändert. Würde der Session-Mechanismus das bei der Anmeldung eingegebene Passwort speichern und bei jedem Request gegen das in der DB prüfen, würde die Session des bösen Hackers plötzlich unbrauchbar, da in der übernommenen Session ein nicht mehr gültiges Passwort steht. Beim eigentlichen User wurde in der Session das geänderte Passwort natürlich eingetragen, damit seine Session weiter benutzbar bleibt, ohne dass eine indirekte Zwangsabmeldung erfolgt.

        Nach meinem bescheidenen Wissensstand ist das nur dann möglich, wenn Du einem User mehrere Sessions erlaubst (also die Session nicht in einer DB speicherst) und wenn Du das bei der Anmeldung benutzte Passwort in der Session speicherst.

        • Cookie mitschnüffeln über eine unverschlüsselte Verbindung. Da hilft das Vergeben einer neuen Session-ID gar nichts, denn ich bekomme ja auch immer die Antwort des Servers mit. Das einzige, was hier hilft, ist HTTPS; die Cookies sollten dann mit force SSL flag gesetzt werden.

        OK. Das ist wahr.

        • Die Leute sitzen an einem öffentlich zugänglichen Gerät und loggen sich nicht aus wenn sie gehen; hier hilft das vergeben einer neuen Session-ID gar nichts, denn der Angreifer ist ja am selben Rechner wie die Person zuvor. Hier hilft es nur, einen Logout-Button anzubieten, möglichst prominent.

        Unachtsamkeit kann man technisch nicht oder nur sehr schlecht vorbeugen.

        gängige Praxis: nach der Authentifizierung wird eine neue Session-ID generiert, so dass der Angreifer nicht mehr die alte Session-ID nutzen kann.

        In dem Moment, wo Du dem User eine bestimmte Session-ID unterjubeln kannst, musst Du seinen Client oder dessen Verbindung zum Server ausreichend kompromittiert haben, sodass eine neue Session-ID auch keine Rolle mehr spielen sollte.

        Entweder der User kommt mit einer gültigen Session-ID an, oder nicht. Sollten seine Session-Daten in Ordnung sein, ist er auch eingeloggt. Das kannst Du damit überprüfen, indem Du in den Session-Daten (aber nicht im Cookie und schon gar nicht in irgendeinem URL-Parameter!!) das Passwort des Users (gerne als Hash aus der DB) ablegst und bei einem Request gegen den Hash aus der DB abgleichst.

        Welche zusätzliche Sicherheit bietet das? Entweder die Session ist im Cookie gespeichert, dann ist sie prinzipiell auch manipulierbar. Wenn nicht bei der User-ID, dann ggfls woanders. Hier nutzt man aus genau diesem Grund kryptografisch signierte Session-Daten.

        Ich schreibe nichts in ein Cookie, sondern lasse PHP den Session-Namen (ist das etwas anderes als die Session-ID?) hineinschreiben, was PHP von selbst macht. Den Rest speichere ich in $_SESSION, was ich als "in der Session speichern" bezeichne. Das, was man in ein Cookie schreiben könnte, würde ich als "im Cookie speichern" nennen.

        Oder die Session-Daten sind, wie z.B. bei PHP üblich, in der Datenbank oder in Session-Dateien gespeichert, dann kann die Session auch nicht manipuliert werden.

        Letzteres war von vornherein mein Verständnis. Wie sollte man das sinnvoll anders machen? Die DB dafür bemühen hieße ja, dass ich Dinge neu implementiere, die mir PHP von selbst schon anbietet. Das vermeide ich gerne.

        Eine „Absicherung“ über eine erneute Prüfung des Hashes ist nicht sinnvoll, denn es greift zu wenig weit im ersten Fall oder ist überflüssig im zweiten Fall.

        Nicht dann, wenn ein User beliebig viele Sessions (z.b. in beliebig vielen Clients) starten kann und in einer davon das Passwort ändert und alle restlichen Sessions damit ihre Nutzbarkeit einbüßen sollen (s.o.).

        Vielleicht hatte ich mich einfach ungünstig ausgedrückt?

        Liebe Grüße,

        Felix Riesterer.

        1. Hallo Felix,

          Am besten speichert man nur das in der Session, was sich nicht umgehen lässt. Z.B. die ID des Users, der sich eingeloggt hat. Nicht aber das User-Objekt aus der Datenbank.

          Ich wollte hier darauf hinaus, dass man sparsam mit der Session umgeht. Man handelt sich sonst allerlei Probleme ein, z.B. Synchronisations-Probleme.

          stellen wir uns das einmal vor: Der Account ist via Session-Hijacking kompromittiert. Der böse Hacker kann nun den Account nutzen, da er eine alte Session übernommen hat. Der eigentliche User hat sich neu angemeldet und eine neue Session begonnen. Nehmen wir an, dass der User nun das Passwort ändert. Würde der Session-Mechanismus das bei der Anmeldung eingegebene Passwort speichern und bei jedem Request gegen das in der DB prüfen, würde die Session des bösen Hackers plötzlich unbrauchbar, da in der übernommenen Session ein nicht mehr gültiges Passwort steht. Beim eigentlichen User wurde in der Session das geänderte Passwort natürlich eingetragen, damit seine Session weiter benutzbar bleibt, ohne dass eine indirekte Zwangsabmeldung erfolgt.

          Das Beispiel halte ich für reichlich konstruiert. Viel Wahrscheinlicher ist es, dass der User das gar nicht mitbekommt. Und dass er just in diesem Augenblick zufällig sein Passwort ändert ist unrealistisch und nichts, worauf ich mich verlassen wollen würde.

          Und umgekehrt, mit den neuen Hashing-Verfahren, spätestens jedoch mit Argon2 ist das verifizieren des Passworts richtig teuer.

          Man kauft sich also einen zweifelhaften Sicherheitsgewinn mit viel CPU-Zeit.

          Wollte man diesen Fall allerdings abdecken, dann wäre das ein gangbarer Weg, ja.

          • Die Leute sitzen an einem öffentlich zugänglichen Gerät und loggen sich nicht aus wenn sie gehen; hier hilft das vergeben einer neuen Session-ID gar nichts, denn der Angreifer ist ja am selben Rechner wie die Person zuvor. Hier hilft es nur, einen Logout-Button anzubieten, möglichst prominent.

          Unachtsamkeit kann man technisch nicht oder nur sehr schlecht vorbeugen.

          Exakt darauf wollte ich hinaus ;-)

          gängige Praxis: nach der Authentifizierung wird eine neue Session-ID generiert, so dass der Angreifer nicht mehr die alte Session-ID nutzen kann.

          In dem Moment, wo Du dem User eine bestimmte Session-ID unterjubeln kannst, musst Du seinen Client oder dessen Verbindung zum Server ausreichend kompromittiert haben, sodass eine neue Session-ID auch keine Rolle mehr spielen sollte.

          Das ist nicht richtig. Übliches Szenario für eine Session Fixation ist eine XSS-Lücke, z.B. so:

          document.cookie = 'PHPSESSIONID=blub';
          

          Eine neue Session-ID, gerade wenn sie mit httponly und secure gesetzt wurde, wird allerdings auf Client-Seite nicht auftauchen.

          Ich glaube, du denkst noch nicht verwunden genug ;-)

          Ich schreibe nichts in ein Cookie, sondern lasse PHP den Session-Namen (ist das etwas anderes als die Session-ID?) hineinschreiben, was PHP von selbst macht. Den Rest speichere ich in $_SESSION, was ich als "in der Session speichern" bezeichne. Das, was man in ein Cookie schreiben könnte, würde ich als "im Cookie speichern" nennen.

          Die Definition ist irreführend. Es gibt die Session (als abstrakten Begriff), in der man Werte speichern kann. Wo die Session gespeichert wird ist davon unabhängig; der session storage kann ein Cookie sein, so dass die Session auf den Server gar nicht existiert sondern nur auf dem Client. Es kann eine Datei sein, oder es kann die Datenbank sein. Üblich ist bei PHP eine Session-Datei, es geht jedoch auch bei PHP auch anders.

          Oder die Session-Daten sind, wie z.B. bei PHP üblich, in der Datenbank oder in Session-Dateien gespeichert, dann kann die Session auch nicht manipuliert werden.

          Letzteres war von vornherein mein Verständnis. Wie sollte man das sinnvoll anders machen?

          Bei Rails wird die Session per Default im Cookie gespeichert (und signiert sowie verschlüsselt, bevor sie an den User gesendet wird); das geht auch mit PHP, siehe mein Link von oben.

          Die DB dafür bemühen hieße ja, dass ich Dinge neu implementiere, die mir PHP von selbst schon anbietet. Das vermeide ich gerne.

          Nein, das heisst nur, dass du ein paar Methoden implementieren musst ;)

          LG,
          CK

      3. Toll! Nun lass doch deiner wunderschönen Theorie endlich Taten folgen und setz das am Projekt Wiki in die Praxis um, es wäre ein erheblicher Qualitätsgewinn in Sachen Glaubwürdigkeit.

        1. Tach,

          Toll! Nun lass doch deiner wunderschönen Theorie endlich Taten folgen und setz das am Projekt Wiki in die Praxis um, es wäre ein erheblicher Qualitätsgewinn in Sachen Glaubwürdigkeit.

          den Bugtracker von Mediawiki findest du hier, du kannst dir meiner Unterstützung sicher sein, sie von den von @Christian Kruse genannten Prinzipen zu überzeugen.

          mfg
          Woodfighter

    2. Hi Felix,

      wenn Du PHP nutzt, dann solltest Du das Generieren einer Session-ID den Automatismen von PHP überlassen.

      Das mache ich ja. Ich nutze nur kein session_regenerate, weil ich dadurch viel mehr Türen für's hijacking öffne, als tatsächlich geschlossen werden. Vorallem, weil alte Sessions nicht richtig gelöscht werden, öffnet sich mit jeder neuen Session eine neue Hintertür. So war es jedenfalls, als ich vor 3 Jahren den Prototyp dieser Klasse schrieb.

      userid | Pass (gehasht) 1 | 4a4350df2403b94a13304ee88b861041

      Für den Hash verwendest Du password_hash()? Sieht nicht so aus, solltest Du aber.

      Das werde ich mir ansehen. Hashen tue ich derzeit so:

      md5 (irgendwas.USEREINGABE.nochirgendwas)
      

      Was bitte ist ein "normales" Cookie?

      Ein Cookie halt :) Das eine heisst PHPSESSION, das andere Cookie. Ich weiss, es sind beides letztenendes Cookies, aber der verständlichkeit halber nenne ich es „normale Cookies“.

      Es empfiehlt sich sehr, dass Da nur und ausschließlich die Session-ID steht.

      ? Da steht doch nur der Session-Name.

      Alles andere speicherst Du in der Session. Wenn der User keine Cookies zulässt, dann brauchst Du einen URL-Parameter mit der Session-ID

      Genau das will ich ja nicht. Cookies sind zwingend.

      // userid mit irgendwas multipliziert
      $_SESSION['USER'] = '541 4a4350df2403b94a13304ee88b861041';
      $_COOKIE['USER']  = '541 4a4350df2403b94a13304ee88b861041';
      

      Das bedeutet, dass die Passwort-Informationen im Cookie des Users auf dessen Computer abgelegt werden. Das willst Du nicht, da bin ich mir sicher, denn Du weißt, dass die Cookie-Daten unverschlüsselt durchs Netz gehen, wenn Du keine https-Verbindung hast.

      Es ist doch gehashed, sowohl die Userid ist verfremdet, als auch das Passwort, was will ein Hacker mit den Daten anfangen? Ich könnte ja auch, bevor ich die Daten im Cookie speichere, das ohnehin schon gehashte Passwort noch mal mit md5() hashen, aber viel ändern würde sich ja nicht. Und mit dem gehashten Passwort kann sich keiner einloggen. Ich weiss, es gibt Regenbogentabellen, aber ich salze die Daten ja noch, bevor ich sie speichere. Wie könnte ich denn sonst einen Automatischen Login machen? Irgendwo muss ich die Daten ja hinterlassen.

      Ein Session-Hijacking unterbindest Du sinnvollerweise dadurch, dass Du bei jedem Request eine neue Session-ID generieren lässt.

      Diese Funktion hatte ich vor Jahren genutzt, und festgestellt, das ich mit jedem neuen Seitenaufruf eine neue Session generiert habe, ohne das die alte Session gelöscht wurde. Dadurch schuf ich mit jedem Seitenaufruf eine Hintertür nach der anderen. Das Session Hijacking wird dadurch leider nur erleichtert.

      Eventuell ist ein Cookie-Zwang für diverse Bereiche Deiner Seite Grundvoraussetzung.

      Ohne Cookie, ohne mich :)

      Entweder der User kommt mit einer gültigen Session-ID an, oder nicht. Sollten seine Session-Daten in Ordnung sein, ist er auch eingeloggt. Das kannst Du damit überprüfen, indem Du in den Session-Daten (aber nicht im Cookie und schon gar nicht in irgendeinem URL-Parameter!!) das Passwort des Users (gerne als Hash aus der DB) ablegst und bei einem Request gegen den Hash aus der DB abgleichst.

      Deswegen der Cookie-Zwang. Wenn die Session offen ist, kann ich einfach Session mit Cookie vergleichen, statt die Datenbank zu bemühen.

      Warum? Du hast bei manchen Providern den Fall, dass Leute bei einem Seitenaufruf die einzelnen Dateien mit unterschiedlichen IP-Adressen aufrufen, da der Provider die Requests über einen Pool an IP-Adressen leitet. Das würde die User-Experience im Zweifelsfall empfindlich behindern!

      Das stimmt natürlich, aber der Anteil dieser Nutzer dürfte wohl sehr gering sein. Dafür wäre aber die Anwendung ein ticken sicherer. Dann wäre auch egal, ob jemand die Session oder das Cookie hackt, wenn die IP nicht bekannt ist, muss sich der User regulär einloggen. Wäre nicht mal Security through obscurity ;)

      Um Deine Sicherheit zu erhöhen, kannst Du beim Einloggen mit einer Zwei-Faktor-Authentifizierung arbeiten: Nach dem Login mit Usernamen und Passwort verschickst Du eine Mail mit einem Zufallswert, der ergänzend eingegeben werden muss, der nur etwa fünf Minuten lang gültig ist und nach der ersten Verwendung sofort ungültig wird

      Ich will kein Online-Banking betreiben :)

      Ich brauche einfach nur ein Easy-to-Use-Loginscript, dass ich schnell und einfach implementieren kann, das aber halbwegs sicher ist. Damit plane ich z.B. so eine Seite, wo User sich einloggen und eigene Playlists erstellen können. Also nichts Weltbewegendes.

      Bis bald

      --
      Hosen sind Blau
      1. Hallo Malcolm,

        Es ist doch gehashed, sowohl die Userid ist verfremdet, als auch das Passwort, was will ein Hacker mit den Daten anfangen?

        MD5 weisst signifikante Schwachstellen in Form von Kollisionen auf. Man braucht das Passwort gar nicht, der MD5-Hash lässt sich „errechnen.“

        Allgemein ist es nicht ratsam, den Passwort-Hash aus der Hand zu geben, denn selbst wenn gerade der Algorithmus noch als sicher gilt - was ist in zwei Jahren? Es hat seinen Grund, dass das Passwort das Geheimnis in der Gleichung ist.

        Ich brauche einfach nur ein Easy-to-Use-Loginscript, dass ich schnell und einfach implementieren kann, das aber halbwegs sicher ist.

        Nutze die Hashing-Funktionen, die PHP zur Verfügung stellt. Gib die Passwort-Daten nicht auf den User-Rechner, auch nicht gehasht. Nutze HTTPS (z.B. mit Let's Encrypt) und enforce das auch. Damit solltest du auf der sicheren Seite sein.

        LG,
        CK

        1. Hi Christian,

          Gib die Passwort-Daten nicht auf den User-Rechner, auch nicht gehasht.

          Wenn ich aber nur die UserID speichere, wie soll ich den User dann richtig verifizieren? Die UserID wäre doch leicht zu erraten.

          Wie wäre folgendes Konstrukt?

          Passwort in der Datenbank mit password_hash() speichern. Beim setzen des Cookies das gehashte Passwort mit md5 nochmal verunstalten und diesen Hash im Cookie speichern?

          Nutze HTTPS (z.B. mit Let's Encrypt) und enforce das auch. Damit solltest du auf der sicheren Seite sein.

          Ja, wird langsam Zeit für https, hab ich noch nie ausprobiert.

          Bis bald

          --
          Hosen sind Blau
          1. Hallo Malcolm,

            Gib die Passwort-Daten nicht auf den User-Rechner, auch nicht gehasht.

            Wenn ich aber nur die UserID speichere, wie soll ich den User dann richtig verifizieren? Die UserID wäre doch leicht zu erraten.

            Klar, aber wie willst du die User-ID in die Session kriegen? Bei PHP verlässt die Session doch den Server nicht, nur die Session-ID.

            Passwort in der Datenbank mit password_hash() speichern. Beim setzen des Cookies das gehashte Passwort mit md5 nochmal verunstalten und diesen Hash im Cookie speichern?

            Don't. Es gibt keinen Grund das zu tun, und du öffnest dir potentiell damit ein Loch.

            LG,
            CK

            1. Hi Christian,

              Klar, aber wie willst du die User-ID in die Session kriegen? Bei PHP verlässt die Session doch den Server nicht, nur die Session-ID.

              Stimmt, ich hatte mich Mental auf die Cookie-Variante eingeschossen. Ich werd's mal auf Session umstellen und damit nochmal rumprobieren. Im Grunde kann ich ja sogar bei jedem Aufruf die Datenbank bemühen, um die Daten zu vergleichen.

              Bis bald

              --
              Hosen sind Blau
              1. Hallo Malcolm,

                Klar, aber wie willst du die User-ID in die Session kriegen? Bei PHP verlässt die Session doch den Server nicht, nur die Session-ID.

                Stimmt, ich hatte mich Mental auf die Cookie-Variante eingeschossen.

                Wenn man die User-ID in einem Session-Cookie speichert muss natürlich der Manipulation vorgebeugt werden. Das wird, wie ich bereits versucht habe zu erklären, in der Praxis über eine kryptografische Signatur gemacht. Der Wert des Cookies wird serialisiert, dann signiert und zuletzt zum Browser geschickt, so dass eine Änderung des Wertes eine ungültige Signatur zur Folge hat. Beim Einlesen des Cookies wiederum wird die Signatur überprüft und nur wenn sie gültig ist, wird der Cookie akzeptiert.

                LG,
                CK