CVE-2022-2023 (published 2022-06-20T04:15Z)

Incorrect Use of Privileged APIs in GitHub repository polonel/trudesk prior to 1.2.4.

Severity: HIGH
CVSS v2 base score: 7.5 (AV:N/AC:L/Au:N/C:P/I:P/A:P)
CVSS v3 base score: 9.8, CRITICAL (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-269
cwe_name: Improper Privilege Management
description: The product does not properly assign, modify, track, or check privileges for an actor, creating an unintended sphere of control for that actor.
extended_description: 
            
         
         

Fix information:
repo_url: https://github.com/polonel/trudesk
commit_details: repo_url: https://github.com/polonel/trudesk
author: Chris Brame
author_date: 2022-06-07 23:57:07-04:00
msg: fix(accounts): security enhancement
repository: repo_url: https://github.com/polonel/trudesk
repo_name: polonel/trudesk
description:  :coffee: :seedling: Trudesk is an open-source help desk/ticketing solution.
repo_language: JavaScript
owner: polonel
file_changes: filename: routes.js
change_type: ModificationType.MODIFY
diff: @@ -122,6 +122,7 @@ module.exports = function (middleware, router, controllers) {
   router.delete('/api/v1/groups/:id', apiv1, canUser('groups:delete'), apiCtrl.groups.deleteGroup)
 
   // Users
+  router.put('/api/v1/profile', apiv1, apiCtrl.users.profileUpdate)
   router.get('/api/v1/users', apiv1, canUser('accounts:view'), apiCtrl.users.getWithLimit)
   router.post('/api/v1/users/create', apiv1, canUser('accounts:create'), apiCtrl.users.create)
   router.get('/api/v1/users/notifications', apiv1, apiCtrl.users.getNotifications)

programming_language: CoffeeScript
filename: users.js
change_type: ModificationType.MODIFY
diff: @@ -384,6 +384,104 @@ apiUsers.createPublicAccount = function (req, res) {
   )
 }
 
+apiUsers.profileUpdate = function (req, res) {
+  if (!req.user) return res.status(400).json({ success: false, error: 'Invalid Post Data' })
+  const username = req.user.username
+  if (_.isNull(username) || _.isUndefined(username))
+    return res.status(400).json({ success: false, error: 'Invalid Post Data' })
+
+  const data = req.body
+  let passwordUpdated = false
+
+  const obj = {
+    fullname: data.aFullname,
+    title: data.aTitle,
+    password: data.aPassword,
+    passconfirm: data.aPassConfirm,
+    email: data.aEmail
+  }
+
+  let passwordComplexityEnabled = true
+
+  async.series(
+    {
+      settings: function (done) {
+        const SettingUtil = require('../../../settings/settingsUtil')
+        SettingUtil.getSettings(function (err, content) {
+          if (err) return done(err)
+
+          const settings = content.data.settings
+          passwordComplexityEnabled = settings.accountsPasswordComplexity.value
+
+          return done()
+        })
+      },
+      user: function (done) {
+        UserSchema.getUserByUsername(username, function (err, user) {
+          if (err) return done(err)
+          if (!user) return done('Invalid User Object')
+
+          obj._id = user._id
+
+          if (
+            !_.isUndefined(obj.password) &&
+            !_.isEmpty(obj.password) &&
+            !_.isUndefined(obj.passconfirm) &&
+            !_.isEmpty(obj.passconfirm)
+          ) {
+            if (obj.password === obj.passconfirm) {
+              if (passwordComplexityEnabled) {
+                // check Password Complexity
+                const passwordComplexity = require('../../../settings/passwordComplexity')
+                if (!passwordComplexity.validate(obj.password)) return done('Password does not meet requirements')
+              }
+
+              user.password = obj.password
+              passwordUpdated = true
+            }
+          }
+
+          if (!_.isUndefined(obj.fullname) && obj.fullname.length > 0) user.fullname = obj.fullname
+          if (!_.isUndefined(obj.email) && obj.email.length > 0) user.email = obj.email
+          if (!_.isUndefined(obj.title) && obj.title.length > 0) user.title = obj.title
+
+          user.save(function (err, nUser) {
+            if (err) return done(err)
+
+            nUser.populate('role', function (err, populatedUser) {
+              if (err) return done(err)
+              const resUser = stripUserFields(populatedUser)
+
+              return done(null, resUser)
+            })
+          })
+        })
+      },
+      groups: function (done) {
+        groupSchema.getAllGroupsOfUser(obj._id, done)
+      }
+    },
+    async function (err, results) {
+      if (err) {
+        winston.debug(err)
+        return res.status(400).json({ success: false, error: err })
+      }
+
+      const user = results.user.toJSON()
+      user.groups = results.groups.map(function (g) {
+        return { _id: g._id, name: g.name }
+      })
+
+      if (passwordUpdated) {
+        const Session = require('../../../models/session')
+        await Session.destroy(user._id)
+      }
+
+      return res.json({ success: true, user: user })
+    }
+  )
+}
+
 /**
  * @api {put} /api/v1/users/:username Update User
  * @apiName updateUser

programming_language: JavaScript
filename: profile.js
change_type: ModificationType.MODIFY
diff: @@ -74,7 +74,7 @@ define([
         }
 
         $http
-          .put('/api/v1/users/' + data.username, {
+          .put('/api/v1/profile/', {
             aId: id,
             aFullname: data.fullname,
             aPass: data.password,

programming_language: JavaScript