CVE-2022-3173: Improper Authentication (CWE-287)
value: Improper Authentication in GitHub repository snipe/snipe-it prior to 6.0.10.
CWE description: When an actor claims to have a given identity, the product does not prove or insufficiently proves that the claim is correct.
CVSS v3 base score: 4.3
Published: 2022-09-17T07:15Z
Repository: https://github.com/snipe/snipe-it
Language: PHP
Files changed: app/Http/Controllers/Licenses/LicenseFilesController.php, app/Policies/LicensePolicy.php, app/Policies/SnipePermissionsPolicy.php, app/Providers/AuthServiceProvider.php, resources/lang/en/admin/licenses/message.php, resources/views/licenses/view.blade.php
Commit date: 2022-09-16 14:00:27 -0700
Commit message: Check for licenses.files permissions

Signed-off-by: snipe <snipe@snipe.net>

Diff: diff --git a/app/Http/Controllers/Licenses/LicenseFilesController.php b/app/Http/Controllers/Licenses/LicenseFilesController.php
index 81a2f26ede5..db414edebfe 100644
--- a/app/Http/Controllers/Licenses/LicenseFilesController.php
+++ b/app/Http/Controllers/Licenses/LicenseFilesController.php
@@ -133,10 +133,11 @@ class LicenseFilesController extends Controller
         $license = License::find($licenseId);
 
         // the license is valid
         if (isset($license->id)) {
             $this->authorize('view', $license);
+            $this->authorize('licenses.files', $license);
 
             if (! $log = Actionlog::find($fileId)) {
                 return response('No matching record for that asset/file', 500)
                     ->header('Content-Type', 'text/plain');
             }
@@ -169,8 +170,8 @@ class LicenseFilesController extends Controller
 
                 }
             }
         }
 
-        return redirect()->route('license.index')->with('error', trans('admin/licenses/message.does_not_exist', ['id' => $fileId]));
+        return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist', ['id' => $fileId]));
     }
 }
diff --git a/app/Policies/LicensePolicy.php b/app/Policies/LicensePolicy.php
index 7a92b5b7de5..3f2f780d9b4 100644
--- a/app/Policies/LicensePolicy.php
+++ b/app/Policies/LicensePolicy.php
@@ -40,10 +40,14 @@ class LicensePolicy extends CheckoutablePermissionsPolicy
      * Determine whether the user can access files associated with licenses.
      *
      * @param  \App\Models\User  $user
      * @return mixed
      */
-    public function files(User $user)
+    public function viewFiles(User $user)
     {
-        return $user->hasAccess($this->columnName().'.files');
+        if ($user->hasAccess('licenses.files'))  {
+            return true;
+        }
+        return false;
+
     }
 }
diff --git a/app/Policies/SnipePermissionsPolicy.php b/app/Policies/SnipePermissionsPolicy.php
index 703385ec99e..d4f2d88ccd8 100644
--- a/app/Policies/SnipePermissionsPolicy.php
+++ b/app/Policies/SnipePermissionsPolicy.php
@@ -59,10 +59,15 @@ abstract class SnipePermissionsPolicy
     public function view(User $user, $item = null)
     {
         return $user->hasAccess($this->columnName().'.view');
     }
 
+    public function files(User $user, $item = null)
+    {
+        return $user->hasAccess($this->columnName().'.files');
+    }
+
     /**
      * Determine whether the user can create accessories.
      *
      * @param  \App\Models\User  $user
      * @return mixed
diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php
index ac466d0ca98..7541e39919a 100644
--- a/app/Providers/AuthServiceProvider.php
+++ b/app/Providers/AuthServiceProvider.php
@@ -120,10 +120,17 @@ class AuthServiceProvider extends ServiceProvider
                 return true;
             }
         });
 
 
+        Gate::define('licenses.files', function ($user) {
+            if ($user->hasAccess('licenses.files')) {
+                return true;
+            }
+        });
+
+
         // -----------------------------------------
         // Reports
         // -----------------------------------------
         Gate::define('reports.view', function ($user) {
             if ($user->hasAccess('reports.view')) {
diff --git a/resources/lang/en/admin/licenses/message.php b/resources/lang/en/admin/licenses/message.php
index 87a7c3d0b9d..dd7e54dea4a 100644
--- a/resources/lang/en/admin/licenses/message.php
+++ b/resources/lang/en/admin/licenses/message.php
@@ -1,10 +1,10 @@
 <?php
 
 return array(
 
-    'does_not_exist' => 'License does not exist.',
+    'does_not_exist' => 'License does not exist or you do not have permission to view it.',
     'user_does_not_exist' => 'User does not exist.',
     'asset_does_not_exist' 	=> 'The asset you are trying to associate with this license does not exist.',
     'owner_doesnt_match_asset' => 'The asset you are trying to associate with this license is owned by somene other than the person selected in the assigned to dropdown.',
     'assoc_users'	 => 'This license is currently checked out to a user and cannot be deleted. Please check the license in first, and then try deleting again. ',
     'select_asset_or_person' => 'You must select an asset or a user, but not both.',
diff --git a/resources/views/licenses/view.blade.php b/resources/views/licenses/view.blade.php
index 1f6b085a475..d0623cf405f 100755
--- a/resources/views/licenses/view.blade.php
+++ b/resources/views/licenses/view.blade.php
@@ -34,20 +34,22 @@
               <span class="hidden-xs hidden-sm">{{ trans('admin/licenses/form.seats') }}</span>
               <span class="badge badge-secondary">{{ number_format($license->availCount()->count()) }} / {{ number_format($license->seats) }}</span>
 
             </a>
         </li>
-        
+
+        @can('licenses.files', $license)
         <li>
           <a href="#files" data-toggle="tab">
             <span class="hidden-lg hidden-md">
             <i class="far fa-file fa-2x" aria-hidden="true"></i></span>
             <span class="hidden-xs hidden-sm">{{ trans('general.file_uploads') }}
               {!! ($license->uploads->count() > 0 ) ? '<badge class="badge badge-secondary">'.number_format($license->uploads->count()).'</badge>' : '' !!}
             </span>
           </a>
         </li>
+        @endcan
 
         <li>
           <a href="#history" data-toggle="tab">
             <span class="hidden-lg hidden-md">
             <i class="fas fa-history fa-2x" aria-hidden="true"></i></span>
@@ -414,11 +416,11 @@
             </div>
 
           </div> <!--/.row-->
         </div> <!-- /.tab-pane -->
 
-        @can('files', $license)
+        @can('licenses.files', $license)
         <div class="tab-pane" id="files">
           <div class="table-responsive">
             <table
                 data-cookie-id-table="licenseUploadsTable"
                 data-id-table="licenseUploadsTable"

Vulnerable code:         return redirect()->route('license.index')->with('error', trans('admin/licenses/message.does_not_exist', ['id' => $fileId]));
    public function files(User $user)
        return $user->hasAccess($this->columnName().'.files');
    'does_not_exist' => 'License does not exist.',
        
        @can('files', $license)
Fixed code:             $this->authorize('licenses.files', $license);
        return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist', ['id' => $fileId]));
    public function viewFiles(User $user)
        if ($user->hasAccess('licenses.files'))  {
            return true;
        }
        return false;

    public function files(User $user, $item = null)
    {
        return $user->hasAccess($this->columnName().'.files');
    }

        Gate::define('licenses.files', function ($user) {
            if ($user->hasAccess('licenses.files')) {
                return true;
            }
        });


    'does_not_exist' => 'License does not exist or you do not have permission to view it.',

        @can('licenses.files', $license)
        @endcan
        @can('licenses.files', $license)