CVE-2024-36399: Insufficient Information (NVD-CWE-noinfo)
value: Kanboard is project management software that focuses on the Kanban methodology. The vuln is in app/Controller/ProjectPermissionController.php function addUser(). The users permission to add users to a project only get checked on the URL parameter project_id. If the user is authorized to add users to this project the request gets processed. The users permission for the POST BODY parameter project_id does not get checked again while processing. An attacker with the 'Project Manager' on a single project may take over any other project. The vulnerability is fixed in 1.2.37.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
Published: 2024-06-06T16:15Z
Repository: https://github.com/kanboard/kanboard
Language: PHP
Files changed: app/Controller/ProjectPermissionController.php, app/Template/project_permission/groups.php, app/Template/project_permission/users.php
Commit date: 2024-06-05 20:54:17 -0700
Commit message: Add CSRF check and remove project_id form value for addUser/addGroup actions

Diff: diff --git a/app/Controller/ProjectPermissionController.php b/app/Controller/ProjectPermissionController.php
index 21f0ddb0f9..02efcf51bd 100644
--- a/app/Controller/ProjectPermissionController.php
+++ b/app/Controller/ProjectPermissionController.php
@@ -64,20 +64,22 @@ class ProjectPermissionController extends BaseController
      *
      * @access public
      */
     public function addUser()
     {
+        $this->checkCSRFForm();
+
         $project = $this->getProject();
         $values = $this->request->getValues();
 
         if (empty($values['user_id']) && ! empty($values['external_id']) && ! empty($values['external_id_column'])) {
             $values['user_id'] = $this->userModel->getOrCreateExternalUserId($values['username'], $values['name'], $values['external_id_column'], $values['external_id']);
         }
 
         if (empty($values['user_id'])) {
             $this->flash->failure(t('User not found.'));
-        } elseif ($this->projectUserRoleModel->addUser($values['project_id'], $values['user_id'], $values['role'])) {
+        } elseif ($this->projectUserRoleModel->addUser($project['id'], $values['user_id'], $values['role'])) {
             $this->flash->success(t('Project updated successfully.'));
         } else {
             $this->flash->failure(t('Unable to update this project.'));
         }
 
@@ -142,10 +144,12 @@ class ProjectPermissionController extends BaseController
      *
      * @access public
      */
     public function addGroup()
     {
+        $this->checkCSRFForm();
+
         $project = $this->getProject();
         $values = $this->request->getValues();
 
         if (empty($values['group_id']) && ! empty($values['external_id'])) {
             $values['group_id'] = $this->groupModel->getOrCreateExternalGroupId($values['name'], $values['external_id']);
diff --git a/app/Template/project_permission/groups.php b/app/Template/project_permission/groups.php
index 7a7c132fb2..72c18f388b 100644
--- a/app/Template/project_permission/groups.php
+++ b/app/Template/project_permission/groups.php
@@ -35,11 +35,10 @@
 
 <?php if ($project['is_private'] == 0): ?>
     <div class="panel">
         <form method="post" action="<?= $this->url->href('ProjectPermissionController', 'addGroup', array('project_id' => $project['id'])) ?>" autocomplete="off" class="form-inline">
             <?= $this->form->csrf() ?>
-            <?= $this->form->hidden('project_id', array('project_id' => $project['id'])) ?>
             <?= $this->form->hidden('group_id', $values) ?>
             <?= $this->form->hidden('external_id', $values) ?>
 
             <?= $this->form->label(t('Group Name'), 'name') ?>
             <?= $this->form->text('name', $values, $errors, array(
diff --git a/app/Template/project_permission/users.php b/app/Template/project_permission/users.php
index 78f2e9392d..350a0c7b0a 100644
--- a/app/Template/project_permission/users.php
+++ b/app/Template/project_permission/users.php
@@ -33,11 +33,10 @@
 
 <?php if ($project['is_private'] == 0): ?>
     <div class="panel">
         <form method="post" action="<?= $this->url->href('ProjectPermissionController', 'addUser', array('project_id' => $project['id'])) ?>" autocomplete="off" class="form-inline">
             <?= $this->form->csrf() ?>
-            <?= $this->form->hidden('project_id', array('project_id' => $project['id'])) ?>
             <?= $this->form->hidden('user_id', $values) ?>
             <?= $this->form->hidden('username', $values) ?>
             <?= $this->form->hidden('external_id', $values) ?>
             <?= $this->form->hidden('external_id_column', $values) ?>
 

Vulnerable code:         } elseif ($this->projectUserRoleModel->addUser($values['project_id'], $values['user_id'], $values['role'])) {
            <?= $this->form->hidden('project_id', array('project_id' => $project['id'])) ?>
            <?= $this->form->hidden('project_id', array('project_id' => $project['id'])) ?>
Fixed code:         $this->checkCSRFForm();

        } elseif ($this->projectUserRoleModel->addUser($project['id'], $values['user_id'], $values['role'])) {
        $this->checkCSRFForm();