CVE-2021-32648: Other (NVD-CWE-Other)
value: octobercms in a CMS platform based on the Laravel PHP Framework. In affected versions of the october/system package an attacker can request an account password reset and then gain access to the account using a specially crafted request. The issue has been patched in Build 472 and v1.1.5.
CWE description: NVD is only using a subset of CWE for mapping instead of the entire CWE, and the weakness type is not covered by that subset.
CVSS v3 base score: 9.1
Published: 2021-08-26T19:15Z
Repository: https://github.com/octobercms/library
Language: PHP
Files changed: src/Auth/Models/Role.php, src/Auth/Models/User.php
Commit date: 2021-04-07 14:03:37 +1000
Commit message: Use int casting

These manifested as strings for some users

Diff: diff --git a/src/Auth/Models/Role.php b/src/Auth/Models/Role.php
index 4479c844..92c95ce9 100644
--- a/src/Auth/Models/Role.php
+++ b/src/Auth/Models/Role.php
@@ -82,11 +82,11 @@ class Role extends Model
                     // Strip the '*' off the end of the permission.
                     $checkPermission = substr($permission, 0, -1);
 
                     // We will make sure that the merged permission does not
                     // exactly match our permission, but starts with it.
-                    if ($checkPermission != $rolePermission && starts_with($rolePermission, $checkPermission) && $value === 1) {
+                    if ($checkPermission != $rolePermission && starts_with($rolePermission, $checkPermission) && (int) $value === 1) {
                         $matched = true;
                         break;
                     }
                 }
             }
@@ -100,11 +100,11 @@ class Role extends Model
                     // Strip the '*' off the start of the permission.
                     $checkPermission = substr($permission, 1);
 
                     // We will make sure that the merged permission does not
                     // exactly match our permission, but ends with it.
-                    if ($checkPermission != $rolePermission && ends_with($rolePermission, $checkPermission) && $value === 1) {
+                    if ($checkPermission != $rolePermission && ends_with($rolePermission, $checkPermission) && (int) $value === 1) {
                         $matched = true;
                         break;
                     }
                 }
             }
@@ -119,18 +119,18 @@ class Role extends Model
                         // Strip the '*' off the end of the permission.
                         $checkGroupPermission = substr($rolePermission, 0, -1);
 
                         // We will make sure that the merged permission does not
                         // exactly match our permission, but starts with it.
-                        if ($checkGroupPermission != $permission && starts_with($permission, $checkGroupPermission) && $value === 1) {
+                        if ($checkGroupPermission != $permission && starts_with($permission, $checkGroupPermission) && (int) $value === 1) {
                             $matched = true;
                             break;
                         }
                     }
                     // Otherwise, we'll fallback to standard permissions checking where
                     // we match that permissions explicitly exist.
-                    elseif ($permission === $rolePermission && $rolePermissions[$permission] === 1) {
+                    elseif ($permission === $rolePermission && (int) $rolePermissions[$permission] === 1) {
                         $matched = true;
                         break;
                     }
                 }
             }
diff --git a/src/Auth/Models/User.php b/src/Auth/Models/User.php
index ebba418b..bd524c60 100644
--- a/src/Auth/Models/User.php
+++ b/src/Auth/Models/User.php
@@ -479,11 +479,11 @@ class User extends Model implements \Illuminate\Contracts\Auth\Authenticatable
                     // Strip the '*' off the end of the permission.
                     $checkPermission = substr($permission, 0, -1);
 
                     // We will make sure that the merged permission does not
                     // exactly match our permission, but starts with it.
-                    if ($checkPermission != $mergedPermission && starts_with($mergedPermission, $checkPermission) && $value === 1) {
+                    if ($checkPermission != $mergedPermission && starts_with($mergedPermission, $checkPermission) && (int) $value === 1) {
                         $matched = true;
                         break;
                     }
                 }
             }
@@ -494,11 +494,11 @@ class User extends Model implements \Illuminate\Contracts\Auth\Authenticatable
                     // Strip the '*' off the beginning of the permission.
                     $checkPermission = substr($permission, 1);
 
                     // We will make sure that the merged permission does not
                     // exactly match our permission, but ends with it.
-                    if ($checkPermission != $mergedPermission && ends_with($mergedPermission, $checkPermission) && $value === 1) {
+                    if ($checkPermission != $mergedPermission && ends_with($mergedPermission, $checkPermission) && (int) $value === 1) {
                         $matched = true;
                         break;
                     }
                 }
             }
@@ -513,19 +513,19 @@ class User extends Model implements \Illuminate\Contracts\Auth\Authenticatable
                         // Strip the '*' off the end of the permission.
                         $checkMergedPermission = substr($mergedPermission, 0, -1);
 
                         // We will make sure that the merged permission does not
                         // exactly match our permission, but starts with it.
-                        if ($checkMergedPermission != $permission && starts_with($permission, $checkMergedPermission) && $value === 1) {
+                        if ($checkMergedPermission != $permission && starts_with($permission, $checkMergedPermission) && (int) $value === 1) {
                             $matched = true;
                             break;
                         }
                     }
 
                     // Otherwise, we'll fallback to standard permissions checking where
                     // we match that permissions explicitly exist.
-                    elseif ($permission === $mergedPermission && $mergedPermissions[$permission] === 1) {
+                    elseif ($permission === $mergedPermission && (int) $mergedPermissions[$permission] === 1) {
                         $matched = true;
                         break;
                     }
                 }
             }

Vulnerable code:                     if ($checkPermission != $rolePermission && starts_with($rolePermission, $checkPermission) && $value === 1) {
                    if ($checkPermission != $rolePermission && ends_with($rolePermission, $checkPermission) && $value === 1) {
                        if ($checkGroupPermission != $permission && starts_with($permission, $checkGroupPermission) && $value === 1) {
                    elseif ($permission === $rolePermission && $rolePermissions[$permission] === 1) {
                    if ($checkPermission != $mergedPermission && starts_with($mergedPermission, $checkPermission) && $value === 1) {
                    if ($checkPermission != $mergedPermission && ends_with($mergedPermission, $checkPermission) && $value === 1) {
                        if ($checkMergedPermission != $permission && starts_with($permission, $checkMergedPermission) && $value === 1) {
                    elseif ($permission === $mergedPermission && $mergedPermissions[$permission] === 1) {
Fixed code:                     if ($checkPermission != $rolePermission && starts_with($rolePermission, $checkPermission) && (int) $value === 1) {
                    if ($checkPermission != $rolePermission && ends_with($rolePermission, $checkPermission) && (int) $value === 1) {
                        if ($checkGroupPermission != $permission && starts_with($permission, $checkGroupPermission) && (int) $value === 1) {
                    elseif ($permission === $rolePermission && (int) $rolePermissions[$permission] === 1) {
                    if ($checkPermission != $mergedPermission && starts_with($mergedPermission, $checkPermission) && (int) $value === 1) {
                    if ($checkPermission != $mergedPermission && ends_with($mergedPermission, $checkPermission) && (int) $value === 1) {
                        if ($checkMergedPermission != $permission && starts_with($permission, $checkMergedPermission) && (int) $value === 1) {
                    elseif ($permission === $mergedPermission && (int) $mergedPermissions[$permission] === 1) {