"Strict-Transport-Security" HTTP header (HSTS)

Whoopsie, mixed up
Header always set Referrer-Policy "strict-origin"
with
Header always set X-Frame-Options "sameorigin"

referrer-policy: strict-origin

As you can see, the second header line overrides the first.
Please try to remove Header always set Referrer-Policy "strict-origin" line as well to be most strict.

Check out the result of the different directives: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy#Directives


But this shows, that the other headers are set as expected, just HSTS somehow wrong:

strict-transport-security: max-age=0; includeSubDomains; preload

Hmm strange, as my config line looks exactly the same… and where is the preload option coming from?..

Certbot places an own security config file that is loaded after you set your headers. See in your config at the bottom: Include /etc/letsencrypt/options-ssl-apache.conf

Please check this file, as perhaps it overrides your HSTS.

And again, for debugging please try as well to remove (or comment out) <IfModule mod_headers.c> and </IfModule> around the header section.

preload does only work if the domain is added to the preload-list:

https://hstspreload.org/

But be careful and know what you are doing.

1 Like

Jep, but doesn’t hurt, if it is added. I have this in my config since ages, but as my Nextcloud runs on a subdomain, it cannot be added to the preload-list, thus the option is just ignored :wink:.

Michalng thank you very much for your help first of all i have the following :slight_smile:

# cat /etc/letsencrypt/options-ssl-apache.conf
# This file contains important security parameters. If you modify this file
# manually, Certbot will be unable to automatically provide future security
# updates. Instead, Certbot will print and log an error message with a path to
# the up-to-date file that you will need to refer to when manually updating
# this file.

SSLEngine on

# Intermediate configuration, tweak to your needs
SSLProtocol             all -SSLv2 -SSLv3
SSLCipherSuite          ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS
SSLHonorCipherOrder     on
SSLCompression          off

SSLOptions +StrictRequire

# Add vhost name to log entries:
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" vhost_combined
LogFormat "%v %h %l %u %t \"%r\" %>s %b" vhost_common

#CustomLog /var/log/apache2/access.log vhost_combined
#LogLevel warn
#ErrorLog /var/log/apache2/error.log

# Always ensure Cookies have "Secure" set (JAH 2012/1)
#Header edit Set-Cookie (?i)^(.*)(;\s*secure)??((\s*;)?(.*)) "$1; Secure$3$4" 

my vhost file looks like this now

 <IfModule mod_ssl.c>
<VirtualHost *:443>

        ServerName cloud.mydomain.org
        ServerAdmin webmaster@localhost

Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains"
Header always set Referrer-Policy "no-referrer"

# Prevent MIME based attacks
Header set X-Content-Type-Options "nosniff"

SSLEngine on
SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
SSLProtocol All -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
SSLHonorCipherOrder On

        ProxyPreserveHost On
        ProxyPass / http://192.168.1.10:80/
        ProxyPassReverse / http://192.168.1.10:80/

        ErrorLog ${APACHE_LOG_DIR}/cloud.mydomain.org-error.log
        CustomLog ${APACHE_LOG_DIR}/cloud.mydomain.org-access.log combined

SSLCertificateFile /etc/letsencrypt/live/cloud.mydomain.org/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/cloud.mydomain.org/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>

and if i issue again " curl -s -D- https://cloud.domain.com "

# curl -s -D- https://cloud.mydomain.com
HTTP/2 302
date: Tue, 09 Oct 2018 14:14:23 GMT
content-type: text/html; charset=UTF-8
set-cookie: __cfduid=d806abf8129081a9efacfabaf86fa9a041539094463; expires=Wed, 09-Oct-19 14:14:23 GMT; path=/; domain=.mydomain.com; HttpOnly; Secure
strict-transport-security: max-age=0; includeSubDomains; preload
referrer-policy: no-referrer
expires: Thu, 19 Nov 1981 08:52:00 GMT
cache-control: no-store, no-cache, must-revalidate
pragma: no-cache
content-security-policy: default-src 'self'; script-src 'self' 'unsafe-eval' 'nonce-TEpsSW9BU3BtYWYrN1dXcWJNeWJNLzcvMldpUDNqVmxLTm1ocGFqRnVlST06ZTZBOTVHWDgvdUt5dXlqZFZZS3RWYTJJblFmcWpRY1VHb0RQOWNhR2o0QT0='; style-src 'self' 'unsafe-inline'; frame-src *; img-src * data: blob:; font-src 'self' data:; media-src *; connect-src *; object-src 'none'; base-uri 'self';
x-frame-options: SAMEORIGIN
location: https://cloud.mydomain.com/index.php/login
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
x-robots-tag: none
x-download-options: noopen
x-permitted-cross-domain-policies: none
set-cookie: ocz9mx9tsb1o=0c6kcvtmp03ron1pvsae7f64rh; path=/; secure; HttpOnly
set-cookie: oc_sessionPassphrase=3bGcTDE9wlDFlL%2FyWUY%2FTY90krGiwkC%2Bu%2FFXwrM%2BFFofW9wYL65gAe2PPnodV2cKygtrlEC3xPNUxSoFyjJyhv4LIE1G8nBVXuFlFsYK5gt2NZt9eOVyL4XF6t7mAAtV; path=/; secure; HttpOnly
set-cookie: __Host-nc_sameSiteCookielax=true; path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax
set-cookie: __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=strict
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
server: cloudflare
cf-ray: 4671740b8c08acae-OTP

so it seems there is no change or i don’t understand what configuration file it’s rewriting my header:

strict-transport-security: max-age=0; includeSubDomains; preload

Okay, so finally referrer-policy: no-referrer is good.

As you can see, your vhost and the letsencrypt config file double several directives. This does not seem to break something, but you could clean up your configs a bid.
You could try to comment the SSLProtocol and SSLCipherSuite lines from letsencrypt config (or optionally comment the Include /etc/letsencrypt/options-ssl-apache.conf, to not load this at all) and see if still all your browsers/clients can communicate with your webserver. Your procotol line is stricter, but not sure about the cipher :thinking:.

However still HSTS not resolved :sweat_smile:. Hmm I am out of ideas.

  • Based on your vhost config, there is no further config included that could override HSTS, besides maybe /conf-enabled/* is included after /sites-enabled/*
  • Please run grep -rnw '/etc/apache2' -e 'Strict-Transport' to check for all apache config files that set this header. Perhaps there is a forgotten config overriding this somehow…
  • As last resort: grep -rnw '/etc/apache2' -e 'Include' to check for all perhaps external config inclusions.

okay so i have this

#  grep -rnw '/etc/apache2' -e 'Strict-Transport'
/etc/apache2/sites-available/001-cloud.mydomain.com-le-ssl.conf:14:Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains"
/etc/apache2/sites-available/default-ssl.conf:5:		Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains"
/etc/apache2/sites-available/001-cloud.mydomain.com-le-ssl.conf.bak:15:Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains"

# grep -rnw '/etc/apache2' -e 'Include'
/etc/apache2/sites-available/001-cloud.mydomain.com-le-ssl.conf:42:     #Include conf-available/serve-cgi-bin.conf
/etc/apache2/sites-available/001-cloud.mydomain.com-le-ssl.conf:47:Include /etc/letsencrypt/options-ssl-apache.conf
/etc/apache2/sites-available/default-ssl.conf:23:               #Include conf-available/serve-cgi-bin.conf
/etc/apache2/sites-available/001-cloud.mydomain.com.conf:31:    #Include conf-available/serve-cgi-bin.conf
/etc/apache2/apache2.conf:145:# Include module configuration:
/etc/apache2/apache2.conf:149:# Include list of ports to listen on
/etc/apache2/apache2.conf:150:Include ports.conf
/etc/apache2/apache2.conf:218:# Include of directories ignores editors' and dpkg's backup files,
/etc/apache2/apache2.conf:221:# Include generic snippets of statements
/etc/apache2/apache2.conf:224:# Include the virtual host configurations:

Okay, I guess 001-cloud.mydomain.com-le-ssl.conf is the only one of the three that is enabled (linked to sites-enabled/), right?
To quick check: ls -l /etc/apache2/sites-enabled/

Somehow the grep above does not match IncludeOptional, to be failsafe, you can check as well: grep -rnw '/etc/apache2' -e 'IncludeOptional'

Besides, everything looks like it should :thinking:.

# ls -l /etc/apache2/sites-enabled/

lrwxrwxrwx 1 root root 50 Oct  3 20:22 001-cloud.mydomain.com.conf -> ../sites-available/001-cloud.mydomain.com.conf
lrwxrwxrwx 1 root root 67 Oct  3 20:25 001-cloud.mydomain.com-le-ssl.conf -> /etc/apache2/sites-available/001-cloud.mydomain.com-le-ssl.conf

# grep -rnw '/etc/apache2' -e 'IncludeOptional'
/etc/apache2/apache2.conf:146:IncludeOptional mods-enabled/*.load
/etc/apache2/apache2.conf:147:IncludeOptional mods-enabled/*.conf
/etc/apache2/apache2.conf:222:IncludeOptional conf-enabled/*.conf
/etc/apache2/apache2.conf:225:IncludeOptional sites-enabled/*.conf

I am really not sure, if externally there can be headers injected/changed, e.g. by antivirus software that intrusively inject their scripts into the SSL connections, or by services like cloudflare and such. But from your webserver config, at least I cannot find anything wrong.

Hopefully we have some cracks here, that have further ideas.

So main issue is, even that vhost truly sets HSTS correctly and no other webserver config overwrites this header, curl test (and Nextcloud self-check) reports HSTS being set wrong, interestingly with preload option that is never set at all.

should i open a ticket for cloudflare to ask them ?

Ah nice, I have access to a domain on cloudflare. Jep, you can enable HSTS there and this only makes sense, if this overrides local server settings. curl on the domain in my case does not show any HSTS header, the switch is disabled in cloudflare settings and header not set in webserver config as well.

So I guess it’s the following:

  • cloudflare HSTS overrides webserver setting
  • If you enable HSTS on webserver, but it is disabled on cloudflare, cloudflare will overwrite the header with max-age=0, otherwise it leaves this untouched.

So it seems that you need to enable/configure HSTS on cloudflare web panel then.

2 Likes

Hi Michalng , you were right i did the changes on my cloudflare account and now all the security checks are green:

All checks passed

Thank you very much for your help.

You’re welcome. And we leaned something quite important about cloudflare. Since it is widely used, there might be more people stumble over this.

Cloudflare? If Security and Privacy matters, then you shouldn’t use Cloudflare.

Not the first time I read this. But seems like a kind of trade-off between the features it offers and privacy. Also read that compared to other large providers it does very good in terms pig privacy. Do you know better alternatives with similar CDN, always-online etc features?

@dimostin
Maybe you can mark the topic as solved and add cloudflare to the topic name, so others can easily find it, perhaps just “Cloudflare and "Strict-Transport-Security" HTTP header (HSTS):thinking:.

Well let’s not steal up this thread for further discussion. Just one thought: The fact you’re using Nextcloud shows, that you are concerned about Privacy. So why you’re bringing in another 3rd party as man-in-the-middle giving him your DNS? Where is the difference to any other 3rd party Cloud Provider then?

At least, using Nextcloud, the data itself is on your own server, inaccessible to Cloudflare (or any other provider). And you still have full control over your servers security settings as last instance. But yeah you are right, this is off-topic :wink: .

I should make other modification to my post or i should do other thing ?
My situation it’s resolved now thanks to MihaIng.
Thank you very much again MichaIng, was very nice from you to help me out.

No I just though the header/topic could be renamed for this to be most helpful for others. You can rename the header by editing the first post, AFAIK. But was just an idea, no must :wink:.

By mark as solved, I mean to click the solve button on the best answering reply. By this when searching the forum, other users directly see that there is no additional support needed any more and the “solving” answer is linked inside the opening post, so users with similar issue don’t need to read all posts to finally find the solution.

THANK YOU!

1 Like