CVE-2022-4068: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: A user is able to enable their own account if it was disabled by an admin while the user still holds a valid session. Moreover, the username is not properly sanitized in the admin user overview. This enables an XSS attack that enables an attacker with a low privilege user to execute arbitrary JavaScript in the context of an admin's account.
CWE description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVSS v3 base score: 5.4
Published: 2022-11-20T05:15Z
Repository: https://github.com/librenms/librenms
Language: PHP
Files changed: app/Http/Controllers/UserController.php, app/Http/Requests/UpdateUserRequest.php
Commit date: 2022-10-17 12:11:14 -0500
Commit message: Fix authentication mass assignment vulnerability (#14468)

Users were able to submit changes to fields they should not have access to change by bypassing the frontend validation.  Correct backend validation to prevent that.
Diff: diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php
index 5d15a0b300e..427d9bfe0b5 100644
--- a/app/Http/Controllers/UserController.php
+++ b/app/Http/Controllers/UserController.php
@@ -178,11 +178,11 @@ class UserController extends Controller
             if ($current_user->user_id !== $user->user_id) {
                 Auth::setUser($current_user);
             }
         }
 
-        $user->fill($request->all());
+        $user->fill($request->validated());
 
         if ($request->has('dashboard') && $this->updateDashboard($user, $request->get('dashboard'))) {
             $flasher->addSuccess(__('Updated dashboard for :username', ['username' => $user->username]));
         }
 
diff --git a/app/Http/Requests/UpdateUserRequest.php b/app/Http/Requests/UpdateUserRequest.php
index 72726c51532..b33c00d8a62 100644
--- a/app/Http/Requests/UpdateUserRequest.php
+++ b/app/Http/Requests/UpdateUserRequest.php
@@ -35,15 +35,28 @@ class UpdateUserRequest extends FormRequest
      *
      * @return array
      */
     public function rules()
     {
+        if ($this->user()->isAdmin()) {
+            return [
+                'realname' => 'nullable|max:64|alpha_space',
+                'email' => 'nullable|email|max:64',
+                'descr' => 'nullable|max:30|alpha_space',
+                'new_password' => 'nullable|confirmed|min:' . Config::get('password.min_length', 8),
+                'new_password_confirmation' => 'nullable|same:new_password',
+                'dashboard' => 'int',
+                'level' => 'int',
+                'enabled' => 'nullable',
+                'can_modify_passwd' => 'nullable',
+            ];
+        }
+
         return [
             'realname' => 'nullable|max:64|alpha_space',
             'email' => 'nullable|email|max:64',
             'descr' => 'nullable|max:30|alpha_space',
-            'level' => 'int',
             'old_password' => 'nullable|string',
             'new_password' => 'nullable|confirmed|min:' . Config::get('password.min_length', 8),
             'new_password_confirmation' => 'nullable|same:new_password',
             'dashboard' => 'int',
         ];

Vulnerable code:         $user->fill($request->all());
            'level' => 'int',
Fixed code:         $user->fill($request->validated());
        if ($this->user()->isAdmin()) {
            return [
                'realname' => 'nullable|max:64|alpha_space',
                'email' => 'nullable|email|max:64',
                'descr' => 'nullable|max:30|alpha_space',
                'new_password' => 'nullable|confirmed|min:' . Config::get('password.min_length', 8),
                'new_password_confirmation' => 'nullable|same:new_password',
                'dashboard' => 'int',
                'level' => 'int',
                'enabled' => 'nullable',
                'can_modify_passwd' => 'nullable',
            ];
        }