From 2a8ba9020fde4deaae0d190b3ca9ae561ee23040 Mon Sep 17 00:00:00 2001 From: Jakub Onderka Date: Wed, 3 Mar 2021 20:06:25 +0100 Subject: [PATCH] new: [internal] Security setting force_https --- app/Controller/AppController.php | 37 +++++++++++++++++++++----------- app/Lib/Tools/SecurityAudit.php | 11 ++++++++-- app/Model/Server.php | 9 ++++++++ 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/app/Controller/AppController.php b/app/Controller/AppController.php index 68349da20..0c7888b4a 100755 --- a/app/Controller/AppController.php +++ b/app/Controller/AppController.php @@ -94,26 +94,19 @@ class AppController extends Controller public function beforeFilter() { $this->_setupBaseurl(); - $this->Auth->loginRedirect = $this->baseurl. '/users/routeafterlogin'; + $this->Auth->loginRedirect = $this->baseurl . '/users/routeafterlogin'; $customLogout = Configure::read('Plugin.CustomAuth_custom_logout'); $this->Auth->logoutRedirect = $customLogout ?: ($this->baseurl . '/users/login'); $this->__sessionMassage(); - if (Configure::read('Security.allow_cors')) { - // Add CORS headers - $this->response->cors($this->request, - explode(',', Configure::read('Security.cors_origins')), - ['*'], - ['Origin', 'Content-Type', 'Authorization', 'Accept']); - if ($this->request->is('options')) { - // Stop here! - // CORS only needs the headers - $this->response->send(); - $this->_stop(); - } + // If server is running behind reverse proxy, PHP will not recognize that user is accessing site by HTTPS connection. + // By setting `Security.force_https` to `true`, session cookie will be set as Secure and CSP headers will upgrade insecure requests. + if (Configure::read('Security.force_https')) { + $_SERVER['HTTPS'] = 'on'; } + $this->__cors(); if (Configure::read('Security.check_sec_fetch_site_header')) { $secFetchSite = $this->request->header('Sec-Fetch-Site'); if ($secFetchSite !== false && $secFetchSite !== 'same-origin' && ($this->request->is('post') || $this->request->is('put') || $this->request->is('ajax'))) { @@ -740,6 +733,24 @@ class AppController extends Controller $this->response->header($header, implode('; ', $header)); } + private function __cors() + { + if (Configure::read('Security.allow_cors')) { + // Add CORS headers + $this->response->cors($this->request, + explode(',', Configure::read('Security.cors_origins')), + ['*'], + ['Origin', 'Content-Type', 'Authorization', 'Accept']); + + if ($this->request->is('options')) { + // Stop here! + // CORS only needs the headers + $this->response->send(); + $this->_stop(); + } + } + } + private function __rateLimitCheck() { $info = array(); diff --git a/app/Lib/Tools/SecurityAudit.php b/app/Lib/Tools/SecurityAudit.php index 1d87b221b..bb9491e84 100644 --- a/app/Lib/Tools/SecurityAudit.php +++ b/app/Lib/Tools/SecurityAudit.php @@ -77,8 +77,15 @@ class SecurityAudit 'https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP', ]; } - if (Configure::read('Security.disable_form_security')) { - $output['Browser'][] = ['error', __('Disabling form security is never a good idea.')]; + if (!env('HTTPS') && strpos(Configure::read('MISP.baseurl'), 'https://') === 0) { + $output['Browser'][] = [ + 'error', + __('MISP base URL is set to https://, but MISP things that the connection is insecure. This usually happens when server is running behind reverse proxy. By setting `Security.force_https` to `true`, session cookie will be set as Secure and CSP headers will upgrade insecure requests.'), + ]; + } + $sessionConfig = Configure::read('Session'); + if (isset($sessionConfig['ini']['session.cookie_secure']) && !$sessionConfig['ini']['session.cookie_secure']) { + $output['Browser'][] = ['error', __('Setting session cookie is not secure is never good idea.')]; } if (empty(Configure::read('Security.advanced_authkeys'))) { diff --git a/app/Model/Server.php b/app/Model/Server.php index e0dc2c339..d7aacbd96 100644 --- a/app/Model/Server.php +++ b/app/Model/Server.php @@ -5693,6 +5693,15 @@ class Server extends AppModel 'type' => 'boolean', 'null' => true, ], + 'force_https' => [ + 'level' => self::SETTING_OPTIONAL, + 'description' => __('If enabled, MISP server will consider all requests as secure. This is usually useful when you run MISP behind reverse proxy that terminates HTTPS.'), + 'value' => false, + 'errorMessage' => '', + 'test' => 'testBool', + 'type' => 'boolean', + 'null' => true, + ], 'email_otp_enabled' => array( 'level'=> 2, 'description' => __('Enable two step authentication with a OTP sent by email. Requires e-mailing to be enabled. Warning: You cannot use it in combination with external authentication plugins.'),