Add CSRF check for task and project files upload

This commit is contained in:
Frédéric Guillot
2018-01-29 15:56:30 -08:00
parent 90984d6bb9
commit 9ddefa979a
13 changed files with 71 additions and 13 deletions

View File

@@ -26,6 +26,13 @@ abstract class BaseController extends Base
}
}
protected function checkReusableCSRFParam()
{
if (! $this->token->validateReusableCSRFToken($this->request->getRawValue('csrf_token'))) {
throw new AccessForbiddenException();
}
}
/**
* Check webhook token
*

View File

@@ -32,6 +32,7 @@ class ProjectFileController extends BaseController
*/
public function save()
{
$this->checkReusableCSRFParam();
$project = $this->getProject();
$result = $this->projectFileModel->uploadFiles($project['id'], $this->request->getFileInfo('files'));

View File

@@ -51,6 +51,7 @@ class TaskFileController extends BaseController
*/
public function save()
{
$this->checkReusableCSRFParam();
$task = $this->getTask();
$result = $this->taskFileModel->uploadFiles($task['id'], $this->request->getFileInfo('files'));

View File

@@ -111,6 +111,17 @@ class Request extends Base
return array();
}
/**
* Get POST value without modification
*
* @param $name
* @return mixed|null
*/
public function getRawValue($name)
{
return isset($this->post[$name]) ? $this->post[$name] : null;
}
/**
* Get the raw body of the HTTP request
*

View File

@@ -25,21 +25,25 @@ class Token extends Base
}
/**
* Generate and store a CSRF token in the current session
* Generate and store a one-time CSRF token
*
* @access public
* @return string Random token
*/
public function getCSRFToken()
{
if (! session_exists('csrf')) {
session_set('csrf', []);
}
return $this->createSessionToken('csrf');
}
$nonce = self::getToken();
session_merge('csrf', [$nonce => true]);
return $nonce;
/**
* Generate and store a reusable CSRF token
*
* @access public
* @return string
*/
public function getReusableCSRFToken()
{
return $this->createSessionToken('pcsrf');
}
/**
@@ -60,4 +64,26 @@ class Token extends Base
return false;
}
public function validateReusableCSRFToken($token)
{
$tokens = session_get('pcsrf');
if (isset($tokens[$token])) {
return true;
}
return false;
}
protected function createSessionToken($key)
{
if (! session_exists($key)) {
session_set($key, []);
}
$nonce = self::getToken();
session_merge($key, [$nonce => true]);
return $nonce;
}
}

View File

@@ -12,6 +12,11 @@ use Kanboard\Core\Base;
*/
class AppHelper extends Base
{
public function getToken()
{
return $this->token;
}
public function isAjax()
{
return $this->request->isAjax();

View File

@@ -3,6 +3,7 @@
</div>
<?= $this->app->component('file-upload', array(
'csrf' => $this->app->getToken()->getReusableCSRFToken(),
'maxSize' => $max_size,
'url' => $this->url->to('ProjectFileController', 'save', array('project_id' => $project['id'])),
'labelDropzone' => t('Drag and drop your files here'),

View File

@@ -3,6 +3,7 @@
</div>
<?= $this->app->component('file-upload', array(
'csrf' => $this->app->getToken()->getReusableCSRFToken(),
'maxSize' => $max_size,
'url' => $this->url->to('TaskFileController', 'save', array('task_id' => $task['id'], 'project_id' => $task['project_id'])),
'labelDropzone' => t('Drag and drop your files here'),