Add CSRF check for task and project files upload
This commit is contained in:
parent
90984d6bb9
commit
9ddefa979a
|
|
@ -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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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'));
|
||||
|
||||
|
|
|
|||
|
|
@ -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'));
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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'),
|
||||
|
|
|
|||
|
|
@ -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'),
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -29,7 +29,7 @@ KB.component('file-upload', function (containerElement, options) {
|
|||
currentFileIndex++;
|
||||
|
||||
if (currentFileIndex < files.length) {
|
||||
KB.http.uploadFile(options.url, files[currentFileIndex], onProgress, onComplete, onError, onServerError);
|
||||
KB.http.uploadFile(options.url, files[currentFileIndex], options.csrf, onProgress, onComplete, onError, onServerError);
|
||||
} else {
|
||||
KB.trigger('modal.stop');
|
||||
KB.trigger('modal.hide');
|
||||
|
|
@ -92,7 +92,7 @@ KB.component('file-upload', function (containerElement, options) {
|
|||
|
||||
function uploadFiles() {
|
||||
if (files.length > 0) {
|
||||
KB.http.uploadFile(options.url, files[currentFileIndex], onProgress, onComplete, onError, onServerError);
|
||||
KB.http.uploadFile(options.url, files[currentFileIndex], options.csrf, onProgress, onComplete, onError, onServerError);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -83,9 +83,10 @@ KB.http.postForm = function (url, formElement) {
|
|||
return (new KB.http.request('POST', url, {}, formData)).execute();
|
||||
};
|
||||
|
||||
KB.http.uploadFile = function (url, file, onProgress, onComplete, onError, onServerError) {
|
||||
KB.http.uploadFile = function (url, file, csrf, onProgress, onComplete, onError, onServerError) {
|
||||
var fd = new FormData();
|
||||
fd.append('files[]', file);
|
||||
fd.append('csrf_token', csrf);
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.upload.addEventListener('progress', onProgress);
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ return array(
|
|||
'Kanboard\\Action\\TaskAssignColorColumn' => $baseDir . '/app/Action/TaskAssignColorColumn.php',
|
||||
'Kanboard\\Action\\TaskAssignColorLink' => $baseDir . '/app/Action/TaskAssignColorLink.php',
|
||||
'Kanboard\\Action\\TaskAssignColorOnDueDate' => $baseDir . '/app/Action/TaskAssignColorOnDueDate.php',
|
||||
'Kanboard\\Action\\TaskAssignColorOnStartDate' => $baseDir . '/app/Action/TaskAssignColorOnStartDate.php',
|
||||
'Kanboard\\Action\\TaskAssignColorPriority' => $baseDir . '/app/Action/TaskAssignColorPriority.php',
|
||||
'Kanboard\\Action\\TaskAssignColorSwimlane' => $baseDir . '/app/Action/TaskAssignColorSwimlane.php',
|
||||
'Kanboard\\Action\\TaskAssignColorUser' => $baseDir . '/app/Action/TaskAssignColorUser.php',
|
||||
|
|
@ -94,6 +95,7 @@ return array(
|
|||
'Kanboard\\Action\\TaskMoveColumnCategoryChange' => $baseDir . '/app/Action/TaskMoveColumnCategoryChange.php',
|
||||
'Kanboard\\Action\\TaskMoveColumnClosed' => $baseDir . '/app/Action/TaskMoveColumnClosed.php',
|
||||
'Kanboard\\Action\\TaskMoveColumnNotMovedPeriod' => $baseDir . '/app/Action/TaskMoveColumnNotMovedPeriod.php',
|
||||
'Kanboard\\Action\\TaskMoveColumnOnStartDate' => $baseDir . '/app/Action/TaskMoveColumnOnStartDate.php',
|
||||
'Kanboard\\Action\\TaskMoveColumnUnAssigned' => $baseDir . '/app/Action/TaskMoveColumnUnAssigned.php',
|
||||
'Kanboard\\Action\\TaskOpen' => $baseDir . '/app/Action/TaskOpen.php',
|
||||
'Kanboard\\Action\\TaskUpdateStartDate' => $baseDir . '/app/Action/TaskUpdateStartDate.php',
|
||||
|
|
|
|||
|
|
@ -219,6 +219,7 @@ class ComposerStaticInit6edea6294a88689e3f5c56484bb70c9b
|
|||
'Kanboard\\Action\\TaskAssignColorColumn' => __DIR__ . '/../..' . '/app/Action/TaskAssignColorColumn.php',
|
||||
'Kanboard\\Action\\TaskAssignColorLink' => __DIR__ . '/../..' . '/app/Action/TaskAssignColorLink.php',
|
||||
'Kanboard\\Action\\TaskAssignColorOnDueDate' => __DIR__ . '/../..' . '/app/Action/TaskAssignColorOnDueDate.php',
|
||||
'Kanboard\\Action\\TaskAssignColorOnStartDate' => __DIR__ . '/../..' . '/app/Action/TaskAssignColorOnStartDate.php',
|
||||
'Kanboard\\Action\\TaskAssignColorPriority' => __DIR__ . '/../..' . '/app/Action/TaskAssignColorPriority.php',
|
||||
'Kanboard\\Action\\TaskAssignColorSwimlane' => __DIR__ . '/../..' . '/app/Action/TaskAssignColorSwimlane.php',
|
||||
'Kanboard\\Action\\TaskAssignColorUser' => __DIR__ . '/../..' . '/app/Action/TaskAssignColorUser.php',
|
||||
|
|
@ -243,6 +244,7 @@ class ComposerStaticInit6edea6294a88689e3f5c56484bb70c9b
|
|||
'Kanboard\\Action\\TaskMoveColumnCategoryChange' => __DIR__ . '/../..' . '/app/Action/TaskMoveColumnCategoryChange.php',
|
||||
'Kanboard\\Action\\TaskMoveColumnClosed' => __DIR__ . '/../..' . '/app/Action/TaskMoveColumnClosed.php',
|
||||
'Kanboard\\Action\\TaskMoveColumnNotMovedPeriod' => __DIR__ . '/../..' . '/app/Action/TaskMoveColumnNotMovedPeriod.php',
|
||||
'Kanboard\\Action\\TaskMoveColumnOnStartDate' => __DIR__ . '/../..' . '/app/Action/TaskMoveColumnOnStartDate.php',
|
||||
'Kanboard\\Action\\TaskMoveColumnUnAssigned' => __DIR__ . '/../..' . '/app/Action/TaskMoveColumnUnAssigned.php',
|
||||
'Kanboard\\Action\\TaskOpen' => __DIR__ . '/../..' . '/app/Action/TaskOpen.php',
|
||||
'Kanboard\\Action\\TaskUpdateStartDate' => __DIR__ . '/../..' . '/app/Action/TaskUpdateStartDate.php',
|
||||
|
|
|
|||
Loading…
Reference in New Issue