CVE-2021-25970 (published 2021-10-20T12:15Z)

Camaleon CMS 0.1.7 to 2.6.0 doesn’t terminate the active session of the users, even after the admin changes the user’s password. A user that was already logged in, will still have access to the application even after the password was changed.

Severity: MEDIUM
CVSS v2 base score: 6.8 (AV:N/AC:M/Au:N/C:P/I:P/A:P)
CVSS v3 base score: 8.8, HIGH (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-613
cwe_name: Insufficient Session Expiration
description: According to WASC, "Insufficient Session Expiration is when a web site permits an attacker to reuse old session credentials or session IDs for authorization."
extended_description: 
            
            
            
         
         

Fix information:
repo_url: https://github.com/owen2345/camaleon-cms
commit_details: repo_url: https://github.com/owen2345/camaleon-cms
author: Brian Kephart
author_date: 2021-09-30 20:02:25-05:00
msg: Logout user on password change, except in the session making the change
repository: repo_url: https://github.com/owen2345/camaleon-cms
repo_name: owen2345/camaleon-cms
description: Camaleon CMS is a dynamic and advanced content management system based on Ruby on Rails
repo_language: Ruby
owner: owen2345
file_changes: filename: users_controller.rb
change_type: ModificationType.MODIFY
diff: @@ -46,7 +46,22 @@ class CamaleonCms::Admin::UsersController < CamaleonCms::AdminController
   # update som ajax requests from profile or user form
   def updated_ajax
     @user = current_site.users.find(params[:user_id])
-    render inline: @user.update(params.require(:password).permit!) ? "" : @user.errors.full_messages.join(', ')
+    update_session = current_user_is?(@user)
+    @user.update(params.require(:password).permit!)
+    render inline: @user.errors.full_messages.join(', ')
+    # keep user logged in when changing their own password
+    update_auth_token_in_cookie @user.auth_token if update_session && @user.saved_change_to_password_digest?
+  end
+
+  def update_auth_token_in_cookie(token)
+    return unless cookie_auth_token_complete?
+    current_token = cookie_split_auth_token
+    updated_token = [token, *current_token[1..-1]]
+    cookies[:auth_token] = updated_token.join("&")
+  end
+
+  def current_user_is?(user)
+    user_auth_token_from_cookie == user.auth_token rescue false
   end
 
   def edit

programming_language: Ruby
filename: session_helper.rb
change_type: ModificationType.MODIFY
diff: @@ -120,11 +120,21 @@ module CamaleonCms::SessionHelper
     @cama_current_user = cama_calc_api_current_user
     return @cama_current_user if @cama_current_user
 
-    return nil unless cookies[:auth_token].present?
-    c = cookies[:auth_token].split("&")
-    return nil unless c.size == 3
+    return nil unless cookie_auth_token_complete?
 
-    @cama_current_user = current_site.users_include_admins.find_by_auth_token(c[0]).try(:decorate)
+    @cama_current_user = current_site.users_include_admins.find_by_auth_token(user_auth_token_from_cookie).try(:decorate)
+  end
+
+  def cookie_auth_token_complete?
+    cookie_split_auth_token&.size == 3
+  end
+
+  def cookie_split_auth_token
+    cookies[:auth_token]&.split("&")
+  end
+
+  def user_auth_token_from_cookie
+    cookie_split_auth_token.first
   end
 
   # check if a visitor was logged in

programming_language: Ruby
filename: user_methods.rb
change_type: ModificationType.MODIFY
diff: @@ -11,6 +11,8 @@ module CamaleonCms::UserMethods extend ActiveSupport::Concern
     before_destroy :reassign_posts
     after_destroy :reassign_comments
     before_create { generate_token(:auth_token) }
+    # invaliidate sessions when changing password
+    before_update { generate_token :auth_token if will_save_change_to_password_digest? }
 
     # relations
     cama_define_common_relationships('User')

programming_language: Ruby