CVE-2022-25318 (published 2022-02-18T06:15Z)

An issue was discovered in Cerebrate through 1.4. An incorrect sharing group ACL allowed an unprivileged user to edit and modify sharing groups.

Severity: MEDIUM
CVSS v2 base score: 4.0 (AV:N/AC:L/Au:S/C:N/I:P/A:N)
CVSS v3 base score: 4.3, MEDIUM (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N)

Weakness information:
cwe_id: CWE-863
cwe_name: Incorrect Authorization
description: The product performs an authorization check when an actor attempts to access a resource or perform an action, but it does not correctly perform the check. This allows attackers to bypass intended access restrictions.
extended_description: 
            Assuming a user with a given identity, authorization is the process of determining whether that user can access a given resource, based on the user's privileges and any permissions or other access-control specifications that apply to the resource.
            When access control checks are incorrectly applied, users are able to access data or perform actions that they should not be allowed to perform. This can lead to a wide range of problems, including information exposures, denial of service, and arbitrary code execution.
         
         

Fix information:
repo_url: https://github.com/cerebrate-project/cerebrate
commit_details: repo_url: https://github.com/cerebrate-project/cerebrate
author: iglocska
author_date: 2022-02-04 00:16:24+01:00
msg: fix: [security] Sharing group ACL fixes

- added indirect object reference protection
- added correct ACL functionalities to delete, addOrg, removeOrg

- as reported by Dawid Czarnecki from Zigrin Security
repository: repo_url: https://github.com/cerebrate-project/cerebrate
repo_name: cerebrate-project/cerebrate
description: Cerebrate is an open-source platform meant to act as a trusted contact information provider and interconnection orchestrator for other security tools.
repo_language: PHP
owner: cerebrate-project
file_changes: filename: CRUDComponent.php
change_type: ModificationType.MODIFY
diff: @@ -420,10 +420,16 @@ class CRUDComponent extends Component
         }
 
         $data = $this->Table->get($id, $params);
+        if (empty($data)) {
+            throw new NotFoundException(__('Invalid {0}.', $this->ObjectAlias));
+        }
         $data = $this->attachMetaData($id, $data);
         if (isset($params['afterFind'])) {
             $data = $params['afterFind']($data);
         }
+        if (empty($data)) {
+            throw new NotFoundException(__('Invalid {0}.', $this->ObjectAlias));
+        }
         if ($this->Controller->ParamHandler->isRest()) {
             $this->Controller->restResponsePayload = $this->RestResponse->viewData($data, 'json');
         }

programming_language: PHP
filename: SharingGroupsController.php
change_type: ModificationType.MODIFY
diff: @@ -7,6 +7,7 @@ use Cake\Utility\Hash;
 use Cake\Utility\Text;
 use \Cake\Database\Expression\QueryExpression;
 use Cake\Error\Debugger;
+use Cake\Http\Exception\NotFoundException;
 
 class SharingGroupsController extends AppController
 {
@@ -54,8 +55,25 @@ class SharingGroupsController extends AppController
 
     public function view($id)
     {
+        $currentUser = $this->ACL->getUser();
         $this->CRUD->view($id, [
-            'contain' => ['SharingGroupOrgs', 'Organisations', 'Users' => ['fields' => ['id', 'username']]]
+            'contain' => ['SharingGroupOrgs', 'Organisations', 'Users' => ['fields' => ['id', 'username']]],
+            'afterFind' => function($data) use ($currentUser) {
+                if (empty($currentUser['role']['perm_admin'])) {
+                    $orgFround = false;
+                    if (!empty($data['sharing_group_orgs'])) {
+                        foreach ($data['sharing_group_orgs'] as $org) {
+                            if ($org['id'] === $currentUser['organisation_id']) {
+                                $orgFound = true;
+                            }
+                        }
+                    }
+                    if ($data['organisation_id'] !== $currentUser['organisation_id'] && !$orgFround) {
+                        return null;
+                    }
+                }
+                return $data;
+            }
         ]);
         $responsePayload = $this->CRUD->getResponsePayload();
         if (!empty($responsePayload)) {
@@ -87,7 +105,11 @@ class SharingGroupsController extends AppController
 
     public function delete($id)
     {
-        $this->CRUD->delete($id);
+        $currentUser = $this->ACL->getUser();
+        if (empty($currentUser['role']['perm_admin'])) {
+            $params['conditions'] = ['organisation_id' => $currentUser['organisation_id']];
+        }
+        $this->CRUD->delete($id, $params);
         $responsePayload = $this->CRUD->getResponsePayload();
         if (!empty($responsePayload)) {
             return $responsePayload;
@@ -97,9 +119,18 @@ class SharingGroupsController extends AppController
 
     public function addOrg($id)
     {
+        $currentUser = $this->ACL->getUser();
         $sharingGroup = $this->SharingGroups->get($id, [
             'contain' => 'SharingGroupOrgs'
         ]);
+        if (empty($currentUser['role']['perm_admin'])) {
+            if ($sharingGroup['organisation_id'] !== $currentUser['organisation_id']) {
+                $sharingGroup = null;
+            }
+        }
+        if (empty($sharingGroup)) {
+            throw new NotFoundException(__('Invalid SharingGroup.'));
+        }
         $conditions = [];
         $containedOrgIds = array_values(\Cake\Utility\Hash::extract($sharingGroup, 'sharing_group_orgs.{n}.id'));
         if (!empty($containedOrgIds)) {
@@ -156,9 +187,18 @@ class SharingGroupsController extends AppController
 
     public function removeOrg($id, $org_id)
     {
+        $currentUser = $this->ACL->getUser();
         $sharingGroup = $this->SharingGroups->get($id, [
             'contain' => 'SharingGroupOrgs'
         ]);
+        if (empty($currentUser['role']['perm_admin'])) {
+            if ($sharingGroup['organisation_id'] !== $currentUser['organisation_id']) {
+                $sharingGroup = null;
+            }
+        }
+        if (empty($sharingGroup)) {
+            throw new NotFoundException(__('Invalid SharingGroup.'));
+        }
         if ($this->request->is('post')) {
             $org = $this->SharingGroups->SharingGroupOrgs->get($org_id);
             $result = (bool)$this->SharingGroups->SharingGroupOrgs->unlink($sharingGroup, [$org]);

programming_language: PHP