Vulnerability: In Kanboard before 1.0.47, by altering form data, an authenticated user can download attachments from a private project of another user.
Vulnerability ID: CVE-2017-15205
CWE: CWE-200
Severity score: 2.9
Project: https://github.com/kanboard/kanboard
Published: 2017-10-11
File: app/Controller/BaseController.php
Commit message: Make sure people do not access to files of other projects
Commit author: Frederic Guillot

Vulnerable version (before fix):
 protected function getFile()     {         $task_id = $this->request->getIntegerParam('task_id');         $file_id = $this->request->getIntegerParam('file_id');         $model = 'projectFileModel';          if ($task_id > 0) {             $model = 'taskFileModel';             $project_id = $this->taskFinderModel->getProjectId($task_id);              if ($project_id !== $this->request->getIntegerParam('project_id')) {                 throw new AccessForbiddenException();             }         } protected function getFile()             throw new PageNotFoundException();         }          $file['model'] = $model;         return $file;     }

Fixed version (after fix):
 protected function getFile()     {         $task_id = $this->request->getIntegerParam('task_id');         $file_id = $this->request->getIntegerParam('file_id');         $project_id = $this->request->getIntegerParam('project_id');         $model = 'projectFileModel';          if ($task_id > 0) {             $model = 'taskFileModel';             $task_project_id = $this->taskFinderModel->getProjectId($task_id);              if ($project_id != $task_project_id) {                 throw new AccessForbiddenException();             }         } protected function getFile()             throw new PageNotFoundException();         }          if (isset($file['task_id']) && $file['task_id'] != $task_id) {             throw new AccessForbiddenException();         } else if (isset($file['project_id']) && $file['project_id'] != $project_id) {             throw new AccessForbiddenException();         }          $file['model'] = $model;         return $file;     }

Patch:
patch: @@ -74,13 +74,14 @@ protected function getFile()
     {
         $task_id = $this->request->getIntegerParam('task_id');
         $file_id = $this->request->getIntegerParam('file_id');
+        $project_id = $this->request->getIntegerParam('project_id');
         $model = 'projectFileModel';
 
         if ($task_id > 0) {
             $model = 'taskFileModel';
-            $project_id = $this->taskFinderModel->getProjectId($task_id);
+            $task_project_id = $this->taskFinderModel->getProjectId($task_id);
 
-            if ($project_id !== $this->request->getIntegerParam('project_id')) {
+            if ($project_id != $task_project_id) {
                 throw new AccessForbiddenException();
             }
         }
@@ -91,6 +92,12 @@ protected function getFile()
             throw new PageNotFoundException();
         }
 
+        if (isset($file['task_id']) && $file['task_id'] != $task_id) {
+            throw new AccessForbiddenException();
+        } else if (isset($file['project_id']) && $file['project_id'] != $project_id) {
+            throw new AccessForbiddenException();
+        }
+
         $file['model'] = $model;
         return $file;
     }
path: app/Controller/BaseController.php