Peter Strucks: Session - ich weiß nicht mehr weiter

Hallo zusammen.

In den letzten Tagen wurde hier soviel über Sessions, Sicherheit und Loginsysteme diskutiert, das es den meisten hier denk ich schon langsam zum Hals raushängt. Von daher werd ich nur noch einmal jetzt eine Frage stellen. Und diesmal geht es mir mehr darum einfach mal ein Beispiel zu bekommen als darum wie Sessions funktionieren denn das weiß ich.

Wie ich bisher vorgehe(ich lasse grundlegende Sachen wie SQL Verbindung weg):

session_start();
$query="SELECT user,pwd,bereich,userid FROM all_user WHERE user='$nick'";

$num=mysql_query($query,$c) or die (mysql_error());
$row = mysql_fetch_array($num);
if(!$row){
 header('Location: fehler.php');
 die();
}
$r_name = $row["user"];
$r_pw = $row["pwd"];
$r_branche = $row["branche"];
$r_uid = $row["userid"];
$_SESSION["id"] = $r_uid;
$_SESSION["nickname"] = $r_name;
$_SESSION["bereich"] = $r_branche;
$_SESSION['IP']=$_SERVER['REMOTE_ADDR'];
header("Location: weiter.php");

So. Die Session wird gestartet und es werden 4 Variablen reingeschrieben, di eich zuvor aus einer DB hole. Dann wird auf weiter.php weitergeleitet.
// weiter.php sieht so aus:

session_start ();
if(!isset ($_SESSION["user_id"])){
 header ("Location: index.php");
 die();
}elseif($_SESSION['IP'] != $_SERVER['REMOTE_ADDR']) {
 header ("Location: index.php);
 die();
}

include('sql.php');
$c=mysql_connect($host,$user,$pw);
mysql_select_db('xxx',$c);
$query="SELECT user,pwd,bereich,userid FROM all_user WHERE user='$nick'";
$num=mysql_query($query,$c) or die (mysql_error());
$row = mysql_fetch_array($num);
$r_name = $row["user"];
$r_pw = $row["pwd"];
$r_branche = $row["branche"];
$r_uid = $row["userid"];

Dann vergleiche ich die Session Variablen mit den $r_x variablen.
Wenn alle gleich sind dann wird die Seite angezeigt wenn nicht wird wieder zu index.php weitergeleitet.Ich hab mir den Code gespart ist zu unübersichtlich hier.

So damit habe ch ein Session System das ziemlich unsicher ist meiner Meinung nach. Wie kann ich es nun sicherer machen wenn ich folgendes nicht will:

  • Session fälschbar

  • Session erratbar/ersniffbar

  • Angenommen ich bin eingeloggt und gebe den Link weiter, dann soll der andere sich nicht die Seite angucken ohne sich vorher eingeloggt zu haben.

  • Der User soll jedes mal eine andere Session bekommen.

  • fällt euch noch weitere Sachen ein?

Der Login is geschützt so das XSS kaum/schlecht und SQL Injektions auch nicht möglch sind es geht mir jetzt rein um die Sessions.

Mit freundlichen Grüßen

Peter Strucks

PS: Ich hoffe das sich das Thema damit entgültig hiermit erledigt hat und hoffe auf viele Antworten und Beispiele(auch Codebeispiele manchmal versteht man es dann einfach besser).
Danke.

  1. hi,

    In den letzten Tagen wurde hier soviel über Sessions, Sicherheit und Loginsysteme diskutiert, das es den meisten hier denk ich schon langsam zum Hals raushängt.

    *meld*

    Und zwar nicht nur ob der Häufigkeit des Auftauchens dieses Themas - sondern noch viel mehr, weil von denen, die hier danach fragen, wie sie etwas "sicherer" machen, sich offenbar nur die wenigsten vorher mal gefragt haben, wo denn überhaupt die _Lücken_ ihres bisherigen Aufbaus liegen könnten. Wer diese mal analysiert, dürfte idR. auch schon sehr nahe an ihrer Abstellung und Behebung sein.

    Das schließt natürlich auch bei gewissenhaftester Betrachtung nicht aus, dass man etwas übersieht, und davor ist auch kein "Profi" gefeit (und ein solcher würde sowas auch sicher nicht annehmen).
    Deshalb mal nach dem Prinzip "vier Augen sehen mehr als zwei" anzufragen, ist vollkommen OK.
    Nur das übliche "wie mach ich X sicher(er)?" offenbar mit wenig vorausgehenden Einsatz eigenen Gehirnschmalzes nervt.

    Nimm das bitte nicht persönlich, es ist nicht speziell auf deinen Thread bezogen.

    session_start();
    $query="SELECT user,pwd,bereich,userid FROM all_user WHERE user='$nick'";

    Woher kommt $nick?
    Hier hast du die erste Lücke, wenn du einen von extern kommenden Wert nicht absicherst.

    $num=mysql_query($query,$c) or die (mysql_error());
    $row = mysql_fetch_array($num);
    if(!$row){
    header('Location: fehler.php');
    die();

    Abgesehen davon, dass ein Location-Header per Definition einen absoluten URL inkl. Protokollangabe erfordert -
    Warum eigentlich immer Umleiten?
    Warum nicht die Fehlermeldung innerhalb der gleichen Ressource ausgeben?

    So. Die Session wird gestartet und es werden 4 Variablen reingeschrieben, di eich zuvor aus einer DB hole. Dann wird auf weiter.php weitergeleitet.

    Warum wieder Umleiten ...?

    // weiter.php sieht so aus:

    session_start ();
    if(!isset ($_SESSION["user_id"])){
    header ("Location: index.php");
    die();

    Warum wieder Umleiten ...?

    }elseif($_SESSION['IP'] != $_SERVER['REMOTE_ADDR']) {

    Ungut.
    Dass die IP zwischen mehreren Requests des Nutzers nicht zwangsläufig gleich bleiben muss, wurde schon oft erwähnt - AOL bspw. hat eine ganze Proxyfarm, über die es die Anfragen seiner Nutzer weiterleitet.

    $query="SELECT user,pwd,bereich,userid FROM all_user WHERE user='$nick'";

    Dieser $nick schon wieder - wer ist der Kerl, und woher kommt er?
    register_globals eigentlich ein Begriff, falls das eine Formularübergabe sein soll?

    Dann vergleiche ich die Session Variablen mit den $r_x variablen.

    Warum denn schon wieder?
    Du hast sie auf der vorherigen Seite doch erst in die Session reingeschrieben?

    gruß,
    wahsaga

    --
    /voodoo.css:
    #GeorgeWBush { position:absolute; bottom:-6ft; }
    1. hi,

      In den letzten Tagen wurde hier soviel über Sessions, Sicherheit und Loginsysteme diskutiert, das es den meisten hier denk ich schon langsam zum Hals raushängt.

      Okay.

      session_start();
      $query="SELECT user,pwd,bereich,userid FROM all_user WHERE user='$nick'";

      Woher kommt $nick?

      Wie gesagt $nick kommt von einem Formular das per POST übergeben wurde, wurde aber schon mysql_real_escape_string() drauf angewendet.

      $num=mysql_query($query,$c) or die (mysql_error());
      $row = mysql_fetch_array($num);
      if(!$row){
      header('Location: fehler.php');
      die();

      Abgesehen davon, dass ein Location-Header per Definition einen absoluten URL inkl. Protokollangabe erfordert -
      Warum eigentlich immer Umleiten?
      Warum nicht die Fehlermeldung innerhalb der gleichen Ressource ausgeben?

      Ich habe eine extra Seite für Feherl anzeigen eigendl. kommt noch ein Paramenter hintendran und fehler.php checkt, welche Meldung er ausgeben soll.

      Warum wieder Umleiten ...?

      Formular -> loginskript -> weiter.php

      Warum denn nicht was soll den sonst passieren? In der Loginskript Datei wird kein (X)HTML ausgegeben.

      // weiter.php sieht so aus:

      session_start ();
      if(!isset ($_SESSION["user_id"])){
      header ("Location: index.php");
      die();

      Warum wieder Umleiten ...?

      Falls die $_SESSION["user_id"] nicht vorhanden ist wird zurück zur Loginseite weitergeleitet.(Mit Parameter für Fehlermeldung)

      }elseif($_SESSION['IP'] != $_SERVER['REMOTE_ADDR']) {

      Dass die IP zwischen mehreren Requests des Nutzers nicht zwangsläufig gleich bleiben muss, wurde schon oft erwähnt - AOL bspw. hat eine ganze Proxyfarm, über die es die Anfragen seiner Nutzer weiterleitet.

      Okay dann kass ich das weg.

      Dann vergleiche ich die Session Variablen mit den $r_x variablen.

      Warum denn schon wieder?
      Du hast sie auf der vorherigen Seite doch erst in die Session reingeschrieben?

      Weil ich doch testen muss ob in der Session das ganze wirklich enthalten ist. Sollte ein wenig dagegen absichern das Leute die den Link kriegen au die Seite können ohne sich vorher einzuloggen.

      Was kann ich denn deiner/euer Meinung nach tun um meine Sicherheitswünsche zu erfüllen?

      mfg

      Peter Strucks

      1. Hallo,

        Wie gesagt $nick kommt von einem Formular das per POST übergeben wurde, wurde aber schon mysql_real_escape_string() drauf angewendet.

        wie wahsaga in einem anderen Thread schon schrieb: daten "kontextabhängig" behandeln (nicht genauer Wortlaut).

        ich gehe mal davon aus, dass du $nick noch öfter verwenden willst (zumindest solltest, ansonsten wäre das für mich eine sinnfreie temporäre variable), und nicht nur um mysql queries damit auszuführen. Ich würde also eher folgendes machen:

          
          $query = sprintf("SELECT user, pwd, bereich, userid FROM all_user WHERE user = %s", mysql_real_escape_string($nick));  
        
        

        damit bleibt $nick erhalten und nur im kontext mit dem query einer mysql datenbank wird es escaped (das hat den weiteren vorteil, dass der krempel zusammen bleibt. Du legst wohl wahrscheinlich auch nicht deine Sachen um Kaffee zu machen in die Garage, ein Teil ins Auto, die Tasse auf den Spielplatz, sondern hast das Zeug schön in der Küche, oder nicht?), und man kann es z.B. noch zur Ausgabe verwenden indem man z.B.

          
          echo htmlescapewieauchimmerdiefunktionheisst($nick);  
        
        

        ansonsten müsstes du hier das mysql_real_escape_string() irgendwie wieder rückgängig machen ...

        gruss

        --
        Swiss Army Chainsaw
        Terrorific!
        VI VI VI - the editor of the beast!
        1. Hi.

          $query = sprintf("SELECT user, pwd, bereich, userid FROM all_user WHERE user = %s", mysql_real_escape_string($nick));

            
          Alles klar hab ich verstanden. =) Danke. Gefixt. Und was zum Rest meines Anliegends?  
            
            
          mfg  
            
          Peter Strucks
          
        2. Begrüßung ('Hallo'),

          $query = sprintf("SELECT user, pwd, bereich, userid FROM all_user WHERE user = %s", mysql_real_escape_string($nick));

            
          Kann mir nebenbei einer von Euch bitte kurz den query erklären? Besonders das %s .  
          Ich wäre Euch sehr dankbar!  
            
          Hatte bzw. habe weiter unten einen ähnlich Thread am laufen und verfolge diesen hier mit hoher Aufmerksamkeit.  
            
          Einiges habe ich auch schon geändert bzw. umgestellt.  
            
          AufWiedersehen ('Vielen Dank'),  
          LG  
          \--  
          kEv\*  
          \----  
          
          -- 
          kevin  
          ![Kevin](http://kevin-dilly.de/data/thumbnails/730de2/thumb_CIMG1421.jpg)  
          geboren am: o8.o7.2oo6  
          Gewicht: 3660g  
          \---  
          SELFCODE:  
          \---  
          sh:( fo:| ch:? rl:° br:^ ie:{ mo:| va:) de:] zu:) ss:| ls:[ js:|  
          \---  
          
          
          1. echo $begrüßung;

            $query = sprintf("SELECT user, pwd, bereich, userid FROM all_user WHERE user = %s", mysql_real_escape_string($nick));
            Kann mir nebenbei einer von Euch bitte kurz den query erklären? Besonders das %s .

            Du möchtest dich vermutlich nur über die Funktion sprintf() informieren. Der Rest ist stinknormales SQL.

            echo "$verabschiedung $name";

        3. Moin!

          $query = sprintf("SELECT user, pwd, bereich, userid FROM all_user WHERE user = %s", mysql_real_escape_string($nick));

            
          Böse Falle! sprintf() ersetzt kein Binding, also muß um den Platzhalter selbstverständlich der Stringbegrenzer gemacht werden: '%s'  
            
           - Sven Rautenberg
          
          -- 
          "Love your nation - respect the others."
          
          1. Hallo,

            Böse Falle! sprintf() ersetzt kein Binding, also muß um den Platzhalter selbstverständlich der Stringbegrenzer gemacht werden: '%s'

            Danke! ich ging davon aus mysql...string täte das, danke für die Korrektur.

            gruss

            --
            Swiss Army Chainsaw
            Terrorific!
            VI VI VI - the editor of the beast!
      2. hi,

        Du hast sie auf der vorherigen Seite doch erst in die Session reingeschrieben?

        Weil ich doch testen muss ob in der Session das ganze wirklich enthalten ist.

        Warum sollten die Werte, die du ermittelt und in die Session hineingeschrieben hast, auf der nächsten Seite nicht mehr drin sein?

        Nutze _einen_ Wert für die Überprüfung.
        Wenn die Anmeldedaten korrekt waren, befülle die Werte, die du später noch brauchst. Wenn bei deren Ermittlung ein Fehler auftritt, reagiere zu diesem Zeitpunkt auf ihn.
        Anschließend setze einen Wert wie bspw. $_SESSION['Login_OK'] auf true.

        _Diesen_ Wert fragst du dann auf den Folgeseiten ab, um zu entscheiden, ob der Nutzer sich ordnungsgemäß angemeldet hat oder nicht.
        Wenn er sich ordnungsgemäß angemeldet hat, hast du auch bereits die restlichen Werte, die du brauchst, ermittelt und in der Session hinterlegt - sie ständig erneut abzuprüfen, ist jetzt im Normalfall nicht mehr nötig.

        Sollte ein wenig dagegen absichern das Leute die den Link kriegen au die Seite können ohne sich vorher einzuloggen.

        Das hat damit nichts zu tun.
        Da ist die Übergabe der Session-ID kritisch - aber das Thema wurde in deinem anderen Thread ja IIRC schon angesprochen.

        gruß,
        wahsaga

        --
        /voodoo.css:
        #GeorgeWBush { position:absolute; bottom:-6ft; }
        1. Hi.

          Nutze _einen_ Wert für die Überprüfung.

          Genau _das_ ist der springende Punkt. Welchen Wert, woraus setze ich ihn am besten zusammen und wie überprüfe ihn am besten.

          Wenn die Anmeldedaten korrekt waren, befülle die Werte, die du später noch brauchst. Wenn bei deren Ermittlung ein Fehler auftritt, reagiere zu diesem Zeitpunkt auf ihn.
          Anschließend setze einen Wert wie bspw. $_SESSION['Login_OK'] auf true.

          _Diesen_ Wert fragst du dann auf den Folgeseiten ab, um zu entscheiden, ob der Nutzer sich ordnungsgemäß angemeldet hat oder nicht.
          Wenn er sich ordnungsgemäß angemeldet hat, hast du auch bereits die restlichen Werte, die du brauchst, ermittelt und in der Session hinterlegt - sie ständig erneut abzuprüfen, ist jetzt im Normalfall nicht mehr nötig.

          Okay super das versteh ich =).

          Da ist die Übergabe der Session-ID kritisch - aber das Thema wurde in deinem anderen Thread ja IIRC schon angesprochen.

          Okay werd ich nochmal nachlesen.

          Wie gesagt ich suche eine Methode wie ich das ganze am betsen Überprüfe. Halt diesen _einen_ Wert oder vllt. auch mehrere Werte zum kontrollieren.

          mfg

          Peter Strucks

          1. hi,

            Nutze _einen_ Wert für die Überprüfung.

            Genau _das_ ist der springende Punkt. Welchen Wert, woraus setze ich ihn am besten zusammen und wie überprüfe ihn am besten.

            Du kannst $_SESSION['Mondkalb'] mit dem Wert 'drei Wodka Tonic' belegen, wenn dir danach ist - und es dann abfragen mit

            if(isset($_SESSION['Mondkalb']) && $_SESSION['Mondkalb'] === 'drei Wodka Tonic') { ... }

            Für den Array-Index möchtest du vielleicht einen etwas sinnvolleren Namen als 'Mondkalb' nehmen, weil Programmierer mit _so_ viel Phantasie bei der Namensgebung idR. nicht allzu weit kommen - sie verstehen höchstvermutlich ihre eigenen Scripte nach einem Monat nicht mehr, weil sie nicht mehr wissen, welcher Unsinns-Name für was steht.
            Und statt 'drei Wodka Tonic' haben sich für das Ablegen einfacher wahr/falsch-Information auch eher true und false bewährt. Explizites Setzen auf false können wir uns hier auch sparen - wenn der Wert noch nicht gesetzt wurde, nehmen wir das auch als nicht erfüllt Bedingung an.

            Also: Tendenziell ist vollkommen egal, welchen Namen und Wert du nimmst.
            Dir sollte lediglich das Prinzip klar sein - es kommen keine Werte durch Zufall in die Session, sondern nur genau die, die du selber hineinschreibst [1].
            Also schreibst du _einen_ Wert da rein - und ziehst dann aus seinem Vorhandensein in bei den zukünftigen Session-Zugriffen deine Schlüsse.

            gruß,
            wahsaga

            [1] Interferrenzen auf Grund der unsäglichen register_globals-Einstellung mal aussen vor gelassen.

            --
            /voodoo.css:
            #GeorgeWBush { position:absolute; bottom:-6ft; }
            1. hi.

              Genau _das_ ist der springende Punkt. Welchen Wert, woraus setze ich ihn am besten zusammen und wie überprüfe ihn am besten.

              Du kannst $_SESSION['Mondkalb'] mit dem Wert 'drei Wodka Tonic' belegen, wenn dir danach ist - und es dann abfragen mit

              if(isset($_SESSION['Mondkalb']) && $_SESSION['Mondkalb'] === 'drei Wodka Tonic') { ... }

              Ist damit das ganze sicher? sollte man das ganze nicht auch noch verschlüsseln am besten direkt hardcodiert:

              $wert=md5(md5(md5("uZn876NM".md5($wert."5xthns")."uhsbx")));

              Sowas dürfte nichtmehr zurückverfolgbar sein. Aber bringt es überhaupt  so etwas so zu machen?

              Ich mein kann nicht jeder einfach meine Sessionid fälschen?

              mfg

              Peter Strucks

              1. hi,

                Ist damit das ganze sicher? sollte man das ganze nicht auch noch verschlüsseln am besten direkt hardcodiert:

                $wert=md5(md5(md5("uZn876NM".md5($wert."5xthns")."uhsbx")));

                Sowas dürfte nichtmehr zurückverfolgbar sein.

                Wer sollte irgdnetwas zurückverfolgen, und wohin?

                Aber bringt es überhaupt  so etwas so zu machen?

                M.E. nein.

                Noch Mal: In einer Session steht das drin, was du (dein Script) hineingegeben hast.

                Und Werte aus einer Session bekommt auch nur dann jemand zu Gesicht, wenn du sie explizit ausgibst.

                Ich mein kann nicht jeder einfach meine Sessionid fälschen?

                Das Thema hatten wir in den letzten Tagen jetzt wirklich mehrfach - Sven hat sich bspw. im Thread SICHERHEIT eines session basierten Login-Systems ausführlich dazu geäussert.

                Ich habe Zweifel, ob du die Funktionsweise von Sessions schon komplett durchdrungen hast - die wiederholten Nachfragen klingen anders.
                Also bemühe dich doch bitte zunächst mal darum.

                gruß,
                wahsaga

                --
                /voodoo.css:
                #GeorgeWBush { position:absolute; bottom:-6ft; }
                1. Hallo.

                  Doch ich habs schon verstanden bis auf eins. WIE <- kann ich das ganze etwas sicherer machen?
                  Oder ich frag einfach mal die Profis hier:
                  wahsaga, Gunnar B., Sven R., Powl, Christoph S., dedlfix,Ingo T., bleicher u.s.w.

                  Ihr habt sicher alle schonmal ein Session-System entworfen. Wie habt ihr das gemacht? Wo habt ihr Sicherheitslücken geschlossen? Und so weiter..

                  mfg

                  Peter Strucks

                  1. hi,

                    Doch ich habs schon verstanden bis auf eins. WIE <- kann ich das ganze etwas sicherer machen?

                    Wir drehen uns langsam im Kreis.

                    Und jetzt gilt auch für dich, was ich in meiner ersten Antwort im Thread erst mal allgemein angemerkt hatte, Zitat:

                    [...] wo denn überhaupt die _Lücken_ ihres bisherigen Aufbaus liegen könnten. Wer diese mal analysiert, dürfte idR. auch schon sehr nahe an ihrer Abstellung und Behebung sein.

                    Also, mach dir bitte darüber Gedanken.
                    Erstelle dir eine Liste - wo siehst du potentielle Probleme was die Sicherheit angeht?
                    Dann bewerte diese - was ist wirklich eine Lücke, was ist doch technisch ausgeschlossen und damit nicht gefährdungsrelevant, ...
                    Recherchiere im Archiv und im www, wenn du nicht selber zu einer Antwort kommst.

                    Wenn du potentielle Lücken identifiziert hast (und Hirngespinste in dieser Hinsicht rausgeworfen), dann überlege dir, wie man sie abstellen könnte. (Auch hier wieder: Zunächst bitte Archiv und www, Danke.)
                    Ob deine Ansätze diesbezüglich sinnvoll und zielführend sind, können wir dann gerne alle gemeinsam einer Bewertung unterziehen.

                    Aber die beständige Wiederholung der ewig gleichen Frage, "wie mache ich X sicher?" - die wird wirklich langsam langweilig.

                    gruß,
                    wahsaga

                    --
                    /voodoo.css:
                    #GeorgeWBush { position:absolute; bottom:-6ft; }
                  2. Moin!

                    Doch ich habs schon verstanden bis auf eins. WIE <- kann ich das ganze etwas sicherer machen?

                    Ich habe da so meine Zweifel, dass du die Session-Mechanismen verstanden hast.

                    Aber ich fang' gern nochmal bei Adam und Eva an. :)

                    Session hat erstmal nichts mit Login und Sicherheit zu tun, sondern bezieht sich nur darauf, dass der Browser bei jedem Request, den er macht, dem Server eine eindeutige Identifikationsmarke mitschickt, an der der Server den Browser wiedererkennt.

                    Als praktikabel hat sich dabei erwiesen, eine möglichst zufällig generierte ID in einem Cookie zu speichern. Alternativ wird diese ID irgendwo in der URL (bei PHP als Parameter, denkbar wäre aber auch irgendwo im Pfad), bzw. in den Formulardaten (bei POST) platziert.

                    Die ID muß zufällig sein, damit man sie nicht vorhersagen kann - das könnte dann nämlich auch ein böser Angreiferbrowser tun, der vom Server dann für den echten Browser gehalten wird.

                    Außerdem muß die ID einen sehr großen Wertebereich haben, damit man nicht durch stupides Ausprobieren aller möglichen ID-Varianten auf gültige Sessions stößt.

                    Bei PHP wird zur Generierung der Session-ID ein langer String gebildet, in dem die IP des Angreifers, die aktuellen Sekunden, die aktuellen Mikrosekunden sowie ein Zufallswert stehen. Dieser String wird durch die Funktion md5() geleitet und ergibt damit eine sehr sichere Session-ID, die nicht vorhersagbar ist, und die aufgrund ihres Wertebereichs auch nicht in vernünftiger Zeit annähernd effektiv durchprobiert werden kann. Ab Version 5.0.0 bietet PHP alternativ die Möglichkeit, den Zufallsstring mit sha1() zu bearbeiten, um einen noch größeren ID-Wertebereich zu erhalten.

                    Auf der Serverseite sorgt der Sessionmechanismus dafür, dass gewisse Werte, die die Anwendung beim ersten Request abgelegt hat, durch Übermittlung der identischen Session-ID auch beim zweiten Request wieder geladen werden und dem Skript zur Verfügung stehen.

                    Von außen kann man auf diese Sessionvariablen, die bei PHP im Array $_SESSION abgelegt werden, keinen Zugriff nehmen. Man kann darin nichts verändern - es sei denn, es ist ein Skript geschrieben, welches diese Variablen verändert, und welches man von außen mißbrauchen kann. Gegen Blödheit des Programmierers kann auch ein sauberer Sessionmechanismus nichts ausrichten.

                    Ihr habt sicher alle schonmal ein Session-System entworfen. Wie habt ihr das gemacht? Wo habt ihr Sicherheitslücken geschlossen? Und so weiter..

                    Ich betrachte den Standardmechanismus der Sessions, den PHP bietet, für vollkommen ausreichend selbst für sicherheitstechnisch anspruchvollere Anwendungen. Ich würde damit vielleicht kein Homebanking programmieren (was aber eher an PHP insgesamt liegt), aber jegliche Art von Shopsystemen, Logins sowie alle Anwendungen, die kein SSL benötigen.

                    Dementsprechend gibt es beim Standardmechanismus auch keine Lücken zu schließen. Hinzuzufügen ist allenfalls ein Mechanismus, der Logins nach einer definierten Zeitdauer ungültig macht, damit das vergessene Logout nicht doch durch Unbefugte, die Zugriff auf den eingeloggten Browser haben, mißbraucht werden kann.

                    Hinsichtlich der Prüfung der Logindaten gibt es zwei Modelle:
                    1. Es wird nur einmalig beim Login geprüft, ob die Zugangsdaten in Ordnung sind. Das Ergebnis der Prüfung wird in den Sessionvariablen abgelegt (typisch: $_SESSION['eingeloggt'] = true;). Im weiteren Verlauf wird nur geprüft, ob diese Variable existiert und true ist. Falls ja, kommt die angeforderte Seite, andernfalls das Loginformular.

                    2. Alternativ wird bei jedem Request (und damit auch schon beim ersten) geprüft, ob die Zugangsdaten korrekt sind. Dazu werden diese in den Sessionvariablen abgelegt und jedesmal mit der Datenbank verglichen. Falls sie korrekt sind, kommt die angeforderte Seite, andernfalls das Loginformular.

                    Methode 1 hat den Vorteil, dass sie mit wenig Datenbankkommunikation auskommt und üblicherweise für einfache Logins mit nur einer Berechtigungsstufe (man kriegt Zugang - oder eben nicht) verwendet wird.

                    Methode 2 hat den Vorteil (und Methode 1 damit den Nachteil!), dass jeder Request immer mit den aktuell gültigen Zugangsdaten geprüft wird. Somit kann man einem User den Zugang in der Datenbank entziehen, und er wird beim nächsten Request seiner laufenden Session sofort keinen Zugang mehr zu den Daten erlangen. Bei Methode 1 bleibt er solange eingeloggt und kann zugreifen, bis die Session verfällt oder er sich ausloggt.

                    Deshalb ist Methode 2 mit mehr Datenbankkommunikation verbunden, und eignet sich, da man die Datenbank ohnehin befragt, tendentiell eher dazu, ein Berechtigungssystem mit mehreren Stufen oder Bereichen zu verwalten. Aber selbstverständlich könnte man auch bei Methode 1 die aus der Datenbank ermittelte komplexere Zugangsberechtigung in die Sessionvariablen schreiben.

                    Und noch eine Bemerkung zum Begriff "Sicherheit": Sicherheit ist ein Prozess, kein Zustand. Man kann nicht hingehen und "ein Skript sicher machen", und dann hinterher sagen "das Skript ist sicher". Einfach weil Sicherheit eine vielschichtige Angelegenheit ist. Auf die Aufforderung "Wie kriege ich das sicher!" muß daher immer die Gegenfrage kommen: "Sicher wogegen?" - die Art des Angriffsszenarios ist entscheidend für die Beantwortung.

                    Außerdem ist Sicherheit auch immer eine Abwägungsfrage. Man kann hochsichere Systeme erstellen - die erfordern dann aber auch extreme Einschränkungen der freien Nutzbarkeit. Das klassische Beispiel ist der einzeln stehende, nicht vernetzte Computer mit den extrem geheimen Daten, der in einem Hochsicherheitsbunker untergebracht ist, und an den man nur mit Fingerabdruck und Irisscan drankommt - siehe den Film "Mission Impossible". An die Daten des Computers kommen Unberechtigte mit extrem hoher Wahrscheinlichkeit nicht heran. Dummerweise kommen auch Berechtigte an die Daten nur unter größeren Mühen heran. Außerdem sind solche Sicherheitsmaßnahmen auch entsprechend teuer.

                    Das zu erzielende Sicherheitsniveau ist daher immer auch von der wirtschaftlichen Betrachtungsweise abhängig. Daten für fünfzig Cent abzusichern mit einem System für hunderttausend Euro ist garantiert unsinniger Overkill.

                    Daten so abzusichern, dass man auch als Berechtigter kaum drankommt, ist unsinnig, wenn die Bequemlichkeit nicht zu stark eingeschränkt werden darf. Überlege dir nur mal, wie viele Kunden ein Internetshop finden würde, wenn man vor dem Kauf erst per PostIdent den Account beantragen muß, und in den man sich nur einloggen kann, wenn man einen Chipkartenleser mit kryptographischer Chipkarte an seinen PC anschließt - und das alles nur, damit Angreifer nicht an eventuell eingetragene Kontodaten oder Kreditkartennummern gelangen können.

                    Natürlich sollte man deshalb nicht leichtfertig Sicherheit verschenken, wenn man sie nahezu kostenlos haben kann, und sie keine Beeinträchtigung der Nutzer darstellt. Andererseits habe ich bei sehr vielen diesbezüglichen Fragen den Eindruck, dass der Fragesteller einfach nur eine unbestimmte Angst hat, irgendetwas Unsicheres zu programmieren - und in Wirklichkeit sind Daten im Wert von 50 Cent bedroht.

                    - Sven Rautenberg

                    --
                    "Love your nation - respect the others."
                    1. Hallo Sven.

                      100000-fachen Dank. Perfekter konntest du mir das garnicht beschreiben. ;)

                      Echt super! *Favoriten Liste hinzufüg*

                      =)

                      Vielen Dank.
                      Schönen Sonntag noch.

                      mfg

                      Peter

                    2. Morgn allerseits.

                      Hätte nur einne Frage. Wie bestimme/veränder ich die Session-ID?

                      Irgendwas mit session_id() oder?

                      cu

                      kev

                      1. Moin!

                        Hätte nur einne Frage. Wie bestimme/veränder ich die Session-ID?

                        Irgendwas mit session_id() oder?

                        Das steht eigentlich alles hier: http://de2.php.net/session-id

                        - Sven Rautenberg

                        --
                        "Love your nation - respect the others."