CVE-2023-4649: Session Fixation (CWE-384)
value: Session Fixation in GitHub repository instantsoft/icms2 prior to 2.16.1.
CWE description: Authenticating a user, or otherwise establishing a new user session, without invalidating any existing session identifier gives an attacker the opportunity to steal authenticated sessions.
CVSS v3 base score: 5.4
Published: 2023-08-31T01:15Z
Repository: https://github.com/instantsoft/icms2
Language: PHP
Files changed: system/core/config.php, system/core/user.php
Commit date: 2023-08-16 00:47:41 +0300
Commit message: Add session regenerate after login & logout. Secure cookie if HTTPS.
close #1473
Diff: diff --git a/system/core/config.php b/system/core/config.php
index 4035c6949..df448bef8 100755
--- a/system/core/config.php
+++ b/system/core/config.php
@@ -142,11 +142,11 @@ class cmsConfig extends cmsConfigs {
             $host = empty($url_parts['path']) ? $this->host : $url_parts['scheme'] . '://' . $url_parts['host'];
             $this->upload_host = str_replace($host, '', $this->upload_host);
             $replace_upload_host_protocol = true;
         }
 
-        $this->set('document_root', rtrim(PATH, $this->root));
+        $this->set('document_root', preg_replace('#(.*)('.preg_quote($this->root).')$#u', '$1', PATH . DIRECTORY_SEPARATOR));
         $this->set('root_path', PATH . DIRECTORY_SEPARATOR);
         $this->set('system_path', $this->root_path . 'system/');
         $this->set('upload_path', $this->document_root . $this->upload_root);
         $this->set('cache_path', $this->document_root . $this->cache_root);
 
diff --git a/system/core/user.php b/system/core/user.php
index 408665f4d..c7466d509 100755
--- a/system/core/user.php
+++ b/system/core/user.php
@@ -263,10 +263,12 @@ class cmsUser {
 
         $user = cmsEventsManager::hook('user_login', $user);
 
         self::setUserSession($user, $user['ip']);
 
+        self::sessionRegenerate();
+
         return intval($user['id']);
     }
 
     /**
      * Авторизует пользователя
@@ -341,10 +343,12 @@ class cmsUser {
         $model->updateUserIp($user['id']);
 
         self::getInstance()->id = $user['id'];
         self::getInstance()->is_logged = true;
 
+        self::sessionRegenerate();
+
         return true;
     }
 
     /**
      * Выход пользователя
@@ -382,10 +386,12 @@ class cmsUser {
             self::$auth_token = null;
         }
 
         self::sessionUnset('user');
 
+        self::sessionRegenerate();
+
         return true;
     }
 
 //============================================================================//
 //============================================================================//
@@ -484,10 +490,23 @@ class cmsUser {
         if ($session_time_zone && $session_time_zone !== $config->time_zone) {
             $config->set('time_zone', $session_time_zone);
         }
     }
 
+    public static function sessionRegenerate() {
+
+        session_regenerate_id(false);
+
+        $id = session_id();
+
+        session_write_close();
+
+        session_id($id);
+
+        session_start();
+    }
+
     public static function sessionSet($key, $value) {
 
         if (strpos($key, ':') === false) {
             $_SESSION[$key] = $value;
         } else {
@@ -566,11 +585,11 @@ class cmsUser {
             return setcookie('icms[' . $key . ']', $value, [
                 'expires'  => time() + $time,
                 'path'     => $path,
                 'domain'   => $domain,
                 'samesite' => 'Lax',
-                'secure'   => false,
+                'secure'   => cmsConfig::isSecureProtocol(),
                 'httponly' => $http_only
             ]);
         }
     }
 

Vulnerable code:         $this->set('document_root', rtrim(PATH, $this->root));
                'secure'   => false,
Fixed code:         $this->set('document_root', preg_replace('#(.*)('.preg_quote($this->root).')$#u', '$1', PATH . DIRECTORY_SEPARATOR));
        self::sessionRegenerate();

        self::sessionRegenerate();

        self::sessionRegenerate();

    public static function sessionRegenerate() {

        session_regenerate_id(false);

        $id = session_id();

        session_write_close();

        session_id($id);

        session_start();
    }

                'secure'   => cmsConfig::isSecureProtocol(),