CVE-2023-4650: Improper Access Control (CWE-284)
value: Improper Access Control in GitHub repository instantsoft/icms2 prior to 2.16.1-git.
CWE description: The product does not restrict or incorrectly restricts access to a resource from an unauthorized actor.
CVSS v3 base score: 4.7
Published: 2023-08-31T01:15Z
Repository: https://github.com/instantsoft/icms2
Language: PHP
Files changed: install/templates/step_php.php, system/controllers/users/actions/profile_edit_password.php, system/controllers/users/actions/profile_edit_sessions.php, system/controllers/users/frontend.php
Commit date: 2023-08-14 14:31:14 +0300
Commit message: Administrators cannot change other administrators' passwords
& #1472
Diff: diff --git a/install/templates/step_php.php b/install/templates/step_php.php
index 6a51cce5c..b4ade5dc1 100755
--- a/install/templates/step_php.php
+++ b/install/templates/step_php.php
@@ -1,8 +1,8 @@
 <h1><?php echo LANG_STEP_PHP_CHECK; ?></h1>
 
-<h2><?php echo LANG_PHP_VERSION; ?></h1>
+<h2><?php echo LANG_PHP_VERSION; ?></h2>
 <p><?php echo LANG_PHP_VERSION_REQ ?></p>
 <table class="grid">
     <tr>
         <td><?php echo LANG_PHP_VERSION_DESC; ?></td>
         <td class="value">
diff --git a/system/controllers/users/actions/profile_edit_password.php b/system/controllers/users/actions/profile_edit_password.php
index d36b1c131..2b7184e58 100755
--- a/system/controllers/users/actions/profile_edit_password.php
+++ b/system/controllers/users/actions/profile_edit_password.php
@@ -6,13 +6,18 @@ class actionUsersProfileEditPassword extends cmsAction {
     protected $extended_langs = ['auth'];
     private $verify_exp = 24;
 
     public function run($profile) {
 
-        // проверяем наличие доступа
+        // Владельцы и админы могут редактировать
         if (!$this->is_own_profile && !$this->cms_user->is_admin) {
-            cmsCore::error404();
+            return cmsCore::error404();
+        }
+
+        // Администраторы тут могут редактировать только свои профили
+        if ($this->cms_user->is_admin && !$this->is_own_profile && $profile['is_admin']) {
+            return cmsCore::error404();
         }
 
         $form = $this->getForm('password', [$profile]);
 
         $ups_key = 'users.change_email_' . md5($profile['email']);
@@ -151,11 +156,11 @@ class actionUsersProfileEditPassword extends cmsAction {
                 if (!$errors) {
 
                     $result = $this->model->updateUser($profile['id'], $profile);
 
                     if ($result['success']) {
-                        
+
                         list($profile, $data, $form) = cmsEventsManager::hook('users_after_edit_password', [$profile, $data, $form]);
 
                         if (!empty($data['password1'])) {
                             $success_text[] = LANG_PASS_CHANGED;
                         }
diff --git a/system/controllers/users/actions/profile_edit_sessions.php b/system/controllers/users/actions/profile_edit_sessions.php
index 64de9d7d1..d21cd8ff3 100755
--- a/system/controllers/users/actions/profile_edit_sessions.php
+++ b/system/controllers/users/actions/profile_edit_sessions.php
@@ -9,10 +9,14 @@ class actionUsersProfileEditSessions extends cmsAction {
         // проверяем наличие доступа
         if (!$this->is_own_profile && !$this->cms_user->is_admin) {
             return cmsCore::error404();
         }
 
+        if ($this->cms_user->is_admin && !$this->is_own_profile && $profile['is_admin']) {
+            return cmsCore::error404();
+        }
+
         return $this->cms_template->render('profile_edit_sessions', [
             'id'       => $profile['id'],
             'profile'  => $profile,
             'sessions' => $this->model->getUserAuthTokens($profile['id'])
         ]);
diff --git a/system/controllers/users/frontend.php b/system/controllers/users/frontend.php
index 885379d6b..2fdc80569 100755
--- a/system/controllers/users/frontend.php
+++ b/system/controllers/users/frontend.php
@@ -233,19 +233,22 @@ class users extends cmsFrontend {
                 'title' => LANG_USERS_EDIT_PROFILE_PRIVACY,
                 'url'   => href_to_profile($profile, ['edit', 'privacy'])
             ];
         }
 
-        $menu[] = [
-            'title' => LANG_SECURITY,
-            'url'   => href_to_profile($profile, ['edit', 'password'])
-        ];
+        if ($this->is_own_profile || (!$profile['is_admin'] && $this->cms_user->is_admin)) {
 
-        $menu[] = [
-            'title' => LANG_USERS_SESSIONS,
-            'url'   => href_to_profile($profile, ['edit', 'sessions'])
-        ];
+            $menu[] = [
+                'title' => LANG_SECURITY,
+                'url'   => href_to_profile($profile, ['edit', 'password'])
+            ];
+
+            $menu[] = [
+                'title' => LANG_USERS_SESSIONS,
+                'url'   => href_to_profile($profile, ['edit', 'sessions'])
+            ];
+        }
 
         list($menu, $profile) = cmsEventsManager::hook('profile_edit_menu', [$menu, $profile]);
 
         return $menu;
     }

Vulnerable code: <h2><?php echo LANG_PHP_VERSION; ?></h1>
        // проверяем наличие доступа
            cmsCore::error404();
                        
        $menu[] = [
            'title' => LANG_SECURITY,
            'url'   => href_to_profile($profile, ['edit', 'password'])
        ];
        $menu[] = [
            'title' => LANG_USERS_SESSIONS,
            'url'   => href_to_profile($profile, ['edit', 'sessions'])
        ];
Fixed code: <h2><?php echo LANG_PHP_VERSION; ?></h2>
        // Владельцы и админы могут редактировать
            return cmsCore::error404();
        }

        // Администраторы тут могут редактировать только свои профили
        if ($this->cms_user->is_admin && !$this->is_own_profile && $profile['is_admin']) {
            return cmsCore::error404();

        if ($this->cms_user->is_admin && !$this->is_own_profile && $profile['is_admin']) {
            return cmsCore::error404();
        }

        if ($this->is_own_profile || (!$profile['is_admin'] && $this->cms_user->is_admin)) {
            $menu[] = [
                'title' => LANG_SECURITY,
                'url'   => href_to_profile($profile, ['edit', 'password'])
            ];

            $menu[] = [
                'title' => LANG_USERS_SESSIONS,
                'url'   => href_to_profile($profile, ['edit', 'sessions'])
            ];
        }