Forum Moderators: rogerd & travelin cat

Message Too Old, No Replies

RE: HTTP Strict Transport Security (HSTS) Policy

         

Gemini23

6:05 pm on Feb 14, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



This is on Wordpress hosted sites that I have but may well also apply to other hosted sites.

Hosted on Siteground

I am getting an F Rating for Security when doing a website speed check

ie
The following security headers are missing from the website:
HIGH SEVERITY
Strict Transport Security
A HSTS Policy informing the HTTP client how long to cache the HTTPS only policy and whether this applies to subdomains.

I understand from Siteground that 'something' needs adding to the .htaccess files on the websites concerned.

Anyone advise?

not2easy

6:53 pm on Feb 14, 2021 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



There are several discussions about implementing HSTS policies, one of the most useful is here: [webmasterworld.com...]

Note - that discussion is from 2017 but it covers some key information and links to resources to assist and inform. I am surprised that your host doesn't offer information because it is my understanding that some options can differ between hosts.

Gemini23

6:59 pm on Feb 14, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Thanks - I contacted siteground today and they only advised that a line of code needed adding to the htaccess but they wouldn't say what it is.

londrum

11:30 am on Feb 15, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



this is what I use in my htaccess file
Header set Strict-Transport-Security "max-age=300; includeSubDomains" env=HTTPS

you're supposed to start with a low number (like 300, which is just five minutes), and slowly raise it as time goes on, to make sure you don't have any problems, because you're locking yourself in to using https

Gemini23

11:43 am on Feb 15, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Thanks Londrum - you just enter that exact code into the htaccess?

londrum

3:44 pm on Feb 15, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



exactly like that, yup

Gemini23

3:49 pm on Feb 15, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Hm... still not working...
I think that maybe the error is that http:// is first redirecting to https://www and not https://.domain



[edited by: not2easy at 3:59 pm (utc) on Feb 15, 2021]
[edit reason] readability [/edit]

not2easy

4:10 pm on Feb 15, 2021 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



If this is a WordPress site, the canonical redirects for protocol/www need to be the last rules in your htaccess file - just before the WP generated snippet. The canonical redirects must agree with the URL entered in the WP settings.

This "Header set" is not a rewrite rule, but it should come before the canonical and WP rewrite rules. If added at the end it may not work as expected. The setting for the HSTS (as shown above) should cover all subdomains - the www. is considered a subdomain for this purpose. The HSTS is only setting the time to expiry and the environment.

Gemini23

4:48 pm on Feb 15, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Hm... still not working... I will have to pay someone to have a look at it.

Gemini23

5:02 pm on Feb 15, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Any comment on this?

RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]

RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L,E=HTTPS:1]
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" env=HTTPS

[edited by: phranque at 10:23 pm (utc) on Feb 15, 2021]
[edit reason] unlinked urls [/edit]

londrum

6:23 pm on Feb 15, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



i'm not entirely sure how this works because i've never had the problem myself, but because you've started using a high number like 31536000, rather than starting low like 300, your browser is going to carry on requesting https from your site for the next 12 months, even if you change it back to http.

not2easy

7:15 pm on Feb 15, 2021 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



My only comment is that I don't know where you got that rewrite, there are many simpler examples here on the forums so you don't need to have a separate rule just for https and another one for www - and they both include the [L] flag which can be part of your problem. It instructs the server to do no further rewrites on the same URL after it passes through the first rule.

Do a search for "to https:" and you will find hundreds if not thousands of better examples that combine the two rules. The "Header set..." should be before the canonical rewrite. Visit the Apache forum or use the search, you will find the right way to do that. I agree with londrum. You altered the suggested fix disregarding the "why" that was included. Where did "Header always set" come from?

Gemini23

7:25 pm on Feb 15, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Thanks - I tried entering the simple line of code and it didn't work... have another issue that needs dealing with re importing into woocommerce not updating... one problem at a time...

phranque

11:31 pm on Feb 15, 2021 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



My only comment is that I don't know where you got that rewrite, there are many simpler examples here on the forums so you don't need to have a separate rule just for https and another one for www

this is normally the case, but if you are planning to implement hstspreload [hstspreload.org] you must do this in two separate redirects:
Redirect from HTTP to HTTPS on the same host, if you are listening on port 80.


Any comment on this?

you should combine the two mod_rewrite rulesets as suggested by not2easy (unless you are implementing htstspreload as referred to above) and additionally tighten up the conditional test for the hostname:
RewriteCond %{HTTPS} !=on [OR]
RewriteCond %{HTTP_HOST} !(^www\.example\.com$)? [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]

- you may not need the "?" or the "[NC]" in the RewriteCond directive on your web host but it doesn't hurt
- i wouldn't bother setting the HTTPS environment variable since you already would have the %{HTTPS} SSL environment variable available when you need it.
(note that you don't want to send the Strict-Transport-Security header with the redirect to https: since that is a response to a http: request):
An HSTS Host MUST NOT include the STS header field in HTTP responses conveyed over non-secure transport.

source: https://tools.ietf.org/html/rfc6797#section-7.2

Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" env=HTTPS

i would try something like this, using the expr argument rather than the env argument:
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" "expr=%{HTTPS} == on"

you can learn more here about Expressions in Apache HTTP Server [httpd.apache.org]

i would also suggest carefully reading all of the hstspreload [hstspreload.org] documentation before implementing the preload directive as well as addressing the required changes in redirects between hostnames mentioned above.

[edited by: phranque at 12:01 am (utc) on Feb 16, 2021]

phranque

11:44 pm on Feb 15, 2021 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



Hm... still not working...

Hm... still not working... I will have to pay someone to have a look at it.

I tried entering the simple line of code and it didn't work

you'll have to work harder on your problem descriptions:
- what request was made?
- what were you expecting in the response?
- what did you see or not see in the response that you were(n't) expecting to see?

I think that maybe the error is that http:// is first redirecting to https://www and not https//.domain

for example if you were expecting to see the HSTS header in response to the http->https redirect, then the problem was likely that the HTTPS environment variable wasn't set.
but since we don't know what you were expecting or what you saw...

phranque

12:01 am on Feb 16, 2021 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



i'm not entirely sure how this works because i've never had the problem myself, but because you've started using a high number like 31536000, rather than starting low like 300, your browser is going to carry on requesting https from your site for the next 12 months, even if you change it back to http.

i haven't tried this myself, but according to the HSTS specification:
NOTE: A max-age value of zero (i.e., "max-age=0") signals the UA to cease regarding the host as a Known HSTS Host, including the includeSubDomains directive (if asserted for that HSTS Host).

source: https://tools.ietf.org/html/rfc6797#section-6.1.1

having noted this, i would also strongly (again) recommend reading the hststpreload documentation, specifically the Deployment Recommendations section and the two sections that follow:
https://hstspreload.org/#deployment-recommendations
be sure to note statements and phrases like the following:
...
Examine all subdomains (and nested subdomains) of your site and make sure that they work properly over HTTPS.
Add the Strict-Transport-Security header to all HTTPS responses and ramp up the max-age in stages, ...

During each stage, check for broken pages and monitor your site's metrics (e.g. traffic, revenue). Fix any problems that come up and then wait the full max-age of the stage before you move on. For example, wait a month in the last stage.
Once you're confident that there will be no more issues, increase the max-age to 2 years and submit your site to the preload list:
...

If you have a group of employees or users who can beta test the deployment, consider trying the first few ramp-up stages on those users. Then make sure to go through all stages for all users, starting over from the beginning.

...

If you maintain a project that provides HTTPS configuration advice or provides an option to enable HSTS, do not include the preload directive by default. We get regular emails from site operators who tried out HSTS this way, only to find themselves on the preload list by the time they find they need to remove HSTS to access certain subdomains. Removal tends to be slow and painful for those sites.

It's great to support HSTS preloading as a best practice, and for projects to provide a simple option to enable it. However, site operators who enable HSTS should know about the long-term consequences of preloading before they turn it on for a given domain. ...

Be aware that inclusion in the preload list cannot easily be undone. Domains can be removed, but it takes months for a change to reach users with a Chrome update and we cannot make guarantees about other browsers. Don't request inclusion unless you're sure that you can support HTTPS for your entire site and all its subdomains in the long term.
...