How to set HSTS header from .htaccess only on HTTPS [closed]
Asked Answered
M

5

94

My web application runs on a different number of hosts that I control. To prevent the need to change the Apache config of each vhost, I add most of the config using .htaccess files in my repo so the basic setup of each host is just a couple of lines. This also makes it possible to change the config upon deploying a new version. Currently the .htaccess (un)sets headers, does some rewrite magic and controls the caching of the UA.

I want to enable HSTS in the application using .htaccess. Just setting the header is easy:

Header always set Strict-Transport-Security "max-age=31536000"

But the spec clearly states: "An HSTS Host MUST NOT include the STS header field in HTTP responses conveyed over non-secure transport.". So I don't want to send the header when sending it over HTTP connections. See https://datatracker.ietf.org/doc/html/draft-ietf-websec-strict-transport-sec-14 .

I tried to set the header using environment vars, but I got stuck there. Anyone that knows how to do that?

Mooring answered 10/6, 2014 at 15:10 Comment(3)
Stack Overflow is a site for programming and development questions. This question appears to be off-topic because it is not about programming or development. See What topics can I ask about here in the Help Center. Perhaps Super User or Unix & Linux Stack Exchange would be a better place to ask. Also see Where do I post questions about Dev Ops?Tillandsia
@Tillandsia The .htaccess files are part of my web app repo and maintained by developers to get the desired behaviour of the application (e.g. caching, rewriting url's, and setting the right headers). The question is viewed nearly 20K times here on SO (and [apache], [.htaccess] and [mod-headers] tags are available). So I don't think it is off topic here.Mooring
"The .htaccess files are part of my web app repo and maintained by developers..." - Neither are criteria for inclusion on Stack Overflow. A good sniff test is, can you show your code? In this case, the answer is NO. After examination, its just an Apache config question. "The question is viewed nearly 20K times..." - Stack Overflow is a dumping ground. An off-topic question is asked here, and then it gets indexed by a search engine. Other examples of the phenomenon include Transferring files over SSH. Developers use SSH on occasion, too.Tillandsia
M
131

Apparently there is a HTTPS environment variable available that can be used easily. For people with the same question:

Header set Strict-Transport-Security "max-age=31536000" env=HTTPS
Mooring answered 10/6, 2014 at 15:31 Comment(8)
what file is this setting made in?Sidoney
@Sidoney it would be in .htaccess file.Electrolyse
For some reason, this doesn't work on my server. Apache 2.4Awoke
Didn't work for me as well; however appending "expr=%{HTTPS} == 'on'"worked. The whole line then is Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" "expr=%{HTTPS} == 'on'". Maybe it's because the alwayskeyword?Bowker
Note that the HTTPS env var in the condition env=HTTPS is different to the server var that we commonly see in mod_rewrite conditions (and Apache expr) as %{HTTPS}. Since this is an env variable, it is dependent on the environment ie. server config. Sometimes it is never set. Sometimes it is assigned the same value as the HTTPS server var (so it is always set to either "off" or "on" - and the condition env=HTTPS is always true! env=HTTPS simply tests whether the env var is set, not that it is "on".) Using an Apache expr as @AdrianFöder suggests is recommended on Apache 2.4+Ranzini
Headers got overwritten somehow when I was running PHP in CGI mode, instead of Module. That's why it didn't work for me. #32147913Awoke
adrian foder answer worked very well, thank you, it required the single quotes on the 'on'Crabtree
Adrian Föder's code didnt work but nielsr worked OK on apache 2.4.43 (strange ?)Clippers
E
34

To build on nielsr's answer, I used the following in the .htaccess to meet the secure deployment recommendations at https://hstspreload.org which will hardcode the domain into the Chrome browser. Be aware this will enforce HSTS across your subdomains, and that inclusion in the preload list cannot easily be undone, so rtfm.

<IfModule mod_headers.c>
Header set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" env=HTTPS
</IfModule>
Elation answered 13/9, 2016 at 2:54 Comment(2)
It's a bit more secure yes - if you only ever intend to use HTTPS across your entire domain. If not, it's incredibly dangerous - and so it's irresponsible to suggest it without warning about that. Let's say your webserver responds with this header to a request at a top level domain (example.com) - then as you are including subdomains any other subdomain served by a different webserver over http only and not https (e.g. intranet.example.com), will not work. Including the preload tag also allows this to be submitted to a preload list so it's hardcoded into web browsers and then is irreversible.Martyr
It's a few years later, so I am just remarking that your snippet is still effective as of today.Skeens
M
13

You can use this and put it on your htaccess file to comply with https://hstspreload.org. put this in your .htaccess file.

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

first, it will do redirection for non https to https. and redirect non www https to www https with HSTS header.

(http://example.com -> https://example.com -> https://www.example.com - with HSTS header)

Tested and comply with https://hstspreload.org

Mettle answered 9/5, 2019 at 16:39 Comment(0)
T
4

For httpd.conf (if you have access to edit this) you can use

<VirtualHost 65.81.122.43:443>
    Header always set Strict-Transport-Security "max-age=31536000; includeSubdomains;"
</VirtualHost>

NOTE : You need to set it on the HTTPS vhost only and cannot be on http vhost.

When should I, and should I not use .htaccess files?

Allowing .htaccess files will make Apache look for them upon every access to your server. Since parent directories are searched as well, this will take some (small) amount of time, and can impact your server's performance. Source

Thirteen answered 17/3, 2017 at 9:50 Comment(1)
Apache will always look for .htaccess files. So unless you have disabled .htaccess lookups this will not improve performance, as Apache will check for the file anyway.Enjoin
P
1

Yet another alternative is to always set the header and conditionally remove it for non-ssl connections:

Header always set   Strict-Transport-Security "max-age=31536000" early
Header        unset Strict-Transport-Security env=!HTTPS

This has the advantage, that the Header directive can be used with both the env condition as well as the early flag. With a single Header directive, env and early cannot be used together, they are mutually exclusive (see official documentation: https://httpd.apache.org/docs/current/mod/mod_headers.html#header).

Prairial answered 15/1, 2019 at 13:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.