CVE-2021-29487 (published 2021-08-26T19:15Z)

octobercms in a CMS platform based on the Laravel PHP Framework. In affected versions of the october/system package an attacker can exploit this vulnerability to bypass authentication and takeover of and user account on an October CMS server. The vulnerability is exploitable by unauthenticated users via a specially crafted request. This only affects frontend users and the attacker must obtain a Laravel secret key for cookie encryption and signing in order to exploit this vulnerability. The issue has been patched in Build 472 and v1.1.5.

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

Weakness information:
cwe_id: NVD-CWE-Other
cwe_name: Other
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.
extended_description: Insufficient Information

Fix information:
repo_url: https://github.com/octobercms/library
commit_details: repo_url: https://github.com/octobercms/library
author: Samuel Georges
author_date: 2021-04-07 14:03:04+10:00
msg: Use int casting

These manifested as strings for some users
repository: repo_url: https://github.com/octobercms/library
repo_name: octobercms/library
description: October Rain Library
repo_language: PHP
owner: octobercms
file_changes: filename: Role.php
change_type: ModificationType.MODIFY
diff: @@ -84,7 +84,7 @@ class Role extends Model
 
                     // 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;
                     }
@@ -102,7 +102,7 @@ class Role extends Model
 
                     // 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;
                     }
@@ -121,14 +121,14 @@ class Role extends Model
 
                         // 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;
                     }

programming_language: PHP
filename: User.php
change_type: ModificationType.MODIFY
diff: @@ -481,7 +481,7 @@ class User extends Model implements \Illuminate\Contracts\Auth\Authenticatable
 
                     // 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;
                     }
@@ -496,7 +496,7 @@ class User extends Model implements \Illuminate\Contracts\Auth\Authenticatable
 
                     // 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;
                     }
@@ -515,7 +515,7 @@ class User extends Model implements \Illuminate\Contracts\Auth\Authenticatable
 
                         // 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;
                         }
@@ -523,7 +523,7 @@ class User extends Model implements \Illuminate\Contracts\Auth\Authenticatable
 
                     // 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;
                     }

programming_language: PHP
repo_url: https://github.com/octobercms/library
commit_details: repo_url: https://github.com/octobercms/library
author: Samuel Georges
author_date: 2021-04-01 11:18:07+11:00
msg: Backport code audit from 1.2

Fixes issue with permissions checking
repository: repo_url: https://github.com/octobercms/library
repo_name: octobercms/library
description: October Rain Library
repo_language: PHP
owner: octobercms
file_changes: filename: Manager.php
change_type: ModificationType.MODIFY
diff: @@ -241,7 +241,7 @@ class Manager implements \Illuminate\Contracts\Auth\StatefulGuard
         foreach ($hashedCredentials as $credential => $value) {
             if (!$user->checkHashValue($credential, $value)) {
                 // Incorrect password
-                if ($credential == 'password') {
+                if ($credential === 'password') {
                     throw new AuthException(sprintf(
                         'A user was found to match all plain text credentials however hashed credential "%s" did not match.',
                         $credential

programming_language: PHP
filename: Role.php
change_type: ModificationType.MODIFY
diff: @@ -84,7 +84,7 @@ class Role extends Model
 
                     // 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) && $value === 1) {
                         $matched = true;
                         break;
                     }
@@ -102,7 +102,7 @@ class Role extends Model
 
                     // 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) && $value === 1) {
                         $matched = true;
                         break;
                     }
@@ -121,14 +121,14 @@ class Role extends Model
 
                         // 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) && $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 && $rolePermissions[$permission] === 1) {
                         $matched = true;
                         break;
                     }

programming_language: PHP
filename: Throttle.php
change_type: ModificationType.MODIFY
diff: @@ -99,7 +99,7 @@ class Throttle extends Model
         // anything either as clearing login attempts
         // makes us unsuspended. We need to manually
         // call unsuspend() in order to unsuspend.
-        if ($this->getLoginAttempts() == 0 or $this->is_suspended) {
+        if ($this->getLoginAttempts() === 0 or $this->is_suspended) {
             return;
         }
 

programming_language: PHP
filename: User.php
change_type: ModificationType.MODIFY
diff: @@ -190,7 +190,7 @@ class User extends Model implements \Illuminate\Contracts\Auth\Authenticatable
             return false;
         }
 
-        return $persistCode == $this->persist_code;
+        return $persistCode === $this->persist_code;
     }
 
     //
@@ -278,7 +278,7 @@ class User extends Model implements \Illuminate\Contracts\Auth\Authenticatable
             return false;
         }
 
-        return ($this->reset_password_code == $resetCode);
+        return ($this->reset_password_code === $resetCode);
     }
 
     /**
@@ -386,7 +386,7 @@ class User extends Model implements \Illuminate\Contracts\Auth\Authenticatable
     public function inGroup($group)
     {
         foreach ($this->getGroups() as $_group) {
-            if ($_group->getKey() == $group->getKey()) {
+            if ($_group->getKey() === $group->getKey()) {
                 return true;
             }
         }
@@ -481,7 +481,7 @@ class User extends Model implements \Illuminate\Contracts\Auth\Authenticatable
 
                     // 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) && $value === 1) {
                         $matched = true;
                         break;
                     }
@@ -496,7 +496,7 @@ class User extends Model implements \Illuminate\Contracts\Auth\Authenticatable
 
                     // 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) && $value === 1) {
                         $matched = true;
                         break;
                     }
@@ -515,7 +515,7 @@ class User extends Model implements \Illuminate\Contracts\Auth\Authenticatable
 
                         // 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) && $value === 1) {
                             $matched = true;
                             break;
                         }
@@ -523,7 +523,7 @@ class User extends Model implements \Illuminate\Contracts\Auth\Authenticatable
 
                     // Otherwise, we'll fallback to standard permissions checking where
                     // we match that permissions explicitly exist.
-                    elseif ($permission == $mergedPermission && $mergedPermissions[$permission] == 1) {
+                    elseif ($permission === $mergedPermission && $mergedPermissions[$permission] === 1) {
                         $matched = true;
                         break;
                     }

programming_language: PHP