phpbar.de logo

Mailinglisten-Archive

[php] Sicherheitsloch in meiner Sessionfunktion?

[php] Sicherheitsloch in meiner Sessionfunktion?

Garvin Hicking garvin_(at)_atrava.de
01 Feb 2001 20:02:00 +0100


Hi!

(Entschuldigt bitte das "CrossPost" dieser Mail von der PHP-Newsgroup,  
aber ich hoffe, daß mir in einer der beiden Foren jemand helfen kann...)

Vor schon etwas längerer Zeit habe ich eine Seite entwickelt, die anfangs
eine kleine Sessionverwaltung haben sollte, nur um für eingeloggte User
ein paar Links darzustellen. Über die Zeit ist das ganze nun etwas
gewachsen, jedoch setzt die Session-Funktionalität immer noch auf meine
ganz alten Funktionen auf. Damals habe ich mich gegen den Einsatz von
PHPLib entschieden, weil ich etwas dazulernen wollte.

Nun habe ich heute von einen meiner Betatester etwas schreckliches gehört:
Jemand meinte, er habe die Seite ganz normal aufgerufen, und sei in die
gültige Session eines anderen Benutzers reingelangt. Ohne irgendwo
Benutzerkennung und Passwort einzugeben, wurde dem Benutzer angezeigt, er
wäre als Benutzer XYZ eingelogged. Momentan bin ich echt ratlos, was ich
da falsch gemacht haben könnte.

Als Webserver ist Apache 1.3.14 im Einsatz, als PHP-Version die 4.0.4pl1.
Ein Auszug aus der php.ini:

--> php.ini <--
safe_mode=Off
max_execution_time=30
memory_limit=8M
variables_order="EGPCS"
register_globals=On
register_argc_argv=On
magic_quotes_gpc=On
magic_quotes_runtime=Off
magic_quotes_sybase=Off
session.save_handler=files
session.save_path=/tmp
session.use_cookies=1
session.name=SID
session.auto_start=0
session.cookie_lifetime=0
session.cookie_path=/
session.cookie_domain=
session.serialize_handler=php
session.gc_probability=1
session.gc_maxlifetime=1440
session.referer_check=
session.entropy_length=0
session.entropy_file=
session.cache_limiter=nocache
session.cache_expire=180
session.use_trans_sid=0
<----------------------------->

Hier habe ich jetzt noch einen kurzen Auszug aus meinen Scripten, die
eigentlich alles meiner Benutzererkennung ausmachen. Prinzipiell verläßt
sich alles darauf, ob eine Variable $user["auth"] auf "true" gesetzt ist,
und diese Variable wird ja in der Session-Datei gespeichert. D.h.
eigentlich dürfte man nur als eingeloggter Benutzer erkannt werden wenn:

1. Man eine Session-ID vorweist, in der PHP bereits die Variable auf true
gesetzt hat oder

2. Man eine Session-ID besitzt, der man im laufe der Session diese
Variable zugewiesen hat. Letzteres ist nur durch meine Skripte möglich,
und eigentlich durch Eingriffe von aussen geschützt.

Meine Scripts sind jetzt nicht wirklich das bombensicherste, weil ich z.B.
häufig Globale-Variablen verwendet habe. Aber das habe ich wenigstens
konsequenz gemacht, und vorige Get/Post-Variablen immer gelöscht.

Der Benutzer, der mir berichtete, den Zugriff auf jemand anders zu haben,
hatte die Seite vorher schonmal besucht, und hat vermutlich auch schon
einen Cookie von der Seite erhalten...kann es nun irgendwie sein, daß ihm
eine Session-ID eines noch gültigen Users (also unter der gc_maxlifetime)
von PHP oder dem Zufallsgenerator zugewiesen wurde? Oder sind meine
Routinen so fehleranfällig/sicherheitslöchig, daß es dazu kommen mußte?

Ich wäre wahnsinnig dankbar, wenn mir jemand einen Tip geben könnte, denn
so ein riesiges Loch hat ja keiner gerne in seinen Seiten. ;)

Hier meine Code-Schnippsel:


<-- INDEX.PHP -->
unset($user);
session_start();

include "FUNKTIONEN.PHP";

echo "<body>";
Menu($user, $HTTP_COOKIE_VARS);
echo "</body>";
echo "</html>";
<------------------------------------------------------------------->

<-- FUNKTIONEN.PHP -->
function Menu($user, $HTTP_COOKIE_VARS) // HTML-Menu erstellen.
{
   // Standard-Kopf einer HTML-Seite (Menu) ausgeben

   if ($user["usermail"] != "")
   {
      echo $user["usermail"];
      // Ausgabe der Benutzerkennung im Menu, falls
      // Benutzer schon eingelogged.
   }
    elseif (isset($HTTP_COOKIE_VARS["account"])
       // Wenn der Benutzer nicht eingelogged ist, aber ein
       // Cookie auf den Benutzernamen gesetzt wurd, wird
       // dieser ausgegeben
   {
      echo $HTTP_COOKIE_VARS["account"];
   }

   $reauth = "false";
      // Re-Authorisierung soll erstmal nicht erforderlich
      // sein

   if ($user["auth"] == "true")
      // Dies ist meine Haupt-Session-Variable, sie
      // beschreibt ob ein User eingelogged ist oder nicht.
   {
      $zeit = authtime($user["usermail"]);
      // Diese Funktion prueft, ob der Benutzer schon
      // laenger als 10 Minuten inaktiv war.

      if ($zeit[2] == "true")
      // Falls diese Zeit noch nicht erreicht wurde, wird
      // der aktuelle Timestamp neu gesetzt.
      {
         authsettime($user["usermail"]);
         // Timestamp neusetzen
      }
       else
      {
         $user["auth"] = "false";
         // Benutzer muss sich neu authentifizieren.
         session_register("user");
         // Session-Variable speichern
         $reauth = "true";
         // Re-Authorisierung ist notwendig.
      }
   }

   if ($user["auth"] == "true")
   // Falls der Benutzer nun noch als eingelogged anerkannt
   // wird, einige Benutzerspezifische Daten ausgeben...
   {
      // Spezielle Links darstellen, die nur fuer
      // eingeloggte Benutzer gelten.
   }

   if ($reauth == "true")
      // Falls Re-Authorisation notwendig ist...
   {
      login($user, "index.php", "index-user.php", "Login");
   }
}

function login($user, $start, $root, $text)
// Login-Fenster anzeigen. Returns $page (ARRAY)
{
   $user["targetpage"] = $target; // Zielseite sichern
   $user["rootpage"] = $root;     // Quellseite sichern

   session_register("user");

   // Formular mit Feldern fuer Userkennung und Passwort einblenden.
   // Formular zeigt auf TRANSFER.PHP

   if ($user["loginerror"] != "")
   // Falls ein voriger Login schon stattfand und Fehler beinhaltete,
   // diesen nun anzeigen und loeschen.
   {
      // Vorige Fehlermeldung ausgeben

      unset($user["loginerror"]);
      // Fehlermeldung loeschen
      session_register("user");
      // Geloeschte Fehlermeldung speichern. ;)
   }
}

<------------------------------------------------------------------->

<-- TRANSFER.PHP -->
ignore_user_abort(true);
unset($user);
// Verhindern, dass die Variable irgendwie auf die Datei "getrickst"
// wird.
session_start();
setcookie("account", $HTTP_POST_VARS["usermail"], time()+time(), "/");
// Usernamen vom Login-Formular im Cookie sichern.

$user["usermail"] = $HTTP_POST_VARS["usermail"];
// Variable vom HTML-Formular speichern.
$target = $user["targetpage"];

$val = validate($user["usermail"], $HTTP_POST_VARS["passwort"]);
// Login auf Gueltigkeit pruefen. Gibt Array zurueck. Index 0 enthält
// true|false und Index 1 die Benutzer-ID

if ($val[0] == "true")
{
   $user["id"] = $val[1];
   // BenutzerID sichern
   $user["auth"] = "true";
   // Benutzer als gueltig anerkennen
   authsettime($HTTP_POST_VARS["usermail"]);
   // Den Timestamp des Benutzers auf aktuelle Zeit setzen
   session_register("user");
   // Sessionvariablen speichern
   header("Location: $target");
   // Umleitung auf zielseite
}
 else
{
   switch($val[0])
   // Wenn der Benutzer nicht gueltig validiert wurde
   {
      case "noemail":
      // Keine gueltige E-Mail Adresse gegeben
         $user["auth"] = false;
         $target = $user["rootpage"];
         $page["error"] = "Keine E-Mail Adresse";
         session_register("user");
         header("Location: $target");
         break;

      case "nopassword":
      // Kein gueltiges Passwort
         $user["auth"] = false;
         $target = $user["rootpage"];
         $page["error"] = "Kein gueltiges Passwort";
         session_register("user");
         header("Location: $target");
         break;

      default:
         $user["auth"] = false;
         $target = $user["rootpage"];
         $page["error"] = "Keine Uebereinstimmung";
         session_register("user");
         header("Location: $target");
         break;
   }
}

ignore_user_abort(false);
<------------------------------------------------------------------->

<-- LOGOUT.PHP -->
session_start();
setcookie(session_name(), "", 0, "/");
setcookie("account", $user["usermail"], time()+time(), "/");
session_destroy();
header("Location: index.php");
<------------------------------------------------------------------->

(Danke an alle, die die Mail bis hierhin gelesen haben. :-)

-- 
Bye                   .:~~[  Atrava Design & Computer  ]~~:.
                      |   Garvin Hicking - ICQ 21392242    |
 Garvin.              `....[   http://www.atrava.de/  ]....'



php::bar PHP Wiki   -   Listenarchive