PHP Cookie & Session Sicherheit

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    • PHP Cookie & Session Sicherheit

      Ich arbeite zurzeit an einem Control Panel und möchte meinen Usern die größtmögliche Sicherheit bieten, ich bin auf der Suche nach einer sicheren Kombination von Cookies und Sessions.
      Für den Anfang benutze ich im Moment nur Cookies und das darf auf keinen Fall so bleiben und deswegen brauche ich eure Tipps und Vorschläge.

      Nur Sessions würde auch nicht infrage kommen da der Login bestehen bleiben soll wenn der User die Seite verlässt.
      Ich habe über die Möglichkeit nachgedacht den Usernamen nach einem eigenen Algorithmus zu verschlüsseln bzw zu Salten und beim aufrufen der Seite abzufragen. Das wiederum würde einen Cookie benötigen der gefälscht werden kann.
      Ich bin auf eure Tipps und Vorschläge gespannt und hoffe jemand kann mir helfen.

      Gruß,
      require
    • Servus @require:

      Hier ist mal ein kleiner Lösungsansatz von mir. Ich benutze eine etwas andere Methode als diese aber Sie ist im Grundegenommen dasselbe.
      Falls du weitere Fragen hast, zögere nicht zu Fragen.

      PHP-Quellcode

      1. session_start();
      2. # Falls diese Anweisung nicht aufgerufen wird, ist der "Benutzer" nicht eingeloggt.
      3. if(!isset($_SESSION["securityToken"])):
      4. # Session überprüfen (IP Check ist hier vom Vorteil)
      5. $clientIP = $_SERVER["REMOTE_ADDR"];
      6. $userName = $_SESSION["username"];
      7. $securityToken = md5(sha1($clientIP . $userName));
      8. $currentTimestamp = time();
      9. $mysqlConnection = new PDO('mysql:host=dbname=DATENBANK;host=127.0.0.1;charset=utf8', 'username', 'passwort');
      10. $result = $mysqlConnection->query("SELECT * FROM `sessions` WHERE `sessionID` = "$securityToken" AND `time` > $currentTimestamp AND `clientIP` = "$clientIP"");
      11. if($result->rowCount() >= 1):
      12. # Er ist noch eingeloggt (Update den Timestamp damit er die Seite weiterhin nutzen kann
      13. $currentTimestamp += 600; # 10 Minuten (in Sekunden)
      14. $mysqlConnection->exec("UPDATE `sessions` SET `time` = $currentTimestamp WHERE `sessionID` = "$securityToken"");
      15. else:
      16. # Er ist nichtmehr eingeloggt
      17. session_unset();
      18. endif;
      19. endif;
      20. session_destroy();
      Alles anzeigen


      //EDIT: Da der PHP Quellcode keine \ erlaubt, musst du diese selbstständig bei den Querys / Updates einfügen.
      //EDIT2: Bitte beachte, dass du deine vorhandene Datenbankverbindung verwendest um die Ladezeit gering zu halten. (Kommt hierbei auf deinem Hoster / Anbieter an)

      Es ist nur ein Beispiel. Dieses kann man noch etwas besser aufbauen.

      Mit freundlichem Gruß
      LuXorioN

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von LuXorioN ()

    • Für einen Anmeldevorgang solltest du Cookies verwenden, da machen Sessions nur wenig sinn.
      Prinzipiell solltest du einfach eine zufällige Zeichenkette generieren und diese als Cookie abspeichern.
      Der Client identifiziert sich dann mit dieser Zeichenkette und erhält Zugriff.
      Um zu verhindern, dass die Session gestohlen wird (kann bspw. durch ein von Angreifern eingebettetes JavaScript passieren), solltest du IP und UserAgent mit der Zeichenkette speichern und dementsprechend überprüfen.
    • Servus erneut :D
      Hier ist nochmals ein etwas besseres Beispiel. Danke hierfür an @Laerik: für diesen kleinen Hinweis mit dem User Agent. Den muss ich in der Nacht wohl übersehen haben :D

      PHP-Quellcode

      1. if(isset($_COOKIE["securityToken"])):
      2. $clientIP = $_SERVER["REMOTE_ADDR"];
      3. $userAgent = $_SERVER["HTTP_USER_AGENT"];
      4. $currentTimestamp = time();
      5. $securityToken = md5($clientIP . $userAgent);
      6. $mysqlConnection = new PDO('mysql:host=dbname=DATENBANK;host=127.0.0.1;charset=utf8', 'username', 'passwort');
      7. $result = $mysqlConnection->query("SELECT * FROM `sessions` WHERE `sessionID` = "$securityToken"");
      8. if($result->rowCount() >= 1):
      9. $fields = $result->fetch(PDO::FETCH_ASSOC);
      10. if($currentTimestamp < $fields->time):
      11. # Er ist noch eingeloggt. (Token update)...
      12. $currentTimestamp += 600;
      13. setcookie("securityToken", $securityToken, $currentTimestamp);
      14. $mysqlConnection->exec("UPDATE `sessions` SET `time` = $currentTimestamp WHERE `sessionID` = "$securityToken"");
      15. else:
      16. # Er ist noch eingeloggt aber die Zeit wurde überschritten.
      17. $mysqlConnection->exec("DELETE FROM `sessions` WHERE `sessionID` = "$securityToken"");
      18. $notLoggedin = true;
      19. endif;
      20. else:
      21. # Es wurde kein Eintrag in der Datenbank gefunden -> Reset
      22. $notLoggedin = true;
      23. endif;
      24. if($notLoggedin):
      25. #Löscht alle Cookies für den aktuellen Domain.
      26. if (isset($_SERVER['HTTP_COOKIE'])):
      27. $cookies = explode(';', $_SERVER["HTTP_COOKIE"]);
      28. foreach($cookies as $cookie):
      29. $parts = explode('=', $cookie);
      30. $name = trim($parts[0]);
      31. setcookie($name, '', -1);
      32. endforeach;
      33. endif;
      34. endif;
      35. endif;
      Alles anzeigen


      HINWEIS: Dies ist nur ein Beispiel welches nicht getestet worden ist!

      Wieimmer: Solltest du Fragen haben, frag ruhig :)


      Mit freundlichem Gruß
      LuXorioN
    • Da habt ihr mich wohl missverstanden, die IP-Adresse und der User-Agent sollten zusätzlich zur SID in der Datenbank gespeichert werden, um Session-Diestbahl zu verhindern.
      Wie die SID generiert wird, ist irrelevant, solange dies zufällig geschieht.
      Ich würde die SID nicht aus IP und UA generieren, wieso nicht einfach mit uniqid() oder rand() etwas zufälliges generieren und daraus einen Hash bilden?

      Im Endeffekt ist es völlig egal, ob die SID super sicher generiert worden ist, solange sichergestellt ist, dass niemand anders sie nutzen kann.
      Da man aber bspw. in einem großen Netzwerk (VPNs sind ja momentan im Trend) schnell die gleiche IP hat, ist nur noch der UA unterschiedlich.
      Deshalb sollte die SID nicht zu erraten sein.
    • PHP-Quellcode

      1. # Token erstellen (generieren) - Beim Login
      2. $securityToken = md5(sha1(uniqid(microtime() . rand(1, 999999) . $userAgent . $clientIP)));
      3. setcookie("securityToken", $securityToken, time() + 600, '/');
      4. # Login / Session Checks
      5. if(isset($_COOKIE["securityToken"])):
      6. $myToken = $_COOKIE["securityToken"];
      7. # IP und Useragent überprüfen...
      8. endif;
    • Ich hab mal eben das Beispiel von LuXorioN überarbeitet, so wie Laerik es sagte.

      Es wäre es sinnvoller nur die 2-3 ersten Blöcke der IP-Adresse zu überprüfen, da viele Nutzer eine dynamische IP besitzen (IP-Adresse ändert sich nach einer Zeit).

      Ausserdem sollte die IP-Adresse nicht direkt aus $_SERVER['REMOTE_ADDR'] genutzt werden.
      Es ist nämlich möglich mit dem X-Forwared-For Header eine beliebige IP zu übermitteln (ex. X-Forwared-For: 8.8.8.8).
      $_SERVER['REMOTE_ADDR'] würde nun 8.8.8.8 ausgeben, obwohl ich eine ganz andere IP habe.


      PHP-Quellcode

      1. if (isset($_COOKIE["securityToken"]) && !empty($_COOKIE["securityToken"])) {
      2. $clientIP = getRealIP();
      3. $userAgent = $_SERVER["HTTP_USER_AGENT"];
      4. $currentTimestamp = time();
      5. $securityToken = $_COOKIE["securityToken"];
      6. $mysqlConnection = new PDO('mysql:host=dbname=DATENBANK;host=127.0.0.1;charset=utf8', 'username', 'passwort');
      7. $result = $mysqlConnection->query("SELECT * FROM `sessions` WHERE `sessionID` = '".$securityToken."'");
      8. if ($result->rowCount() >= 1) {
      9. $fields = $result->fetch(PDO::FETCH_ASSOC);
      10. $dbUID = $fields->UID;
      11. $dbIP = $fields->IP;
      12. $dbUserAgent = $fields->UserAgent;
      13. $expIP = explode(".", getRealIP());
      14. $expDbIP = explode(".", $dbIP);
      15. if ($expIP[0] == $expDbIP[0] && $expIP[1] == $expDbIP[1] && $expIP[2] == $expDbIP[2]) {
      16. if ($dbUserAgent == $userAgent) {
      17. $isLoggedin = true;
      18. }
      19. }
      20. }
      21. }
      22. function getRealIP() {
      23. $ip = $_SERVER['REMOTE_ADDR'];
      24. if (!empty($_SERVER['HTTP_CLIENT_IP'])) { //check ip from share internet
      25. $ip = $_SERVER['HTTP_CLIENT_IP'];
      26. } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { //to check ip is pass from proxy
      27. $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
      28. }
      29. return $ip;
      30. }
      31. # Hier mal kurz, wie man den Login lösen könnte
      32. $userID = ...
      33. $sessionID = hash('sha256', uniqid().rand(999999999));
      34. $clientIP = getRealIP();
      35. $userAgent = $_SERVER["HTTP_USER_AGENT"];
      36. setcookie("securityToken", $sessionID, "/");
      37. /*
      38. MySQL-Query:
      39. INSERT INTO sessions (uID, sessionID, IP, UserAgent) VALUES ('".$userID."', '".$sessionID."', '".$clientIP."', '".$userAgent."')
      40. */
      Alles anzeigen



      LG
      Lars
      *** User Panel für Vio Lite / Extended / Ultimate ***
      who | grep -i hot && grep -i female | date; cd ~; unzip; touch; strip; finger; mount; gasp; yes; uptime; umount; sleep