diff --git a/modules/backend/assets/js/backend.js b/modules/backend/assets/js/backend.js index 9a368ccc6..97f44aa83 100644 --- a/modules/backend/assets/js/backend.js +++ b/modules/backend/assets/js/backend.js @@ -2,6 +2,18 @@ * October General Utilities */ +/* + * Ensure the CSRF token is added to all AJAX requests. + */ + +$.ajaxPrefilter(function(options) { + var token = $('meta[name="csrf-token"]').attr('content') + + if (token) { + options.headers['X-CSRF-TOKEN'] = token + } +}) + /* * Implement "Sweet Alert" with AJAX framework */ diff --git a/modules/backend/classes/Controller.php b/modules/backend/classes/Controller.php index 66f732180..c401c815e 100644 --- a/modules/backend/classes/Controller.php +++ b/modules/backend/classes/Controller.php @@ -118,6 +118,11 @@ class Controller extends Extendable */ protected $statusCode = 200; + /** + * @var bool Determine if submission requests use CSRF protection. + */ + public $useSecurityToken = true; + /** * Constructor. */ @@ -168,6 +173,13 @@ class Controller extends Extendable $this->action = $action; $this->params = $params; + /* + * Check security token. + */ + if ($this->useSecurityToken && !$this->verifyCsrfToken()) { + return Response::make(Lang::get('backend::lang.page.invalid_token.label'), 403); + } + /* * Extensibility */ @@ -596,4 +608,27 @@ class Controller extends Extendable $hiddenHints = UserPreferences::forUser()->get('backend::hints.hidden', []); return array_key_exists($name, $hiddenHints); } + + // + // CSRF Protection + // + + /** + * Checks the request data / headers for a valid CSRF token. + * Returns false if a valid token is not found. + * @return bool + */ + protected function verifyCsrfToken() + { + if (in_array(Request::method(), ['HEAD', 'GET', 'OPTIONS'])) { + return true; + } + + $token = Request::input('_token') ?: Request::header('X-CSRF-TOKEN'); + + return \Symfony\Component\Security\Core\Util\StringUtils::equals( + Session::getToken(), + $token + ); + } } diff --git a/modules/backend/lang/en/lang.php b/modules/backend/lang/en/lang.php index 40404fb00..f9015d2e9 100644 --- a/modules/backend/lang/en/lang.php +++ b/modules/backend/lang/en/lang.php @@ -18,6 +18,9 @@ return [ 'label' => 'Access denied', 'help' => "You don't have the required permissions to view this page.", 'cms_link' => 'Return to the back-end' + ], + 'invalid_token' => [ + 'label' => 'Invalid security token' ] ], 'partial' => [ diff --git a/modules/backend/layouts/_head.htm b/modules/backend/layouts/_head.htm index 5eb515183..91b4a7616 100644 --- a/modules/backend/layouts/_head.htm +++ b/modules/backend/layouts/_head.htm @@ -2,6 +2,7 @@ +