From 7eea2476ca72c0b15ccc154f9f5c564b7a96cdfd Mon Sep 17 00:00:00 2001 From: Matt Kilgore Date: Mon, 3 May 2021 12:42:06 -0400 Subject: [PATCH] Harden Headers (#2721) * Basic security headers * Remove XSS Header (not relevent) * Fix config name * Use Arr::get() * Add tests * Re-fix the StoreConfig step for fresh installs Co-authored-by: luceos Co-authored-by: Alexander Skvortsov --- src/Admin/AdminServiceProvider.php | 4 +- src/Forum/ForumServiceProvider.php | 2 + .../Middleware/ContentTypeOptionsHeader.php | 25 ++++++++++++ src/Http/Middleware/ReferrerPolicyHeader.php | 34 ++++++++++++++++ src/Install/Steps/StoreConfig.php | 5 ++- .../middleware/ContentTypeOptionsTest.php | 28 +++++++++++++ .../middleware/ReferrerPolicyTest.php | 39 +++++++++++++++++++ 7 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 src/Http/Middleware/ContentTypeOptionsHeader.php create mode 100644 src/Http/Middleware/ReferrerPolicyHeader.php create mode 100644 tests/integration/middleware/ContentTypeOptionsTest.php create mode 100644 tests/integration/middleware/ReferrerPolicyTest.php diff --git a/src/Admin/AdminServiceProvider.php b/src/Admin/AdminServiceProvider.php index 4fd20f77f..f07da123b 100644 --- a/src/Admin/AdminServiceProvider.php +++ b/src/Admin/AdminServiceProvider.php @@ -59,7 +59,9 @@ class AdminServiceProvider extends AbstractServiceProvider HttpMiddleware\SetLocale::class, 'flarum.admin.route_resolver', HttpMiddleware\CheckCsrfToken::class, - Middleware\RequireAdministrateAbility::class + Middleware\RequireAdministrateAbility::class, + HttpMiddleware\ReferrerPolicyHeader::class, + HttpMiddleware\ContentTypeOptionsHeader::class ]; }); diff --git a/src/Forum/ForumServiceProvider.php b/src/Forum/ForumServiceProvider.php index 9ea0df61c..6cdd80908 100644 --- a/src/Forum/ForumServiceProvider.php +++ b/src/Forum/ForumServiceProvider.php @@ -73,6 +73,8 @@ class ForumServiceProvider extends AbstractServiceProvider HttpMiddleware\CheckCsrfToken::class, HttpMiddleware\ShareErrorsFromSession::class, HttpMiddleware\FlarumPromotionHeader::class, + HttpMiddleware\ReferrerPolicyHeader::class, + HttpMiddleware\ContentTypeOptionsHeader::class ]; }); diff --git a/src/Http/Middleware/ContentTypeOptionsHeader.php b/src/Http/Middleware/ContentTypeOptionsHeader.php new file mode 100644 index 000000000..f78ec9049 --- /dev/null +++ b/src/Http/Middleware/ContentTypeOptionsHeader.php @@ -0,0 +1,25 @@ +handle($request); + + return $response->withAddedHeader('X-Content-Type-Options', 'nosniff'); + } +} diff --git a/src/Http/Middleware/ReferrerPolicyHeader.php b/src/Http/Middleware/ReferrerPolicyHeader.php new file mode 100644 index 000000000..fd1769542 --- /dev/null +++ b/src/Http/Middleware/ReferrerPolicyHeader.php @@ -0,0 +1,34 @@ +policy = Arr::get($config, 'headers.referrerPolicy') ?? 'same-origin'; + } + + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface + { + $response = $handler->handle($request); + + return $response->withAddedHeader('Referrer-Policy', $this->policy); + } +} diff --git a/src/Install/Steps/StoreConfig.php b/src/Install/Steps/StoreConfig.php index 163b75b60..63fa75ad6 100644 --- a/src/Install/Steps/StoreConfig.php +++ b/src/Install/Steps/StoreConfig.php @@ -55,10 +55,13 @@ class StoreConfig implements Step, ReversibleStep { return [ 'debug' => $this->debugMode, - 'poweredByHeader' => true, 'database' => $this->dbConfig->toArray(), 'url' => (string) $this->baseUrl, 'paths' => $this->getPathsConfig(), + 'headers' => [ + 'poweredByHeader' => true, + 'referrerPolicy' => 'same-origin', + ] ]; } diff --git a/tests/integration/middleware/ContentTypeOptionsTest.php b/tests/integration/middleware/ContentTypeOptionsTest.php new file mode 100644 index 000000000..4109b57d6 --- /dev/null +++ b/tests/integration/middleware/ContentTypeOptionsTest.php @@ -0,0 +1,28 @@ +send( + $this->request('GET', '/') + ); + $this->assertEquals(200, $response->getStatusCode()); + $this->assertArrayHasKey('X-Content-Type-Options', $response->getHeaders()); + $this->assertEquals('nosniff', $response->getHeader('X-Content-Type-Options')[0]); + } +} diff --git a/tests/integration/middleware/ReferrerPolicyTest.php b/tests/integration/middleware/ReferrerPolicyTest.php new file mode 100644 index 000000000..734f0082b --- /dev/null +++ b/tests/integration/middleware/ReferrerPolicyTest.php @@ -0,0 +1,39 @@ +send( + $this->request('GET', '/') + ); + $this->assertEquals(200, $response->getStatusCode()); + $this->assertArrayHasKey('Referrer-Policy', $response->getHeaders()); + } + + /** + * @test + */ + public function has_default_referer_policy() + { + $response = $this->send( + $this->request('GET', '/') + ); + $this->assertEquals(200, $response->getStatusCode()); + $this->assertEquals('same-origin', $response->getHeader('Referrer-Policy')[0]); + } +}