/** * Initialize PHP session and do security checks to prevent session stealing. */ private static function initPHPSession() { //start PHP session session_write_close(); session_start(); self::debug("initPHPSession: PHPSESSID=" . session_id()); //1. check client's identifier code //we make sure that who created the session is the one who resumes it. $sSessionIdentifier = self::calculateSessionIdentifier(); if (AnwEnv::_SESSION(self::PHPSESSION_IDENTIFIER) && $sSessionIdentifier == AnwEnv::_SESSION(self::PHPSESSION_IDENTIFIER)) { //2. check session code //just to make it harder, even if someone who steals PHPSESSID would probably steal the session code too. if (AnwEnv::_SESSION(self::PHPSESSION_CODE) && AnwEnv::_COOKIE(self::COOKIE_PHPSESSION_CODE) && AnwEnv::_SESSION(self::PHPSESSION_CODE) == AnwEnv::_COOKIE(self::COOKIE_PHPSESSION_CODE)) { //allright, session seems safe to work with self::debug("initPHPSession: OK, resuming PHP session (" . session_id() . ")"); return; } else { self::debug("initPHPSession: WARNING: no valid PHP session: bad session code"); } } else { self::debug("initPHPSession: no valid PHP session: bad or missing session identifier"); } //no valid session found self::debug("initPHPSession: no valid PHP session found, starting a new session (" . session_id() . ")"); //clear session data if (is_array($_SESSION)) { foreach ($_SESSION as $i => $v) { AnwEnv::unsetSession($i); } } //start a new session and delete old phpsession file session_regenerate_id(true); //set the session identifier, for next hit AnwEnv::putSession(self::PHPSESSION_IDENTIFIER, $sSessionIdentifier); //generate a session code $sSessionCode = self::generateSessionCode(); AnwEnv::putCookie(self::COOKIE_PHPSESSION_CODE, $sSessionCode); AnwEnv::putSession(self::PHPSESSION_CODE, $sSessionCode); }
private function saveSession($oSession, $bCreateSessionIfNotExists = false) { $sSessionId = $oSession->getId(); if ($oSession->isLoggedIn()) { //purge the old sessions from database (needed for the update/insert test) $this->purgeExpiredSessionsFromDatabase(); //try to update session in database (if it already exists) $sSessionIdentifier = AnwEnv::calculateSessionIdentifier(); $sSessionCode = self::generateSessionCode(); //a new code is generated (even if session already exists) to prevent session stealing $nSessionUser = $oSession->getUser()->getId(); $sSessionResume = $oSession->isResume() ? 1 : 0; $nSessionTimeSeen = time(); $asData = array("SessionIdentifier" => $this->db()->strtosql($sSessionIdentifier), "SessionCode" => $this->db()->strtosql($sSessionCode), "SessionUser" => $this->db()->inttosql($nSessionUser), "SessionResume" => $this->db()->strtosql($sSessionResume), "SessionTimeSeen" => $this->db()->inttosql($nSessionTimeSeen)); $this->db()->do_update($asData, "session", "WHERE SessionId=" . $this->db()->strtosql($sSessionId)); //otherwise, we may need to INSERT this new session or to kill it if ($this->db()->affected_rows() != 1) { if ($bCreateSessionIfNotExists) { //user is logging in, it's normal that the session doesn't exist in database. $asData["SessionId"] = $this->db()->strtosql($sSessionId); $asData["SessionTimeStart"] = $this->db()->inttosql(time()); $asData["SessionTimeAuth"] = $this->db()->inttosql(time()); $this->db()->do_insert($asData, "session"); } else { //here, the session is supposed to exist in database, but isn't found. //this can happend in the following situations: // - The session has expired (DurationIdle or DurationMax) // - An user was using a session, when someone tried to steal it. The session was killed for security reasons. // - An administrator has killed the session. // - The session has expired. //In both situations, the current session is no longer safe and must be closed. self::debug("WARNING: Session doesn't exist in database, but session creation is NOT expected. Logging out."); AnwCurrentSession::logout(); return; } } //remember current session in cookies $nCookieExpires = AnwSessions::isResumeEnabled() && $oSession->isResume() ? time() + $this->cfgResumeDelayMax() : 0; AnwEnv::putCookie(self::COOKIE_SESSION_ID, $sSessionId, $nCookieExpires); AnwEnv::putCookie(self::COOKIE_SESSION_CODE, $sSessionCode, $nCookieExpires); AnwEnv::putSession(self::SESSION_CODE, $sSessionCode); } else { //unset cookies AnwEnv::unsetCookie(self::COOKIE_SESSION_ID); AnwEnv::unsetCookie(self::COOKIE_SESSION_CODE); } }