Sebastian Goertz: max. Sicherheit beim Arbeiten von Login mit Sessions (PHP)

Hallo,

ich mache mir gerade Gedanken um bestmögliche Sicherheit bei der Arbeit mit Sessions beim Login. Nun Interessieren mich andere Meinungen dazu...

Ausgangssituation:
Das Passwort wird als MD5-Hash in der Datenbank gespeichert.
Login erfolgt wie gewohnt durch Eingabe von Benutzername / Passwort
Bei der ersten Prüfung werden Session-Variablen angelegt, auch Benutzername und md5(Passwort).
Bei jedem weiteren Aufruf einer Seite wird nun erneut Benutzername und Passwort überprüft.

Frage:
Ist der letzte Schritt unnötig? Ist die Arbeit mit Sessions ausreichend sicher, dass es genügen würde, nach der ersten Prüfung ein $_SESSION['Login'] = TRUE/FALSE zu speichern und dies dann bei jedem weiteren Aufruf zu überprüfen? Sollte man dann dabei zur optimalen Sicherheit noch etwas beachten?

Vielen Dank,
Sebastian

  1. Hi Sebastian.

    ich mache mir gerade Gedanken um bestmögliche Sicherheit bei der Arbeit mit Sessions beim Login.

    Wovor willst Du Sicherheit? (Ist ne echte Frage.)

    Das Passwort wird als MD5-Hash in der Datenbank gespeichert.

    MD5 ist unsicher. Schau Dir mal die SHA-2-Hashes an. Ansonsten suche nach dem Stichwort "Salt" im Archiv.

    Login erfolgt wie gewohnt durch Eingabe von Benutzername / Passwort

    Ok.

    Bei der ersten Prüfung werden Session-Variablen angelegt, auch Benutzername und md5(Passwort).

    Benutzername ok, wenn Du ihn im Skript brauchst. Für das Speichern des Passwort-Hashes in der Session gibt es keinen guten Grund.

    Bei jedem weiteren Aufruf einer Seite wird nun erneut Benutzername und Passwort überprüft.

    Nein! Dazu müsste der Nutzer jedes Mal wieder die Daten senden. Das will er nicht und soll er nicht! Er identifiziert sich nur(!) durch Senden der Session-ID.

    Frage:
    Ist der letzte Schritt unnötig?

    Mehr noch: er ist problematisch. Er erhöht die Sicherheit nicht, und schafft anderesherum evtl. Dritten zusätzliche Möglichkeiten, die Zugangsdaten zu entführen (was u.U. sehr viel schlechter wäre, als "nur" eine Session zu entführen, siehe 3.: unten).

    Ist die Arbeit mit Sessions ausreichend sicher, dass es genügen würde, nach der ersten Prüfung ein $_SESSION['Login'] = TRUE/FALSE zu speichern und dies dann bei jedem weiteren Aufruf zu überprüfen?

    Das hängt natürlich davon ab, was man für 'ausreichend' erachtet. Aber: Ja. Die Session-ID ist lang genug, um nicht (im probabilistischen Sinne) von Dritten erraten werden zu können. Sie bietet daher alles, was ein (gutes) Passwort auch bietet.

    Sollte man dann dabei zur optimalen Sicherheit noch etwas beachten?

    Ein paar Anregungen, wenn Du denn sicherheitsfanatisch bist:

    1.: Sehr ratsam ist ein automatischer Logout nach einer angemessenen Zeit der Inaktivität (so was wie 10-15 Minuten vielleicht). Denn ein Szenario, in dem eine Session leicht entführt werden kann, ist, dass jemand vergisst, sich auszuloggen und jemand anderes etwa Zugang zu dem Computer hat, bevor die Session abgelaufen ist. Das kannst Du nicht restlos verhindern, und es ist auch nicht in erster Linie Deine Verantwortung, Fehler Deiner Nutzer zu verhindern, aber Du solltest ihnen auf diese Weise so weit wie möglich entgegen kommen.

    2.: Wenn Dir danach ist, kannst Du aktiv mit einem Hinweis anregen, dass Deine Nutzer vernünftige Passwörter verwenden und nicht etwa "qwertz" oder dergleichen. (Ich persönlich mag es allerdings ganz gerne, wenn es bei (höchstens) diesem Anregen bleibt und die Anwendung nicht meint, mir irgendein Passwort technisch verbieten zu müssen. Aber auch das solls geben.) Etwas mehr Infos darüber, wann Passwörter vernünftig sind, liefert google sicher gern..

    3.: Überlege Dir, wozu man mit einem normalen Login Zugang haben sollte und wozu nicht. Wenn zum Beispiel der Nutzer in irgendwelchen Nutzereinstellungen die Möglichkeit hat, sein Passwort zu ändern, dann sollte das nur mit erneuter Eingabe des alten Passwortes möglich sein. Auf diese Weise kann jemand, der eine Session entführt, zwar vielleicht allerlei Schabernack treiben, aber nicht die Zugangsdaten ändern und damit deren eigentlichen Besitzer aussperren.

    4.: Du solltest auf mehrfach gescheiterte Login-Versuche reagieren. Ein einzelner gescheiterter Versuch kann vom Nutzer selber leicht durch Vertipper kommen, bei mehreren aber sollte reagiert werden. Möglichkeiten:

    • Es dem Nutzer beim nächsten Login mitteilen: "Achtung, es gab weit Ihrem letzten Login 7 gescheiterte Login-Versuche. Möglicherweise wurde versucht, ihr Konto zu hacken, und sie sollten evtl. Ihr Passwort ändern."

    • Das Konto für eine gewisse Zeit sperren und keinen Login zulassen.

    • Falls Du seine Email-Adresse gespeichert hast, obige Nachricht per Email an ihn schicken, und ggf. obige Sperre nicht auf eine gewisse Zeit beschränken, sondern ihm in der Email einen Link liefern, mit dem er die Sperre wieder aufheben kann.

    Viele Grüße,
    der Bademeister

    1. MD5 ist unsicher. Schau Dir mal die [link:http://en.wikipedia.org

      Also das kann ich so nicht stehen lassen. MD5 ist bestimmt für viele Seiten ausreichend. Kein Hacker macht sich die Arbeit bzw bemüht sein Rechner um die Datenbank von www.meinehomepage.de zu knacken und die Benutzerdaten von admin/root zu bekommen.
      Das es eine sichere Methode gibt da gebe ich dir Recht. Aber eine Möglichkeit wäre auch auf das md5 Passwort noch einmal md5 anzuwenden so in etwa:

      <?php
      $passmd5 = md5(md5("passwd"));
      ?>

      Damit bräuchte mann schon doppelt so lang diese Passwort zu kacken.

      Eine andere Möglichkeit wäre es den Benutzer ein Passwort eingeben zu lassen was min. 12(vllt auch mehr) zeichen lang ist, zahlen und Großbuchstaben enthält. Der daraus generierte Hash-Wert ist 100x schwerer zu kacken.

      Also ich hoffe Ihr versteht mich richtig man muss nicht immer mit Kanonen auf Spatzen schießen ;)

      lg Lil

      1. Hi!

        MD5 ist unsicher. Schau Dir mal die http://en.wikipedia.org
        Also das kann ich so nicht stehen lassen. MD5 ist bestimmt für viele Seiten ausreichend.

        Ja, es gibt Kollisionen, und die muss man erstmal finden. Aber gibt es die nicht theoretisch für jedes Hash-System, nur sind sie bei den besseren noch nicht wirtschaftlich berechenbar?

        Kein Hacker macht sich die Arbeit bzw bemüht sein Rechner um die Datenbank von www.meinehomepage.de zu knacken und die Benutzerdaten von admin/root zu bekommen.

        Warum nicht? Wenn man damit Zugang zum Server an sich bekommt und ihn für andere Dinge verwenden kann, ist das doch ein lohnendes Ziel.

        Das es eine sichere Methode gibt da gebe ich dir Recht. Aber eine Möglichkeit wäre auch auf das md5 Passwort noch einmal md5 anzuwenden so in etwa:

        Lieber salzen.

        Damit bräuchte mann schon doppelt so lang diese Passwort zu kacken.

        Es ist auch nicht viel aufwendiger, neben der Rainbow-Tabelle mit einfachen MD5-Hashes noch eine mit zweifachen anzulegen. Die Salz-Methode ist wesentlich unwirtschaftlicher zu berechnen.

        Lo!

        1. Lieber salzen.

          Es ist auch nicht viel aufwendiger, neben der Rainbow-Tabelle mit einfachen MD5-Hashes noch eine mit zweifachen anzulegen. Die Salz-Methode ist wesentlich unwirtschaftlicher zu berechnen.

          Lo!

          Mit einem "schwachen Passwort" bringt dir die salt Methode auch nicht viel da die verwendeten Salts dem Angreifer bekannt sind. Und schon kann man wieder mit Brute Force und Wörterbuch Angriffen fortfahren.

          Ich würde immer noch dazu raten die Benutzer der Seite ein passwort eingeben zu lassen was mind. 12 Zeichen lang ist, Groß- und Kleinschreibung enthält vllt noch Zahlen das "gesalzen", wie es mein werter Kollege vorschlägt, und schon hat man ein "sicheres" Passwort wobei sicher relativ ist ;)

          lil!

          1. Hi!

            Lieber salzen.
            Es ist auch nicht viel aufwendiger, neben der Rainbow-Tabelle mit einfachen MD5-Hashes noch eine mit zweifachen anzulegen. Die Salz-Methode ist wesentlich unwirtschaftlicher zu berechnen.

            Mit einem "schwachen Passwort" bringt dir die salt Methode auch nicht viel da die verwendeten Salts dem Angreifer bekannt sind. Und schon kann man wieder mit Brute Force und Wörterbuch Angriffen fortfahren.

            Brute Force kann man immer probieren, ob gesalzen oder nicht. Aber diesen Aufwand will man sich ja mit dem Einsatz einer Rainbow-Tabelle sparen, beziehungsweise man will dem Angreifer den Aufwand des Brute Force für jeden Eintrag neu auferlegen, in der Hoffnung, dass seine Rechenleistung zu schwach ist. Ob der Aufwand nun einfach oder doppelt so groß ist, weil man einfach oder doppelt hasht, spielt dann keine große Geige.

            Lo!

            1. Moin!

              OK und wie wäre es wenn man z.B. ein Bestätigungscode eingeben muss der per Image realisiert wird?
              Ich kenn noch kein System was so ein zufällig gewählten Code erkennen kann.
              Wobei ich diese Methode als nervig empfinde.

              lg lil

              1. Hi!

                OK und wie wäre es wenn man z.B. ein Bestätigungscode eingeben muss der per Image realisiert wird?
                Ich kenn noch kein System was so ein zufällig gewählten Code erkennen kann.

                Du solltest dein Wissen updaten. Solche Systeme gibt es schon lange, sowohl automatische als auch welche, die die Arbeit an andere Menschen weiterdelegieren und sie unter einem anderem Vorwand das Rätsel lösen lassen.

                Wobei ich diese Methode als nervig empfinde.

                Letzlich bleibt nur das übrig.

                Lo!

                1. Du solltest dein Wissen updaten. Solche Systeme gibt es schon lange, sowohl automatische als auch welche, die die Arbeit an andere Menschen weiterdelegieren und sie unter einem anderem Vorwand das Rätsel lösen lassen.

                  Das mag sein das mein Wissensstand nicht vom 1..3.2011 ist aber ich befürchte das du dass auch nicht von dir behaupten kannst soviel dazu.

                  Und da du zu wissen scheinst wo man das nachlesen kann, das so ein System existiert, bitte ich dich mir diese Quelle zu nennen, danke.

                  Und was bringt es bitte, wenn diese Aufgabe dann doch ein Mensch macht? Jedes mal wenn ein Login fehlschlägt wird ein neues Image generiert > System versteht den Inhalt nicht [weil verschoben, unterschiedliche größen ect...] stopt und wartet bis ich ihm sage das es New York heißt? Oder habe ich dich da etwa falsch verstanden?

                  lg

                  1. Hi!

                    Du solltest dein Wissen updaten. Solche Systeme gibt es schon lange, sowohl automatische als auch welche, die die Arbeit an andere Menschen weiterdelegieren und sie unter einem anderem Vorwand das Rätsel lösen lassen.
                    Und da du zu wissen scheinst wo man das nachlesen kann, das so ein System existiert, bitte ich dich mir diese Quelle zu nennen, danke.

                    Ich merke mir auch nicht immer, wo ich was gelesen habe. Aber vermutlich kam es mal in einer Heise-News-Meldung. Du könntest mit deinen Recherchen in der Wikipedia zu Captcha starten.

                    Und was bringt es bitte, wenn diese Aufgabe dann doch ein Mensch macht?

                    Dass sie gelöst ist. Das ist das Ziel der Spammer. Bot versucht sich anzumelden und bekommt ein Captcha, gibt dieses an aktuell Besuchende einer anderen Website mit interessierendem Inhalt zum Lösen, mit der Aussicht an die verdeckten Inhalte zu kommen.

                    Jedes mal wenn ein Login fehlschlägt wird ein neues Image generiert

                    Wenn der erste Versuch nicht klappt, machen wir eben einen nächsten. Wird schon irgendwann passen.

                    Lo!

                  2. Und da du zu wissen scheinst wo man das nachlesen kann, das so ein System existiert, bitte ich dich mir diese Quelle zu nennen, danke.

                    Manchmal genügt es auch statt Quelle, dass mehrere Leute davon gelesen haben. Ich auch.
                    Wie beim Phishing wird anderen Leuten auf beliebigen Seiten eine scheinbare Prüfung vorgehalten. Deren Lösung ist deine Lösung und schon ist das Captcha geknackt.

                    Bots, die ein Captcha lösen können, soll es auch schon geben. Und mal im ernst - warum auch nicht? Wäre doch auch langweilig, wenn man sich nicht wieder neue Sicherheitsmechanismen ausdenken müsste ;)

                    Eben mal schnell über Google gefunden:
                    Hotmail-Captcha per Bot in sechs Sekunden ausgehebelt

              2. Hi.

                OK und wie wäre es wenn man z.B. ein Bestätigungscode eingeben muss der per Image realisiert wird?

                Das ist ne ganz andere Baustelle. Die Dinger sind dazu da, Menschen von Maschinen zu unterscheiden. Sie helfen aber nicht, gute Menschen von boesen zu unterscheiden.

                Viele Gruesse,
                der Bademeister

      2. Hi.

        MD5 ist unsicher. Schau Dir mal die [Urbild-Attacken](http://en.wikipedia.org

        Also das kann ich so nicht stehen lassen. MD5 ist bestimmt für viele Seiten ausreichend.

        Ich habe selber eine private Website am laufen, auf der Passwoerter von Usern ohne Salt als MD5 gespeichert sind. Und ich sehe es auch nicht als besonders dringlich an, das mal zu aendern. Dennoch ist der Status Quo, dass es einigermassen effiziente [link:http://de.wikipedia.org/wiki/Preimage-Angriff) fuer MD5 gibt. Und damit ist es nicht sicher.

        Es mag fuer gewisse Einsatzzwecke immer noch "ausreichend" sein, ja, aber: "ausreichend" ist so ein bisschen eine gefaehrliche Haltug in der Kryptographie. Wenn man jetzt ein Login-System neu programmiert, gibt es keinen guten Grund, MD5 statt etwa einen geeigneten SHA-2 zu benutzen. Das wollte ich nur sagen.

        Kein Hacker macht sich die Arbeit bzw bemüht sein Rechner um die Datenbank von www.meinehomepage.de zu knacken und die Benutzerdaten von admin/root zu bekommen.

        Kann sein. Aber unterschaetze auch nicht, zu welchem Bloedsinn Hobby-Hacker faehig sind, die aus Spass an der Freude ein paar Fingeruebungen machen wollen.

        Das es eine sichere Methode gibt da gebe ich dir Recht. Aber eine Möglichkeit wäre auch auf das md5 Passwort noch einmal md5 anzuwenden so in etwa:

        <?php
        $passmd5 = md5(md5("passwd"));
        ?>
        Damit bräuchte mann schon doppelt so lang diese Passwort zu kacken.

        Das ist ein gefaehrlicher Irrtum.

        Eine andere Möglichkeit wäre es den Benutzer ein Passwort eingeben zu lassen was min. 12(vllt auch mehr) zeichen lang ist, zahlen und Großbuchstaben enthält. Der daraus generierte Hash-Wert ist 100x schwerer zu kacken.

        Das wurde ja schon angesprochen. Aber: Das macht Rainbow-Attacken schwierig. Die Unsicherheit von MD5 liegt nicht an moeglichen Rainbow-Attacken (das traefe ja auf alle Hash-Funktionen gleichermassen zu).

        Also ich hoffe Ihr versteht mich richtig man muss nicht immer mit Kanonen auf Spatzen schießen ;)

        Wenn die Kanonenkugeln gratis sind, spricht aber auch nichts dagegen.

        Viele Gruesse,
        der Bademeister

    2. Hello,

      MD5 ist unsicher. Schau Dir mal die SHA-2-Hashes an. Ansonsten suche nach dem Stichwort "Salt" im Archiv.

      MD5 ist hier nicht unsicherer, als die Sicherheit der Datenbank dies ermöglicht. Ob der Datenbankadministrator das MD5-gewandelte Passwort mittels Rainbowtables ermitteln kann, ist so ziemlich egal, denn er könnte ohnehin jede Manipulation an den Daten durchführen.

      Bei der ganzen Frage muss man wohl erstmal unterscheiden zwischen sicheren und nrmalen (unsicheren) Netzen. In normalen Netzen ist die Übermittlung eines Schlüssels, bzw. die gemeinsame Übermittlung von zwei Schlüsselteilen immer unsicher. Eine [Session-ID] ist also genauso unsicher, wie ein [Username + (gutes) Passwort].

      Hier spielt die Erratbarkeit wohl eher eine untergeordnete Rolle. Die Abfischbarkeit stellt die größere Gefahr dar.

      Bei jedem weiteren Aufruf einer Seite wird nun erneut Benutzername und Passwort überprüft.

      Nein! Dazu müsste der Nutzer jedes Mal wieder die Daten senden. Das will er nicht und soll er nicht! Er identifiziert sich nur(!) durch Senden der Session-ID.

      Da stimme ich Dir zu, siehe Vorstehendes.

      Allerdings sollte bei jedem Request die Gültigkeit des Accounts überprüft werden und es sollten die aktuellen Rechte geladen werden, wenn man diese nicht sogar bei Abarbeitung des Requests für jede benutzte Funktion einzeln prüft.

      Das wäre dann die Abstufung

      • Sessionbezogene Legitimation
      • Requestbezogene Legitimation
      • Funktionsbezogene Legitimation

      Um die Sessionsicherheit zu erhöhen, kann man mit jedem Request eine neue Session-ID zuweisen
      z.B. bei PHP: http://de3.php.net/manual/en/function.session-regenerate-id.php

      Um die Sicherheit in realen Netzen herzustellen, ist eine Point-to-Point-Verschlüsslung, z.B. mit SSL/TSL notwendig.

      Liebe Grüße aus dem schönen Oberharz

      Tom vom Berg

      --
       ☻_
      /▌
      / \ Nur selber lernen macht schlau
      http://bergpost.annerschbarrich.de
      1. Hi,

        Allerdings sollte bei jedem Request die Gültigkeit des Accounts überprüft werden und es sollten die aktuellen Rechte geladen werden, wenn man diese nicht sogar bei Abarbeitung des Requests für jede benutzte Funktion einzeln prüft.

        Da stellt sich für mich die Frage: Wie sicher sind denn nun eigentlich die Variablen, die ich in einer Session speichere. Sind diese (mit lohnendem Aufwand) manipulierbar?
        Angenommen ich lade beim Login diverse Daten als Variablen in die Session, darunter neben Benutzername und login=TRUE auch diverse Berechtigungen aus der Datenbank. Du empfielst dass ich diese Daten bei jedem Seitenaufruf erneut abfragen sollte. Bedeutet das, dass die Session-Variablen manipulierbar und somit alles andere als "sicher" sind?

        Um die Sessionsicherheit zu erhöhen, kann man mit jedem Request eine neue Session-ID zuweisen

        Geht aber stark zu lasten der Benutzbarkeit. Bringt ja bereits dann Probleme, wenn ein User zwei Tabs parallel laufen lassen will. Uns sei es nur, um kurz nebenbei etwas nachzugucken. Soll es das wert sein? Oder kennt jemand einen Trick beides zu ermöglichen?

        Viele Grüße,
        Sebastian.

        1. Hi!

          Allerdings sollte bei jedem Request die Gültigkeit des Accounts überprüft werden und es sollten die aktuellen Rechte geladen werden, wenn man diese nicht sogar bei Abarbeitung des Requests für jede benutzte Funktion einzeln prüft.
          Da stellt sich für mich die Frage: Wie sicher sind denn nun eigentlich die Variablen, die ich in einer Session speichere. Sind diese (mit lohnendem Aufwand) manipulierbar?

          Es geht nicht um die Manipulationsfähigkeit, sondern darum, dass du dem Benutzer im laufenden Betrieb die Berechtigungen ändern kannst. Ansonsten wird er erst bei neuer Abfrage wegen neuer Session neue Berechtigungen erhalten. Und ihm die Session-Datei zu löschen ist nicht so einfach, wenn du deren ID nicht irgendwo dem User zugeordnet gespeichet hast.

          Bedeutet das, dass die Session-Variablen manipulierbar und somit alles andere als "sicher" sind?

          Mir ist keine Möglichkeit der Manipulation durch speziell formatierte Requests bekannt. Somit hängt alles von deiner Programmierung ab.

          Um die Sessionsicherheit zu erhöhen, kann man mit jedem Request eine neue Session-ID zuweisen
          Geht aber stark zu lasten der Benutzbarkeit. Bringt ja bereits dann Probleme, wenn ein User zwei Tabs parallel laufen lassen will.

          Das ist der Kompromiss zwischen Sicherheit und Komfort. Komfortabel wäre es auch, wenn Anwender nur Namen und kein Passwort eingeben müssten, aber die Sicherheit ist dann verständlicherweise bei Null.

          Lo!

        2. Hello,

          Um die Sessionsicherheit zu erhöhen, kann man mit jedem Request eine neue Session-ID zuweisen

          Geht aber stark zu lasten der Benutzbarkeit. Bringt ja bereits dann Probleme, wenn ein User zwei Tabs parallel laufen lassen will. Uns sei es nur, um kurz nebenbei etwas nachzugucken. Soll es das wert sein? Oder kennt jemand einen Trick beides zu ermöglichen?

          Wenn man mit Cookies arbeitet, bereitet das keine Probleme. Denn die neue Session-ID gilt ja nicht für das Fenster/&den Tab, sondern für das Requestziel. Wenn der Cookie also für die Domain gesetzt wird, würde auch der Request aus dem  anderen Tab den jeweils aktuellen Cookie verwenden.

          Schlecht ist das nur bei Verwendung von transparenter Session-ID, sie ich sowieso nicht empfehlen würde. Dann sollte man die Session schon besser auf HTTP Authentication aufbauen.

          Liebe Grüße aus dem schönen Oberharz

          Tom vom Berg

          --
           ☻_
          /▌
          / \ Nur selber lernen macht schlau
          http://bergpost.annerschbarrich.de
      2. Hi Tom.

        MD5 ist hier nicht unsicherer, als die Sicherheit der Datenbank dies ermöglicht.

        Ich habe diesen Satz jetzt ein paar Mal gelesen und verstehe ihn immer weniger :-)

        Natuerlich ist es ratsam, Angreifern keinen Zugriff zur Datenbank zu gewaehrleisten. Aber wenn das mal schiefgeht, ist es eben auch ratsam, Passworter vernuenftig gespeichert zu haben.

        Und MD5 ist nicht wegen Rainbow-Attacken unsicher - die kann man nun mal fuer jede Hash-Funktion gleichermassen durchfuehren, sondern wegen der Existenz von (einigermassen) effizienten Urbild-Attacken.

        Ob der Datenbankadministrator das MD5-gewandelte Passwort mittels Rainbowtables ermitteln kann, ist so ziemlich egal, denn er könnte ohnehin jede Manipulation an den Daten durchführen.

        Das ist keineswegs egal (selbt wenn jeder, der Zugang zur Datenbank hat, auch Schreibenden Zugang hat) - ob die Datenbank Rueckschluesse auf das vom User gewaehlte Passwort zulaesst oder nicht, ist eine ziemlich erhebliche Datenschutzfrage. Nicht zuletzt benutzen viele User dasselbe Passwort auch anderswo. (Das ist dann vielleicht deren eigener Fehler, ja, aber das aendert nichts. Leute muessen u.U. auch vor sich selbst geschuetzt werden.)

        Bei der ganzen Frage muss man wohl erstmal unterscheiden zwischen sicheren und nrmalen (unsicheren) Netzen. In normalen Netzen ist die Übermittlung eines Schlüssels, bzw. die gemeinsame Übermittlung von zwei Schlüsselteilen immer unsicher.

        Redest Du jetzt vom Schluessel fuer ein gesichertes Netz oder von Usernamen und Passwort?

        Eine [Session-ID] ist also genauso unsicher, wie ein [Username + (gutes) Passwort].

        Eine Session-ID enthaelt aber nicht so wichtige Information wie das Passwort.

        Hier spielt die Erratbarkeit wohl eher eine untergeordnete Rolle. Die Abfischbarkeit stellt die größere Gefahr dar.

        ACK.

        Um die Sessionsicherheit zu erhöhen, kann man mit jedem Request eine neue Session-ID zuweisen
        z.B. bei PHP: http://de3.php.net/manual/en/function.session-regenerate-id.php

        ACK.

        Um die Sicherheit in realen Netzen herzustellen, ist eine Point-to-Point-Verschlüsslung, z.B. mit SSL/TSL notwendig.

        ACK.

        Viele Gruesse,
        der Bademeister

        1. Hello,

          Und MD5 ist nicht wegen Rainbow-Attacken unsicher - die kann man nun mal fuer jede Hash-Funktion gleichermassen durchfuehren, sondern wegen der Existenz von (einigermassen) effizienten Urbild-Attacken.

          Und das verstehe ich nun wieder nicht. Dazu bin ich wohl zu verhasht ;-P

          Kannst Du mir erklären, wie so eine Urbild-Attacke in der Praxis stattfindet? Bildet ein (erfolgreiches) Ergebnis nicht einen Eintrag in eiener Rainbow-Tabelle?

          So hatte ich as bisher immer verstanden.

          Bei der ganzen Frage muss man wohl erstmal unterscheiden zwischen sicheren und normalen (unsicheren) Netzen. In normalen Netzen ist die Übermittlung eines Schlüssels, bzw. die gemeinsame Übermittlung von zwei Schlüsselteilen immer unsicher.

          Redest Du jetzt vom Schluessel fuer ein gesichertes Netz oder von Usernamen und Passwort?

          Username und Passwort ergeben zusammen einen Schlüssel. Sowas nennt man auch Kombinationsschlüssel.

          Eine [Session-ID] ist also genauso unsicher, wie ein [Username + (gutes) Passwort].

          Eine Session-ID enthaelt aber nicht so wichtige Information wie das Passwort.

          Das kommt darauf an, wie lange Session-ID und/oder Passwort gültig sind.

          Liebe Grüße aus dem schönen Oberharz

          Tom vom Berg

          --
           ☻_
          /▌
          / \ Nur selber lernen macht schlau
          http://bergpost.annerschbarrich.de
          1. Hi.

            Und MD5 ist nicht wegen Rainbow-Attacken unsicher - die kann man nun mal fuer jede Hash-Funktion gleichermassen durchfuehren, sondern wegen der Existenz von (einigermassen) effizienten Urbild-Attacken.

            Und das verstehe ich nun wieder nicht. Dazu bin ich wohl zu verhasht ;-P

            Eine Rainbow-Attacke besteht, vereinfacht, daraus, flaechendeckend von moeglichen Passwoertern die Hashes zu berechnen und das Ganze auf effiziente Weise zu speichern, um dann einen konkreten Hash darin zu suchen.

            Das geht fuer *jede* Hash-Funktion - es steckt keinerlei Logik dahiner, die von der konkreten Funktion abhaengt.

            Eine Urbild-Attacke ist ein konkreter Algorithmus, der zu einem konkreten Hash ein Urbild (also ein dazu passendes Passwort) ermittelt. Im Idealfall (aus Angreifer-Sicht) also eine mathematische Umkehrfunktion des Hashs. Bei einer guten (idealen) Hashfunktion gibt es sowas nicht, bei MD5 schon. Diese bekannten Angriffe fuer MD5 sind nun keine deterministischen Funktionen, die eben mal so aus dem Handgelenk ein Urbild ausrechnen, sondern verwenden intern immer noch einige (Sub-)Lookups, aber sie sind (je nach konkretem Hash) erheblich effizienter als Rainbow-Tabellen.

            Kannst Du mir erklären, wie so eine Urbild-Attacke in der Praxis stattfindet?

            Hash-Funktion verstehen, Umkehrfunktion schreiben, Hash reinstecken, Passwort rauskriegen. :-)

            Viele Gruesse,
            der Bademeister

            1. Hello,

              Eine Rainbow-Attacke besteht, vereinfacht, daraus, flaechendeckend von moeglichen Passwoertern die Hashes zu berechnen und das Ganze auf effiziente Weise zu speichern, um dann einen konkreten Hash darin zu suchen.

              Ja, ist klar.

              Das geht fuer *jede* Hash-Funktion - es steckt keinerlei Logik dahiner, die von der konkreten Funktion abhaengt.

              Ist auch klar, da der Algorithmus für die Ermittlung des Prüfwertes schließlich bekannt sein muss.

              Eine Urbild-Attacke ist ein konkreter Algorithmus, der zu einem konkreten Hash ein Urbild (also ein dazu passendes Passwort) ermittelt. Im Idealfall (aus Angreifer-Sicht) also eine mathematische Umkehrfunktion des Hashs. Bei einer guten (idealen) Hashfunktion gibt es sowas nicht, bei MD5 schon. Diese bekannten Angriffe fuer MD5 sind nun keine deterministischen Funktionen, die eben mal so aus dem Handgelenk ein Urbild ausrechnen, sondern verwenden intern immer noch einige (Sub-)Lookups, aber sie sind (je nach konkretem Hash) erheblich effizienter als Rainbow-Tabellen.

              Verstehe ich immer noch nicht. Wenn es doch einen effektiven Algorithmus für die Zuordnung eines (von vielen möglichen) Urbildes zu seinem (einzigen) Prüfwert gibt (bzw. ja anders herum, des einzigen Prüfwertes zur Lösungsschaar der Urbilder), dann kann ich den doch schließlich auch für die Berechnung der Rainbow Tables benutzten. Schließlich gibt es erheblich weniger Prüfwerte, als es Urbilder gibt.

              Und wenn ich die Rainbow Table erst habe, brauche ich nicht mehr zu rechnen, wenn ich den Prüfwert darin finde. Den sollte ich per passender Sortierung sehr schnell finden.

              Kannst Du mir erklären, wie so eine Urbild-Attacke in der Praxis stattfindet?

              Hash-Funktion verstehen, Umkehrfunktion schreiben, Hash reinstecken, Passwort rauskriegen. :-)

              _Das_ Passwort werde ich wohl nicht unbedingt herausbekommen, aber _ein_ passendes. Eine Umkehrfunktion gibt es schließlich nicht, da der Hash-Algorithmus keine bijektive Abbildung ist.

              Liebe Grüße aus dem schönen Oberharz

              Tom vom Berg

              --
               ☻_
              /▌
              / \ Nur selber lernen macht schlau
              http://bergpost.annerschbarrich.de
              1. Verstehe ich immer noch nicht. Wenn es doch einen effektiven Algorithmus für die Zuordnung eines (von vielen möglichen) Urbildes zu seinem (einzigen) Prüfwert gibt (bzw. ja anders herum, des einzigen Prüfwertes zur Lösungsschaar der Urbilder),

                Wirf das nicht in einen Topf. Die Hash-Abbildung (Passwort -> Hashwert) ist gegeben und *nur* die wird zum Anlegen der Rainbow-Tabellen benutzt. Das "anders herum" gibt es zunaechst mal nicht. Und das brauchst Du fuer eine effiziente Urbild-Attacke. Ich habe gerade oben ein Beispiel gemacht.

                Viele Gruesse
                der Bademeister

                1. Hello,

                  Verstehe ich immer noch nicht. Wenn es doch einen effektiven Algorithmus für die Zuordnung eines (von vielen möglichen) Urbildes zu seinem (einzigen) Prüfwert gibt (bzw. ja anders herum, des einzigen Prüfwertes zur Lösungsschaar der Urbilder),

                  Wirf das nicht in einen Topf. Die Hash-Abbildung (Passwort -> Hashwert) ist gegeben und *nur* die wird zum Anlegen der Rainbow-Tabellen benutzt. Das "anders herum" gibt es zunaechst mal nicht. Und das brauchst Du fuer eine effiziente Urbild-Attacke. Ich habe gerade oben ein Beispiel gemacht.

                  Ich habs gesehen und finde das Beispiel sehr gut gemacht.
                  Du solltest einen kurzen Artikel daraus machen [das ist kein Witz].

                  Aber warum sollte man eine "Umkehrfunktion" nicht auch dazu benutzten, Raimbow Tables zu erzeugen. Man könnte ja auch dabei das Pferd von hinten aufzäumen.

                  Allerdings kann ich mir auch vorstellen, dass es zu manchen "Prüfwerten" gar keine Urbilder gibt.

                  Aber nochmal zurück zur Passwortsicherheit. Könnte man die nach diesen Überlegungen nicht erhöhen, wenn man z.B. vorschreibt, dass das Passwort genau 12 Zeichen lang sein muss? Damit würden alle zurückgerechneten Urbilder, die weniger oder mehr als 12 Zeichen hätten, als ungültig erkannt werden, auch wenn sie denselben Prüfwert ergeben würden.

                  Vorwärts benutzt schränkt das allerdings auch die Menge der möglichen Passwörter ein.

                  Was wiegt nun schwerer? Da fehlt mir leider der mathematische Background.

                  Liebe Grüße aus dem schönen Oberharz

                  Tom vom Berg

                  --
                   ☻_
                  /▌
                  / \ Nur selber lernen macht schlau
                  http://bergpost.annerschbarrich.de
                  1. Aber warum sollte man eine "Umkehrfunktion" nicht auch dazu benutzten, Raimbow Tables zu erzeugen. Man könnte ja auch dabei das Pferd von hinten aufzäumen.

                    Ja, wenn man eine Umkehrfunktion erstmal hat, dann braucht man u.U. immer noch sowas wie (kleinere) Rainbow-Tabellen (etwa in dem Beispiel zumindest eine, die alle Hashs der durch drei teilbaren Zahlen liefert), d.h. die Dinge gehen ineinander ueber. Nur der klassische Rainbow-Angriff ist eben ein Angriff *ohne* jede Kenntnis irgendeiner Art Umkehrfunktion.

                    Allerdings kann ich mir auch vorstellen, dass es zu manchen "Prüfwerten" gar keine Urbilder gibt.

                    Ja, das ist im allgemeinen so. In meinem Beispiel etwa waere wie angesprochen keine Zahl mit Rest 2 modulo 3 ein tatsaechlich vorkommender Hashwert.

                    Aber nochmal zurück zur Passwortsicherheit. Könnte man die nach diesen Überlegungen nicht erhöhen, wenn man z.B. vorschreibt, dass das Passwort genau 12 Zeichen lang sein muss? Damit würden alle zurückgerechneten Urbilder, die weniger oder mehr als 12 Zeichen hätten, als ungültig erkannt werden, auch wenn sie denselben Prüfwert ergeben würden.

                    Das Problem wird im Grunde bereits durch den Gebrauch von Salts geloest. Szenario:

                    Mein Passwort ist "abc", in der Datenbank gespeichert ist md5("abcsalt"). (Also "salt" ist der Salt). Jemand von aussen kennt nun diesen MD5-Wert und findet nun ein anderes Wort "neueswort", so dass md5("neueswort") == md5("abcsalt"). Das nuetzt ihm nichts, da nun bei Eingabe dieses Wortes der md5 von "neueswortsalt" gegen den gespeicherten Hash verglichen wuerde. Selbst wenn er den Salt kennt, wuerde ihm das a priori nicht viel helfen. Einen Wert zu finden, der zusammen mit einem gegebenen Salt auf einen gegebenen Hash abgebildet wird, ist noch eine erheblich schwierigere Attacke.

                    Viele Gruesse,
                    der Bademeister

                    1. Hallo,

                      ich habe mal eine Zwischenfrage:

                      Das Problem wird im Grunde bereits durch den Gebrauch von Salts geloest. Szenario:

                      Mein Passwort ist "abc", in der Datenbank gespeichert ist md5("abcsalt"). (Also "salt" ist der Salt). Jemand von aussen kennt nun diesen MD5-Wert und findet nun ein anderes Wort "neueswort", so dass md5("neueswort") == md5("abcsalt"). Das nuetzt ihm nichts, da nun bei Eingabe dieses Wortes der md5 von "neueswortsalt" gegen den gespeicherten Hash verglichen wuerde. Selbst wenn er den Salt kennt, wuerde ihm das a priori nicht viel helfen. Einen Wert zu finden, der zusammen mit einem gegebenen Salt auf einen gegebenen Hash abgebildet wird, ist noch eine erheblich schwierigere Attacke.

                      Wäre es anstatt (oder neben) Salts nicht auch sinnvoll, das Passwort in der Datenbank mehrmals zu speichern und dabei jeweils unterschiedliche Verschlüsselungsalgorithmen zu verwenden?

                      Also einmal mit md5, einmal mit sha und was es noch so gibt.

                      Wenn man dann über Rainbowtables oder anders als Angreifer auf _ein_ mögliches Passwort kommt hilft einem das immer noch nicht, weil dieses eine mögliche Passwort bei den anderen Algorithmen bestimmt nicht auch unter die möglichen Passwörter fällt. So müsste der Angreifer also schon auf das richtige Passwort kommen, um dann damit in andere Accounts des Users (wo er das selbe Passwort nutzt) einzubrechen.

                      Gruß
                      Alex

                      1. Hi!

                        Wäre es anstatt (oder neben) Salts nicht auch sinnvoll, das Passwort in der Datenbank mehrmals zu speichern und dabei jeweils unterschiedliche Verschlüsselungsalgorithmen zu verwenden?

                        Dann kann ich also gleich mehrere vorbereitete Hashlisten heranziehen und in ihnen nach einem Vorkommen nachsehen, falls die eine oder andere neben ihren Schnittmengen noch Überhänge anbietet.

                        Wenn man dann über Rainbowtables oder anders als Angreifer auf _ein_ mögliches Passwort kommt hilft einem das immer noch nicht, weil dieses eine mögliche Passwort bei den anderen Algorithmen bestimmt nicht auch unter die möglichen Passwörter fällt.

                        Dann müsste es aber ein ausreichend langes Passwort sein, für das sich keine Rainbow-Tabellen-Erstellung mehr lohnt. Dann müsste man sich einen kollidierenden Wert suchen, der dann mit der anderen Methode nicht passt. Das erhöht die Sicherheit nur bei sowieso schon sehr sicheren Passwörtern aber laschem Algorithmus. Ein starkes Passwort und ein ordentliches Hash-Verfahren sollte reichen.

                        Lo!

                      2. Hi Alex.

                        Ergänzend zu dedlfix' Antwort:

                        Wäre es anstatt (oder neben) Salts nicht auch sinnvoll, das Passwort in der Datenbank mehrmals zu speichern und dabei jeweils unterschiedliche Verschlüsselungsalgorithmen zu verwenden?

                        Die Antwort ist eindeutig 'Nein'. Das Thema Kollisionen spielt (in diesem Szenario) eine viel kleinere Rolle, als man vielleicht denken mag. Bei einem guten Hash-Algorithmus findet ein Angreifer *überhaupt*kein* Urbild zu einem gegebenen Hash - falls doch, hat der Algorithmus bereits versagt.

                        Mal ne kurze Rechnung:

                        Nehmen wir mal an, wir bilden Hash-Werte von Strings von Länge 32 (Passwort + ggf. Salt). Bei einem Alphabet von, sagen wir, 80 Zeichen (Groß-/Kleinbuchstaben, Ziffern und ein paar andere), haben wir 32^80 mögliche Strings, die in Frage kommen, also (2^5)^80 = 2^400.

                        Ungefähr in der Größenordnung - ganz grob - ist auch die Anzahl der Hash-Werte (2^128 bei MD5, bis zu 2^512 bei SHA-2). Wenn wir also von SHA-2 ausgehen, dann ist erstmal genug "Platz" da, damit es bei unseren Wörtern nicht notwendigerweise viele Kollisionen gibt, und bei einem guten Hash-Algorithmus gibt es die auch nicht.

                        Selbst wenn, mal hypothetisch, im Schnitt jeweils eine Million (= ca. 2^20) unserer möglichen Passwörter kollidieren und denselbern Hash-Wert haben, dann müssen wir im Schnitt 2^400 / 2^20 = 2^380 mögliche Passwörter ausprobieren, um eines dieser 1 Millionen Urbilder zu finden. Das ist immer noch *viel* zu viel.

                        Soll heißen: Du kannst einen Hash-Algorithmus bereits als unbrauchbar ansehen, wenn ein Angreifer irgendein(!) Urbild eines Hash-Wertes finden kann - das bedeutet nämlich, dass er viel zu leichte Urbild-Attacken liefert. Du brauchst also für Deine Website-Nutzerverwaltung auf das Kollisionsproblem keinerlei Rücksicht zu nehmen.

                        Viele Grüße,
                        der Bademeister

                        1. haben wir 32^80 mögliche Strings

                          Blödsinn. Wir haben 80^32 mögliche Strings, also ca. 2^38. Dann sollte der Salt noch ein bisschen länger gemacht werden, damit die Rechnung ansonsten stimmt...

                          Viele Grüße,
                          der Bademeister

                      3. Moin Moin!

                        Wäre es anstatt (oder neben) Salts nicht auch sinnvoll, das Passwort in der Datenbank mehrmals zu speichern und dabei jeweils unterschiedliche Verschlüsselungsalgorithmen zu verwenden?

                        MD5 und SHA sind KEINE Verschlüsselung, es sind Prüfsummen!

                        Also einmal mit md5, einmal mit sha und was es noch so gibt.

                        <schwarzer Schlapphut>
                        Oh ja, prima! Bitte mit allen Hash-Algorithmen, die Du finden kannst. Dann suche ich mir den raus, für den ich am wenigsten Aufwand brauche, um an Passworte zu kommen.
                        </schwarzer Schlapphut>

                        Nimm den härtesten Algorithmus, der Dir zur Zeit zur Verfügung steht, und nutze ein Salt (idealerweise bei jedem Speichervorgang ein anderes), dazu gab's schon genug Postings. Wenn Du im Laufe der Zeit einen noch härteren Algorithmus findest und auf diesen wechselst, speicherst Du ab dem Zeitpunkt "gesalzene" Passwort-Hashes mit dem neuen Algorithmus, für neue User und für alte User, die ihr Passwort ändern müssen / wollen. Sorge dafür, dass Du am Hash erkennen kannst, welcher Algorithmus benutzt wurde, z.B. indem Du den Algorithmus-Namen zusammen mit dem "gesalzenen" Hash abspeicherst.

                        Alexander

                        --
                        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
                        1. Hi Alexander.

                          Wenn Du im Laufe der Zeit einen noch härteren Algorithmus findest und auf diesen wechselst, speicherst Du ab dem Zeitpunkt "gesalzene" Passwort-Hashes mit dem neuen Algorithmus, für neue User und für alte User, die ihr Passwort ändern müssen / wollen.

                          Die User müssen nicht mal ihr Passwort ändern, sondern sich lediglich einmal einloggen, damit ein neuer Hash des Passwortes gespeichert werden kann.

                          Viele Grüße,
                          der Bademeister

                          1. Moin Moin!

                            Die User müssen nicht mal ihr Passwort ändern, sondern sich lediglich einmal einloggen, damit ein neuer Hash des Passwortes gespeichert werden kann.

                            Hmmm, stimmt auffallend. ;-)

                            Alexander

                            --
                            Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
            2. Ich mach mal gerade ein kleines Beispiel:

              Um Zahlen zu verschluesseln, nehme ich die folgende ausserordentlich komplizierte Hash-Funktion:

              [latex] x \mapsto (x+6)^2 % 15 [/latex]

              Also:

              • Addiere 6
              • Quadriere
              • Nimm das Ergebnis modulo 15.

              Du als Hacker kennst den Algorithmus und moechtest zu einem gegebenen Hash (also einer Zahl zwischen 0 und 14) ein(!) moegliches Urbild finden. Jetzt kannst Du:

              A:
              Eine Rainbow-Tabelle anlegen, also, vereinfacht, von alen "kleinen" Zahlen (was immer das genau heisst), die Hash-Werte ausrechnen, speichern, und dann mit vergleichen anfangen. Zu gegebenem Hashwert wuerdest Du immer nach maximal 15 Vergleichen ein Urbild finden.

              B:
              Dir den Algorithmus genau anschauen und folgendes feststellen:

              x ist genau dann durch 3 teilbar, wenn der Hashwert durch 3 teilbar ist!

              Grund:

              1.: x+6 ist durch 3 teilbar gdw x durch 3 teilbar ist - klar.
              2.: y^2 ist durch 3 teilbar gdw y durch 3 teilbar ist (Primfaktorzerlegung)
              3.: z % 15 ist durch 3 teilbar gdw z durch 3 teilbar ist (klar - es wird nur ein Vielfaches von 15 - und damit von 3 - abgezogen).

              Wenn Du das weisst, kannst Du es benutzen:

              Wenn ein gegebener Hashwert durch drei teilbar ist, musst Du nur noch alle Zahlen als Urbilder testen, die durch 3 teilbar sind, und wirst damit schon nach hoechstens 5 statt 15 Versuchen fuendig.

              Letzteres ist immer noch ein Algorithmus, der aufwaendig ist, aber es ist wesentlich(!) effizienter als der Rainbow-Angriff - wenn auch nur fuer bestimmte Hashwerte. Fuer andere Hashwerte gibt der Angriff etwas weniger her: wenn x Rest 1 oder 2 (mod 3) hat, dann wird der Hashwert in beiden Faellen Rest 1 (mod 3) haben, wegen des Quadrierens, und man muss bis zu zehn Urbilder nachgucken.

              So kann man sich das vorstellen. Eine gute Hash-Funktion laesst keine Rueckschluesse vom Hashwert auf das Urbild zu und liefert damit keinen Ansatz wie oben. MD5 aber tut das.

              Viele Gruesse,
              der Bademeister

    3. Hallo Bademeister,

      Wovor willst Du Sicherheit? (Ist ne echte Frage.)

      Vor Missbrauch, Hacking und DAU's

      MD5 ist unsicher. Schau Dir mal die SHA-2-Hashes an. Ansonsten suche nach dem Stichwort "Salt" im Archiv.

      Danke, das ist schonmal ein Punkt :)

      Bei jedem weiteren Aufruf einer Seite wird nun erneut Benutzername und Passwort überprüft.
      Nein! Dazu müsste der Nutzer jedes Mal wieder die Daten senden.

      Der Nutzer übermittels jedes Mal nur seine SessionID. Die Überprüfung findet dann über die gespeicherten Session-Variablen statt.

      Ist der letzte Schritt unnötig?
      Mehr noch: er ist problematisch. Er erhöht die Sicherheit nicht, und schafft anderesherum evtl. Dritten zusätzliche Möglichkeiten

      Also ist die erneute Überprüfung bei jedem Seitenaufruf wohl abgewählt. Vielen Dank genau dort habe ich nach Klarheit gesucht.

      1.: Sehr ratsam ist ein automatischer Logout

      Check: alle 30min. Bringt außerdem als Begleiterscheinung das nette "* User online"-Feature.

      2.: Wenn Dir danach ist, kannst Du aktiv mit einem Hinweis anregen, dass Deine Nutzer vernünftige Passwörter verwenden und nicht etwa "qwertz" oder dergleichen.

      Sehe ich ähnlich: Hinweis ja, Verbot nein! Aber ich denke über eine Abfrage nach, welche dies prüft und einen gezielten Hinweis gibt, welcher zu bestätigen wäre.

      3.: Überlege Dir, wozu man mit einem normalen Login Zugang haben sollte und wozu nicht. Wenn zum Beispiel der Nutzer in irgendwelchen Nutzereinstellungen die Möglichkeit hat, sein Passwort zu ändern, dann sollte das nur mit erneuter Eingabe des alten Passwortes möglich sein.

      Check!

      4.: Du solltest auf mehrfach gescheiterte Login-Versuche reagieren.

      Danke, das ist noch ein gute Punkt, den ich einbauen werde!

      Gruß,
      Sebastian.

      1. Hello,

        Der Nutzer übermittels jedes Mal nur seine SessionID. Die Überprüfung findet dann über die gespeicherten Session-Variablen statt.

        Ist der letzte Schritt unnötig?
        Mehr noch: er ist problematisch. Er erhöht die Sicherheit nicht, und schafft anderesherum evtl. Dritten zusätzliche Möglichkeiten
        Also ist die erneute Überprüfung bei jedem Seitenaufruf wohl abgewählt. Vielen Dank genau dort habe ich nach Klarheit gesucht.

        Das kommt doch darauf an, welches Verfahren Du für die Authenifikation benutzen willst oder kannst.
        Wenn Du Cookies benutzen kannst, ist es unnötig, die Credentials bei jedem Request erneut zu übertragen. Es wäre sogar schwierig, dies zu tun, ohne den User zu nerven.

        Wenn Du mit HTTP Auth arbeitest, geht es nicht anders. Dann überträgt der Browser bei jedem Request das Paar aus Username und Passwort erneut.

        Liebe Grüße aus dem schönen Oberharz

        Tom vom Berg

        --
         ☻_
        /▌
        / \ Nur selber lernen macht schlau
        http://bergpost.annerschbarrich.de
  2. @@Sebastian Goertz:

    nuqneH

    In der letzten Ausgabe von A List Apart gibt es dazu einen Artikel, s.a. Kommentare.

    Qapla'

    --
    Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
    (Mark Twain)
  3. Hallo,

    ich mache mir gerade Gedanken um bestmögliche Sicherheit bei der Arbeit mit Sessions beim Login. Nun Interessieren mich andere Meinungen dazu...

    ich bin letztens zufällig über diese Seite gestolpert:
    http://code.google.com/intl/de/edu/security/index.html

    Schau dir mal die Videos an - vorallem das erste "How to break Web Software" ist sehr interessant. Da geht es unter anderem auch um das stehlen von Sessions und andere Sicherheitsrisiken.

    Ich schütze bei meiner Seite die Session noch durch die IP-Adresse des Users. Diese wird also in der Session gespeichert und bei jedem Request wird die gespeicherte mit der aktuell übermittelten IP verglichen - gibt es Unterschiede, wird der User hieruüber informiert und gebeten sich erneut einzuloggen.

    Z.B. bei AOL Usern kann es da zu Problemen kommen, weil sich da mit jedem Request die IP ändern kann. Aber soweit ich weiß bleibt das immer in einem gewissen IP-Pool - nur die letzten 3 Zahlen verändern sich. Daher schneide ich also die zu testenden IPs jeweils um die letzten 3 Ziffern.

    Bis jetzt habe ich noch von niemanden gehört, dass es damit Probleme gibt. Und die Sicherheit erhöht es jedenfalls, weil man nicht mehr so einfach vone inem anderen Internetanschluss die Session klauen kann.

    Gruß
    Alex

  4. Vielen Dank an alle für die Antworten. Ich schreibe mal kurz zusammen, was für mich dabei rausgekommen ist. Vielleicht auch dann als brauchbare Hilfestellung für Archiv-Suchende ;)

    Mein Login-System sieht dann im Großen und Ganzen so aus:

    Anmeldung

    1. Überprüft Passwort auf Sicherheit. Gibt ggf. hilfreiche Tipps, lässt aber im Prinzip alles zu
    2. Speichert Benutzername/Passwort in Datenbank. Passwort als Hash in der Form: $hash = hash("sha512", md5($username).$password);

    Login-Script

    1. Überprüft den Benutzernamen
    2. Erstellt den Hash und überprüft ihn mit der Datenbank
    3. Überprüft ob Cookies aktiv sind, gibt sonst Warnung aus
    4. Startet die Session und legt Variablen an: "CheckLogin"=TRUE, "IP-Addr", "Zugangsrechte"
    5. Überprüft Anzahl der zuvor gescheiterten Logins. Gibt ggf. Warnung aus.

    Prüf-Script ##### (zu Beginn eines jeden Seitenaufrufs)

    1. Überprüft, ob "CheckLogin"=TRUE
    2. Überprüft, ob IP unverändert: substr("IP-Add",0,strlen("IP-Addr")-3) für AOL-Nutzer
    3. Überprüft, ob letzte Aktivität älter als 30min => Logout
    4. Setzt letzte Aktivität auf aktuelle Zeit
    5. Aktualisiert "Zugangsrechte" aus Datenbank
    6. Weist neue SessionID zu (session_regenerate_id())

    Hoffe, das jetzt alles "richtig" auf der Reihe zu haben. :-)

    1. Hi!

      1. Speichert Benutzername/Passwort in Datenbank. Passwort als Hash in der Form: $hash = hash("sha512", md5($username).$password);

      Wie begründest du, dass du vom Usernamen einen MD5-Hash bildest? Wenn du dir schon Gedanken über Sicherheit machst, dann solltest du auch die Sinnhaftigkeit nachweisen können. Hast du dir mal Literatur über hashs of salted passwords gesucht?

      Lo!

      1. Moin Moin!

        1. Speichert Benutzername/Passwort in Datenbank. Passwort als Hash in der Form: $hash = hash("sha512", md5($username).$password);

        Wie begründest du, dass du vom Usernamen einen MD5-Hash bildest? Wenn du dir schon Gedanken über Sicherheit machst, dann solltest du auch die Sinnhaftigkeit nachweisen können. Hast du dir mal Literatur über hashs of salted passwords gesucht?

        Ich glaube, Du hast das Stückchen Code nicht wirklich gelesen oder es gründlich mißverstanden.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
        1. Hi!

          1. Speichert Benutzername/Passwort in Datenbank. Passwort als Hash in der Form: $hash = hash("sha512", md5($username).$password);
            Wie begründest du, dass du vom Usernamen einen MD5-Hash bildest? Wenn du dir schon Gedanken über Sicherheit machst, dann solltest du auch die Sinnhaftigkeit nachweisen können. Hast du dir mal Literatur über hashs of salted passwords gesucht?
            Ich glaube, Du hast das Stückchen Code nicht wirklich gelesen oder es gründlich mißverstanden.

          Wie hätte ich es denn deines Glaubens nach verstehen sollen? Ich sehe, dass von einem Usernamen der MD5-Hash mit dem Passwort verknüpft wird und davon ein SHA512-Hash gebildet werden soll und frage mich nun - oder besser den Autor -, was der geMD5te Username dort macht? Soll das ein Salt sein? Und wenn ja, was ist dann mit solch bekannten Usernamen wie admin und root, von denen man vorberechnete Hashes bereithalten kann?

          Lo!

          1. Moin Moin!

            1. Speichert Benutzername/Passwort in Datenbank. Passwort als Hash in der Form: $hash = hash("sha512", md5($username).$password);
              Wie begründest du, dass du vom Usernamen einen MD5-Hash bildest? Wenn du dir schon Gedanken über Sicherheit machst, dann solltest du auch die Sinnhaftigkeit nachweisen können. Hast du dir mal Literatur über hashs of salted passwords gesucht?
              Ich glaube, Du hast das Stückchen Code nicht wirklich gelesen oder es gründlich mißverstanden.

            Wie hätte ich es denn deines Glaubens nach verstehen sollen? Ich sehe, dass von einem Usernamen der MD5-Hash mit dem Passwort verknüpft wird und davon ein SHA512-Hash gebildet werden soll und frage mich nun - oder besser den Autor -, was der geMD5te Username dort macht? Soll das ein Salt sein?

            Offenbar.

            Und wenn ja, was ist dann mit solch bekannten Usernamen wie admin und root, von denen man vorberechnete Hashes bereithalten kann?

            Das fällt unter "Pech gehabt". Es lebe der frei definierte Superuser-Name ... ;-)

            Im Ernst: Eine "vielbittige" Zufallszahl als Salt wäre hier in der Tat günstiger, die packt man zusammen mit dem Hash in die DB und alles wird gut.

            Alexander

            --
            Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
            1. Hi!

              Ich sehe, dass von einem Usernamen der MD5-Hash mit dem Passwort verknüpft wird und davon ein SHA512-Hash gebildet werden soll und frage mich nun - oder besser den Autor -, was der geMD5te Username dort macht? Soll das ein Salt sein?
              Offenbar.

              Dann müsste man sich erkundigen, (ob et)was gegen die Verwendung des Usernamens als Salt spricht. Da wird sich sicher schon jemand darüber Gedanken gemacht und sie ins Internet geschrieben haben. Bleibt immer noch die Frage nach dem Sinn des Hashen des Usernamens. Soll der Vorgang an sich so komplex gestaltet sein, dass die Wahrscheinlichkeit für vorberechnete Tabellen nach diesem Muster möglichst gering ist?

              Lo!

              1. Hello,

                Dann müsste man sich erkundigen, (ob et)was gegen die Verwendung des Usernamens als Salt spricht.

                Darüber habe ich gestern schon nachgedacht, als ich mein eigenes Loginsystem anhand der Anregungen dieses Threads untersucht habe.

                Der Username als SALT darf keinesfalls verwendet werden, da er
                1. bekannt sein kann (Social Engineering, zugucken bei der Eingabe)
                2. beim Login über das Netz gejagt wird und damit ebenfalls wieder bekannt ist.

                Der Salt sollte aber außen unbekannt bleiben.
                Es kann für jeden User ein anderer benutzt werden. So habe ich es zur Zeit gelöst.

                Liebe Grüße aus dem schönen Oberharz

                Tom vom Berg

                --
                 ☻_
                /▌
                / \ Nur selber lernen macht schlau
                http://bergpost.annerschbarrich.de
                1. Hi!

                  Der Username als SALT darf keinesfalls verwendet werden, da er

                  1. bekannt sein kann (Social Engineering, zugucken bei der Eingabe)
                  2. beim Login über das Netz gejagt wird und damit ebenfalls wieder bekannt ist.
                    Der Salt sollte aber außen unbekannt bleiben.

                  Sicherlich ist es erstrebenswert, dass nach außen hin alles unbekannt bleibt. Aber genau für den Fall, dass es doch öffentlich wird, ist der Salt erfunden worden. Man kann dann nämlich nicht mehr auf einen Blick anhand gleicher Hashes gleiche Passwörter erkennen, und die Verwendung von Rainbowtables wird auch erschwert. Ein Username als Salt ist im Falle eines Falles genauso bekannt wie ein zufälliger Wert. Es geht nun darum, ob er beim Verwenden von anderen Hilfsmitteln (wie Rainbowtables) "nützlich" ist (weil wegen seines häufigen Vorkommens bereits welche vorberechnet sind) oder nicht (man Brute Force benötigt).

                  Lo!

                  1. Hi dedlfix.

                    Es geht nun darum, ob er beim Verwenden von anderen Hilfsmitteln (wie Rainbowtables) "nützlich" ist (weil wegen seines häufigen Vorkommens bereits welche vorberechnet sind) oder nicht (man Brute Force benötigt).

                    Ein Username als Salt selber ist schlecht. Aber wenn man den Usernamen mit einbaut beim Hashen, dann erlaubt dies, darüberhinaus einen festen Salt zu verwenden und nicht einen individuellen für jeden User. (Der "individuelle" Salt für jeden User ist dann quasi $username . "festersalt").

                    Das ist u.U. praktisch, u.a.U. allerdings logistisch etwas problematisch. In Anwendungen, in denen der Username geändert werden kann, ist diese Lösung mehr oder weniger disqualifiziert (es sei denn, man verlangt vom User beim Ändern des Usernamen wiederum die Eingabe des Passwortes).

                    Viele Grüße,
                    der Bademeister

    2. Hello,

      Vielen Dank an alle für die Antworten. Ich schreibe mal kurz zusammen, was für mich dabei rausgekommen ist. Vielleicht auch dann als brauchbare Hilfestellung für Archiv-Suchende ;)

      Mein Login-System sieht dann im Großen und Ganzen so aus:

      Anmeldung
      1. Überprüft Passwort auf Sicherheit. Gibt ggf. hilfreiche Tipps, lässt aber im Prinzip alles zu
      2. Speichert Benutzername/Passwort in Datenbank. Passwort als Hash in der Form: $hash = hash("sha512", md5($username).$password);

      Dabei sollte auf dem Usernamen ein Unique Index liegen, damit der nicht doppelt eingetragen werden kann.

      Login-Script
      1. Überprüft den Benutzernamen
      2. Erstellt den Hash und überprüft ihn mit der Datenbank

      Zusammenfassen ^ zu einem Query

      1. Überprüft ob Cookies aktiv sind, gibt sonst Warnung aus
      2. Startet die Session und legt Variablen an: "CheckLogin"=TRUE, "IP-Addr", "Zugangsrechte"
      3. Überprüft Anzahl der zuvor gescheiterten Logins. Gibt ggf. Warnung aus.

      Schritt 1, 2 und 5 müssen möglichst in einem gemeinsamen Query durchgeführt werden. Dafür kannst Du bei MySQL ein Update Select() nehmen, dass die Selectdaten in benutzerdefinierten Variablen hinterlässt. Diese können dann gleich anschließend abgeholt werden.

      Diese Vorgehensweise ist quasi-atomar, weil Variablen für jede Connection getrennt geführt werden und innerhalb EINES Queries abgerufen wurden.

      Prüf-Script ##### (zu Beginn eines jeden Seitenaufrufs)
      1. Überprüft, ob "CheckLogin"=TRUE
      2. Überprüft, ob IP unverändert: substr("IP-Add",0,strlen("IP-Addr")-3) für AOL-Nutzer
      3. Überprüft, ob letzte Aktivität älter als 30min => Logout
      4. Setzt letzte Aktivität auf aktuelle Zeit
      5. Aktualisiert "Zugangsrechte" aus Datenbank
      6. Weist neue SessionID zu (session_regenerate_id())

      Hoffe, das jetzt alles "richtig" auf der Reihe zu haben. :-)

      Trenne Authentifizierung und Legitimation in (mindestens) zwei Tabellen auf.

      Sorge dafür, dass Du keine Query-Stacks baust, die nicht atomar gebunden sind.

      Liebe Grüße aus dem schönen Oberharz

      Tom vom Berg

      --
       ☻_
      /▌
      / \ Nur selber lernen macht schlau
      http://bergpost.annerschbarrich.de