From f7bc5f425b2a1be7560096d0ebeb5a879db6a76d Mon Sep 17 00:00:00 2001 From: Tim Clifford Date: Fri, 16 Oct 2020 12:16:07 +0100 Subject: [PATCH] Security headers profile --- Policies/http/http-cache-control.policy.yml | 21 ++++++++ Profiles/algm_sla_site.profile.yml | 4 +- Profiles/security_headers.profile.yml | 19 ++++++++ src/Audit/HttpHeaderRegexChecker.php | 53 +++++++++++++++++++++ 4 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 Policies/http/http-cache-control.policy.yml create mode 100644 Profiles/security_headers.profile.yml create mode 100644 src/Audit/HttpHeaderRegexChecker.php diff --git a/Policies/http/http-cache-control.policy.yml b/Policies/http/http-cache-control.policy.yml new file mode 100644 index 0000000..20e1b6e --- /dev/null +++ b/Policies/http/http-cache-control.policy.yml @@ -0,0 +1,21 @@ +title: "HTTP Cache-Control" +class: \Drutiny\algm\Audit\HttpHeaderRegexChecker +name: algm:HTTP:Cache-Control +description: | + Cache-Control header informs reverse proxies and browsers how to cache your + web page for performance reasons. A cacheable page should also contain the + max-age directive. E.g. `max-age=600; public`. +remediation: | + Your site is choosing not to cache this page for some reason. Drupal sites + in general will cache unless page caching is not enabled or there is an element + on the page that prevents caching from taking place. We recommend you revise your + cache settings and elements in use on this page. +success: | + {{ header }} header found with a {{ regex }} set. +failure: | + {{ header }} header matching {{ regex }} not found in response. +parameters: + header: + default: Cache-Control + regex: + default: 'max-age=' diff --git a/Profiles/algm_sla_site.profile.yml b/Profiles/algm_sla_site.profile.yml index 5228a1f..1c843c0 100644 --- a/Profiles/algm_sla_site.profile.yml +++ b/Profiles/algm_sla_site.profile.yml @@ -66,4 +66,6 @@ policies: blacklist: 'admin, root, drupal, amazee, amazeelabs', status: 1 } - } \ No newline at end of file + } +# include: +# - security_headers diff --git a/Profiles/security_headers.profile.yml b/Profiles/security_headers.profile.yml new file mode 100644 index 0000000..7997c92 --- /dev/null +++ b/Profiles/security_headers.profile.yml @@ -0,0 +1,19 @@ +title: 'Security headers' +name: security_headers +policies: + 'algm:HTTP:Cache-Control': + { + severity: medium, + parameters: { + header: 'Cache-Control', + regex: 'max-age=' + } + } + 'HTTP:Content-Security-Policy': { severity: medium } + 'HTTP:HSTS': { severity: medium } + 'HTTP:ReferrerPolicy': { severity: medium } + 'HTTP:X-Content-Type-Options': { severity: medium } + 'HTTP:X-Frame-Options': { severity: medium } + 'HTTP:X-XSS-Protection': { severity: medium } +format: + html: { template: page, content: [{ heading: Purpose, body: "This report is designed to provide some feedback on the overall health of\nthe web application by performing some deep dive analysis. The items\nsurfaced in the report can help improve performance and stability.\n" }, { heading: 'Reporting period', body: "Period | Date time\n------ | ---------\nStart | {{reporting_period_start}}\nEnd | {{reporting_period_end}}\n" }, { heading: Recommendations, body: "\n" }, { heading: Findings, body: "{{{ severity_stats }}}\n### Issue Summary\n{{{ summary_table }}}\n\n{{#failures}}\n ### Issues\n {{# output_failure }}\n {{{.}}}\n {{/ output_failure }}\n{{/failures}}\n\n{{#warnings}}\n ### Warnings\n {{# output_warning }}\n {{{.}}}\n {{/ output_warning }}\n{{/warnings}}\n" }, { heading: Appendix, body: "{{#notices}}\n ### Appendix - Analysis\n\n The various appendices provides more detailed data regarding the health of\n the site.\n\n {{# output_notice }}\n {{{.}}}\n {{/ output_notice }}\n{{/notices}}\n\n{{#errors}}\n ### Appendix - Errors\n\n During the production of this report, not all report policies were able to\n be carried out due to errors encounted.\n\n {{#output_error}}\n {{{.}}}\n {{/output_error}}\n{{/errors}}\n\n### Appendix - Summary\nThe below table describes all audit and analysis work completed for the\nproduction of this report and their associated outcomes.\n\n{{{ appendix_table }}}\n\n{{#passes}}\n### Appendix - Successful Assessments\n{{# output_success }}\n {{{.}}}\n{{/ output_success }}\n{{/passes}}\n" }] } diff --git a/src/Audit/HttpHeaderRegexChecker.php b/src/Audit/HttpHeaderRegexChecker.php new file mode 100644 index 0000000..a4c24da --- /dev/null +++ b/src/Audit/HttpHeaderRegexChecker.php @@ -0,0 +1,53 @@ +drush([ + 'format' => 'json', + ])->status(); + + $uri = $sandbox->getTarget()->uri(); + if (isset($stats['uri'])) { + $uri = $stats['uri']; + } + + $setUrl = $sandbox->getTarget()->setUri($uri); + + $regex = $sandbox->getParameter('regex'); + $regex = "/$regex/"; + $res = $this->getHttpResponse($sandbox); + $header = $sandbox->getParameter('header'); + + if (!$res->hasHeader($header)) { + return FALSE; + } + $headers = $res->getHeader($header); + return preg_match($regex, $headers[0]); + } +} + +?>