From c55bfc0b8cfa7f9805880ee8978f2325ec98b17a Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 11 Jan 2020 05:28:20 +0100 Subject: [PATCH] Improve config of CSP headers. --- .env.example | 9 ++++- app/Http/Middleware/SecureHeaders.php | 53 ++++++++++++++++++--------- config/firefly.php | 1 + 3 files changed, 45 insertions(+), 18 deletions(-) diff --git a/.env.example b/.env.example index a7d8b4e6be..b25b14f994 100644 --- a/.env.example +++ b/.env.example @@ -161,9 +161,16 @@ WINDOWS_SSO_KEY=AUTH_USER ADLDAP_SYNC_FIELD=userprincipalname # You can disable the X-Frame-Options header if it interferes with tools like -# Organizr. This is at your own risk. +# Organizr. This is at your own risk. Applications running in frames run the risk +# of leaking information to their parent frame. DISABLE_FRAME_HEADER=false +# You can disable the Content Security Policy header when you're using an ancient browser +# or any version of Microsoft Edge / Internet Explorer (which amounts to the same thing really) +# This leaves you with the risk of not being able to stop XSS bugs should they ever surface. +# This is at your own risk. +DISABLE_CSP_HEADER=false + # You can fine tune the start-up of a Docker container by editing these environment variables. # Use this at your own risk. Disabling certain checks and features may result in lost of inconsistent data. # However if you know what you're doing you can significantly speed up container start times. diff --git a/app/Http/Middleware/SecureHeaders.php b/app/Http/Middleware/SecureHeaders.php index 97c847b963..dca47803e6 100644 --- a/app/Http/Middleware/SecureHeaders.php +++ b/app/Http/Middleware/SecureHeaders.php @@ -25,7 +25,6 @@ namespace FireflyIII\Http\Middleware; use Closure; use Illuminate\Http\Request; -use Illuminate\Support\Str; /** * @@ -44,27 +43,22 @@ class SecureHeaders */ public function handle(Request $request, Closure $next) { + // generate and share nonce. $nonce = base64_encode(random_bytes(16)); app('view')->share('JS_NONCE', $nonce); - $response = $next($request); - $google = ''; - $googleImg = ''; - $analyticsId = config('firefly.analytics_id'); - - if ('' !== $analyticsId) { - $google = 'https://www.googletagmanager.com/gtag/js https://www.google-analytics.com/analytics.js'; // @codeCoverageIgnore - $googleImg = 'https://www.google-analytics.com/'; - } - $csp = [ + $response = $next($request); + $googleScriptSrc = $this->getGoogleScriptSource(); + $googleImgSrc = $this->getGoogleImgSource(); + $csp = [ "default-src 'none'", "object-src 'self'", - sprintf("script-src 'unsafe-inline' %s 'nonce-%s'", $nonce, $google), + sprintf("script-src 'unsafe-inline' %s 'nonce-%s'", $googleScriptSrc, $nonce), "style-src 'self' 'unsafe-inline'", "base-uri 'self'", "font-src 'self' data:", "connect-src 'self'", - sprintf("img-src 'self' data: https://api.tiles.mapbox.com %s", $googleImg), + sprintf("img-src 'self' data: https://api.tiles.mapbox.com %s", $googleImgSrc), "manifest-src 'self'", ]; @@ -90,12 +84,11 @@ class SecureHeaders ]; $disableFrameHeader = config('firefly.disable_frame_header'); - if (false === $disableFrameHeader || null === $disableFrameHeader) { + $disableCSP = config('firefly.disable_csp_header'); + if (false === $disableFrameHeader) { $response->header('X-Frame-Options', 'deny'); } - - // content security policy may be set elsewhere. - if (!$response->headers->has('Content-Security-Policy')) { + if (false === $disableCSP && !$response->headers->has('Content-Security-Policy')) { $response->header('Content-Security-Policy', implode('; ', $csp)); } $response->header('X-XSS-Protection', '1; mode=block'); @@ -105,4 +98,30 @@ class SecureHeaders return $response; } + + /** + * @return string + */ + private function getGoogleImgSource(): string + { + if ('' !== config('firefly.analytics_id')) { + return 'https://www.google-analytics.com/'; + } + + return ''; + } + + /** + * Return part of a CSP header allowing scripts from Google. + * + * @return string + */ + private function getGoogleScriptSource(): string + { + if ('' !== config('firefly.analytics_id')) { + return 'https://www.googletagmanager.com/gtag/js https://www.google-analytics.com/analytics.js'; + } + + return ''; + } } diff --git a/config/firefly.php b/config/firefly.php index 98b7e99369..8e2b3d9664 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -154,6 +154,7 @@ return [ 'send_report_journals' => envNonEmpty('SEND_REPORT_JOURNALS', true), 'analytics_id' => env('ANALYTICS_ID', ''), 'disable_frame_header' => env('DISABLE_FRAME_HEADER', false), + 'disable_csp_header' => env('DISABLE_CSP_HEADER', false), 'login_provider' => envNonEmpty('LOGIN_PROVIDER', 'eloquent'), 'cer_provider' => envNonEmpty('CER_PROVIDER', 'fixer'), 'update_endpoint' => 'https://version.firefly-iii.org/index.json',