Kibana: Harden default Kibana security headers

Created on 11 Dec 2019  ·  9Comments  ·  Source: elastic/kibana

Kibana currently uses a Content-Security-Policy header by default, but no others. Industry best practices dictate that many other security headers should be utilized.

In the past we have advised users to set any desired security headers with server.customResponseHeaders. However, this has the following negative impacts:

  1. It prevents us from providing secure default headers that are modifiable, and
  2. It reduces visibility of any headers that we intentionally don't set by default (such as X-Frame-Options) because that would break some Kibana installations

A https://securityheaders.com/ scan of a default Kibana instance, with TLS enabled, produced this report:


click to see report

image

I propose adding individual configuration options for the following headers:

| Header | Default |
|---------------------------|-------------------------------------|
| Strict-Transport-Security | max-age=31536000 |
| X-Content-Type-Options | nosniff |
| Referrer-Policy | no-referrer-when-downgrade |
| X-XSS-Protection* | 1; mode=block |
| X-Frame-Options | |

_*Note: the X-XSS-Protection header is no longer needed in modern browsers when using a strong Content-Security-Policy header, but Kibana still supports IE11 so we should implement it._

Additional headers that we may consider adding in the future as browser support increases are Expect-CT and Feature-Policy.


Larry edit 2020-10-29:

We do not use the Vary:Origin header
The Mozilla docs say:
If the server sends a response with an Access-Control-Allow-Origin value that is an explicit origin (rather than the "*" wildcard), then the response should also include a Vary response header with the value Origin — to indicate to browsers that server responses can differ based on the value of the Origin request header.

Cache time limit
a preflight response is configured to be cached for a prolonged amount of
time. The time a response is allowed to be cached is conveyed using an
Access-Control-Max-Age response header and a value more than 30 minutes is
considered to be prolonged.

Hardening Security enhancement

All 9 comments

Pinging @elastic/kibana-security (Team:Security)

With regard to Strict-Transport-Security, I'm hesitant for us to use the includeSubDomains option as it's possible Kibana is hosted on a mixed http/https domain with subdomains, and this would potentially affect the other subdomains. Similarly, if Kibana is hosted on a base-path, even without the includeSubDomains option we could potentially be affecting the behavior of other "sites" or installations of Kibana.

With regard to Referrer-Policy, we currently want for the referrer information to be included when navigating between Kibana and an Elastic domain per https://github.com/elastic/eui/pull/1565. Wouldn't setting this response header prevent our ideal behavior?

With regard to Strict-Transport-Security, I'm hesitant for us to use the includeSubDomains option as it's possible Kibana is hosted on a mixed http/https domain with subdomains, and this would potentially affect the other subdomains. Similarly, if Kibana is hosted on a base-path, even without the includeSubDomains option we could potentially be affecting the behavior of other "sites" or installations of Kibana.

Seems reasonable, I agree we can omit includeSubDomains for the default.

With regard to Referrer-Policy, we currently want for the referrer information to be included when navigating between Kibana and an Elastic domain per elastic/eui#1565. Wouldn't setting this response header prevent our ideal behavior?

@legrego pointed this out to me earlier in another channel, so I have a call scheduled with someone from the appropriate team this week to discuss and make sure this is adequate for our needs.

Setting this header would prevent the path and query params from being sent in the Referer header. For example, if the user is on a dashboard page: https://kibana.example.com/app/kibana#/dashboards?_g=(refreshInterval:(pause:!f,value:900000),time:(from:now-7d,to:now))
Today, if they click an *.elastic.co link, the following header will be sent:

Referer: https://kibana.example.com/app/kibana

With this change and using Referrer-Policy: strict-origin-when-cross-origin, the following would be sent instead:

Referer: https://kibana.example.com

Because of the way Kibana's apps utilize fragments in URLs, this honestly isn't a big improvement from a security perspective. But the lack of a Referrer-Policy header will start showing up on security scans as various tools are updated to look for it, so we should probably include it by default if possible.

Note: need to reach consensus on prefix for header config values -- probably either server.securityHeaders.* or server.headers.*. We'll want to rename the CSP config values to use this prefix as well. Started discussing in a comment on #52698.

Regarding Referrer-Policy again:

Seeing as we already don't expose much information in the path, I've changed that to default to no-referrer-when-downgrade -- this will send the path when referred to HTTPS sites, and will omit the header entirely when referred to HTTP sites. This seems reasonable to ensure we don't break any systems that may be dependent on the path in the Referer header.

I would like us to restart this discussion for 8.0. We should enable some sensible defaults and have an option for customers to disable specific headers if needed.

I think the defaults @jportner has in the first comment make sense, the only one missing is X-Frame-Options, which I think we should set to "sameorigin"

/cc @legrego

I think the defaults @jportner has in the first comment make sense, the only one missing is X-Frame-Options, which I think we should set to "sameorigin"

Agree. Since that would be a breaking change, perhaps we should aim to change the defaults for everything else in 7.x, and change the default for X-Frame-Options in 8.0.

We should consider replacing or supplementing X-Frame-Options with the CSP frame-ancestors directive, which obsoletes X-Frame-Options in supported browsers (IE11 is unsupported).

I do wonder about usability here though. Users can customize their CSP via csp.rules today in their yml config, but the ability to embed Kibana shouldn't require users to understand CSP in its entirety in order to make Kibana embeddable. So that makes me think that we'd want a different setting to allow Kibana to be embedded, which then influences the CSP and X-Frame-Options header.

So that makes me think that we'd want a different setting to allow Kibana to be embedded, which then influences the CSP and X-Frame-Options header.

👍

Was this page helpful?
0 / 5 - 0 ratings