Server: add_header X-Frame-Options SAMEORIGIN is added somewhere in NextCloud 13

Created on 6 Feb 2018  Â·  66Comments  Â·  Source: nextcloud/server

Steps to reproduce

In the whole /etc/nginx it is only just one place where is:

if ( $x_frame_options = "") {
        set $x_frame_options "SAMEORIGIN";
}
ssl on;
#gzip off;
#add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header Strict-Transport-Security "max-age=31536000; " always;
add_header X-Frame-Options $x_frame_options;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";

Expected behaviour

On my server it is right and every web sites, like this:
image

Actual behaviour

But in NextCloud 13 somewhere it adds in itself and because it adds 2 times for sure and is not NGINX or PHP, because I can show you many pictures, that is right:
image

Actually, I only use in /etc/nginx so it not anywhere, I look for, and I only there in NGINX:

root@server:/etc/nginx# find -type f | xargs egrep -i x-frame-options
./default-ssl-base.conf:add_header X-Frame-Options $x_frame_options;

So only once!

Server configuration

Operating system:
Linux server 4.12.0-2-amd64 #1 SMP Debian 4.12.13-1 (2017-09-19) x86_64 GNU/Linux

Web server:
nginx/1.13.8

Database:
mariadb Ver 15.1 Distrib 10.1.29-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2

PHP version:
PHP 7.2.1-1 (cli) (built: Jan 5 2018 11:21:04) ( NTS )

Nextcloud version: (see Nextcloud admin page)
13

enhancement needs info security

Most helpful comment

Some headers are set in PHP, some are set in .htaccess/nginx. This inconsistency is really bad.

I found them on three different locations:
https://github.com/nextcloud/server/blob/da6c2c9da1721de7aa05b15af1356e3511069980/lib/private/legacy/response.php#L251-L272
https://github.com/nextcloud/documentation/blob/b7dec9a1cab21cf637914073b096eeda44608f1c/admin_manual/installation/nginx.rst#nextcloud-in-the-webroot-of-nginx
https://github.com/nextcloud/documentation/blob/b7dec9a1cab21cf637914073b096eeda44608f1c/admin_manual/configuration_server/harden_server.rst#serve-security-related-headers-by-the-web-server

Things are even worse if you run NextCloud behind a reverse proxy. The headers in the PHP file are not really customizable.
I would prefer setting them only in the server config and display a warning in the setup check.

All 66 comments

Actually I found this:
lib/private/legacy/response.php: header('X-Frame-Options: SAMEORIGIN'); // Disallow iFraming from other domains

If I remove this code, then my Nginx works, but it places dual headers and it senses that my config is wrong.

lib/private/legacy/response.php line 262. that is the bug

This is the actual bug (i commented and now all warning removed):
image

image

This is the actual bug (i commented and now all warning removed):

We don't support that this is set by the web server. The Nginx should not add this header. Fro your point in the call route we are not able to detect if it will be added by the web server or not and thus we add it there because this then needs fewer tweaking of the webserver itself.

This is thus not a bug but an enhancement to also support web servers that somehow set it.

See also #4605, #4863, #5246

Some headers are set in PHP, some are set in .htaccess/nginx. This inconsistency is really bad.

I found them on three different locations:
https://github.com/nextcloud/server/blob/da6c2c9da1721de7aa05b15af1356e3511069980/lib/private/legacy/response.php#L251-L272
https://github.com/nextcloud/documentation/blob/b7dec9a1cab21cf637914073b096eeda44608f1c/admin_manual/installation/nginx.rst#nextcloud-in-the-webroot-of-nginx
https://github.com/nextcloud/documentation/blob/b7dec9a1cab21cf637914073b096eeda44608f1c/admin_manual/configuration_server/harden_server.rst#serve-security-related-headers-by-the-web-server

Things are even worse if you run NextCloud behind a reverse proxy. The headers in the PHP file are not really customizable.
I would prefer setting them only in the server config and display a warning in the setup check.

@MorrisJobke Yeah, it says add it in NGINX, then you tell me to remove from NGINX. so which one we should use??? I think server settings is better, what do you think?

Right now it is chaos.

@J0WI yeah, exactly, what i mean, you cought it!

From a security perspective it also makes more scene to add security settings in the server config, which is harder to hijack in the case of a possible vulnerability in the PHP app.

Edit: And the webserver is also able to set the security headers if PHP is broken for whatever reason.

@J0WI Server is better, but if you want to use PHP, you should comment properly, i think, but of course, we cannot document, and code and fix and etc at once. So understand. I will remove the NGINX settings and I purely set it up for PHP, that's the best right? Like add modHeadersAvailable to the ENV. That's in done on PHP without NGINX or APACHE.

@p3x-robot you can also use proxy_hide_header or fastcgi_hide_header in your nginx config to hide the headers set by PHP:
```
proxy_hide_header X-Content-Type-Options;
fastcgi_hide_header X-XSS-Protection;

well, i just change my server, removed that and that's it. :) it works, awesome. THANKS!

The biggest problem with that is that also there are users, that can't configure this in the webserver because they use a shared hoster. We try to make it as easy as possible for everybody :/ And sorry for the mess.

Could you open a ticket (or even better a PR) in the documentation repo to give hints for this setting in the web server, @J0WI?

@MorrisJobke i just uncommeted that i hacked:
lib/private/legacy/response.php: header('X-Frame-Options: SAMEORIGIN'); // Disallow iFraming from other domains line 262 and i removed the X-Frame-Options from NGINX and then it works.
If now Nextcloud 13 works like this, of course we have ot upgrade and update our nginx server settings,
That's all, Now pass all checks...

The biggest problem with that is that also there are users, that can't configure this in the webserver because they use a shared hoster.

@MorrisJobke shared hoster tend to allow .htaccess (which is also shipped with NextCloud).
I can open a PR for the docs, but for me it's just a workaround. The issue is that headers are set by PHP (which is not really secure) and are not customizable.

Is there a way for a php script to test if the headers are set by the webserver? So that php only adds them if they are not set via webserver. We could enable them by default and provide a configuration switch in case you can activate it on the webserver (the developers probably won't like to add another configuration option).

Is there a way for a php script to test if the headers are set by the webserver? So that php only adds them if they are not set via webserver.

Not really, because the web server adds them after PHP send out the final response ... so it is more up to the web server to check if it is already set.

We could enable them by default and provide a configuration switch in case you can activate it on the webserver (the developers probably won't like to add another configuration option).

That would be the only option to handle this properly. We could even detect this in JS and give the admin that hint.

You could compare if the headers are only set on PHP reposes or also on static resources. But that's again just a hacky workaround.

So what's the plan here? A new config option for future versions (NC 14+)? How do we handle this in NC 13, remove the additional headers in the nginx-config from documentation?

FWIW, OC had has the same problem but they closed it with "Sample documentation seems correct" :-\

With Nextcloud 13 I noticed however that only the X-Frame-Options header is duplicated. My Apache installation sets X-Content-Type-Options, X-XSS-Protection and similar headers by default, but only X-Frame-Options appears to be duplicated, via lib/private/legacy/response.php. As it is marked a legacy function I assume this issue will be resolved as soon as addSecurityHeaders() is removed. Until then, commenting out that line serves as a workaround.

an option in config.php would be nice, to be able to control if headers are added via nextcloud or not.
quite annoying when a php script messes up the header which worked before.

With the risk of making a complete fool of myself, I thought something like this would do the trick:

$ diff -u lib/private/legacy/response.php{.orig,}
--- lib/private/legacy/response.php.orig        2018-08-06 04:55:12.113642060 +0200
+++ lib/private/legacy/response.php     2018-08-06 05:23:07.508675268 +0200
@@ -259,7 +259,12 @@
                        . 'object-src \'none\'; '
                        . 'base-uri \'self\'; ';
                header('Content-Security-Policy:' . $policy);
-               header('X-Frame-Options: SAMEORIGIN'); // Disallow iFraming from other domains
+               if (\OC::$server->getSystemConfig()->getValue('xframe_options', false)) {
+                       return;                                // Trying to fix nextcloud/server #8207
+               }
+               else {
+                       header('X-Frame-Options: SAMEORIGIN'); // Disallow iFraming from other domains
+               }

                // Send fallback headers for installations that don't have the possibility to send
                // custom headers on the webserver side

$ grep xframe_options $DOCROOT/nextcloud/config/config.php 
  'xframe_options' => false,

...except that it doesn't work -- but maybe someone with actual PHP skills knows what I meant to write and can fix this? ;-)

Is it already to late to propose this for Nextcloud 14?

So the header shows up in the dev console on firefox, but nextcloud doesn't detect them.
The webserver (nginx) is configured to add them. Is it the right way to do this ?

So the header shows up in the dev console on firefox, but nextcloud doesn't detect them.
The webserver (nginx) is configured to add them. Is it the right way to do this ?

We add it and require the web server to not add it - see our documentation for nginx about this: https://docs.nextcloud.com/server/13/admin_manual/installation/nginx.html

There is currently no hint in the documentation about this. Some headers are set in the example configuration, so you can't expect that some others are (already) set by PHP.

Only one section gives a decent hint:

            #Avoid sending the security headers twice
            fastcgi_param modHeadersAvailable true;

But this won't work with the PHP-FPM example. Sadly people tend to just copy and paste these example configurations.

If this won't be changed in NextCloud, the documentation should be enhanced. I provided a solution in https://github.com/nextcloud/documentation/pull/674. I can also add an explicit hint outside of the example configuration, that NextCloud may set some headers itself.

      If I remove this code, then my Nginx works, but it places dual headers and it senses that my config is wrong.

In case anyone else is having this issue, just remove any headers you are planning to set so you are not doubling up on them (and causing issues like this).

proxy_hide_header will hide/remove any header set by your PHP backend.

proxy_hide_header X-Frame-Options;
add_header X-Frame-Options "SAMEORIGIN";

@p3x-robot I'm curious why you closed the issue :confused:

it is possible to fix this issue. for me it was using double headers both nginx and nextcloud.
what i fixed, i removed the headers from nginx and now it works. nextcloud takes care the frame options. so it is closed for me, you can open a new bug.

@p3x-robot I'm curious why you closed the issue 😕

Good question. When using Apache or a shared hosting the issue still persists.

ok i just unsubscribe and re-open

i think it should be a configuration, with a simple if with either do it by nextcloud or the server (apache/nginx etc.)

According to this post (in German), nextcloud sets the header itself right here:
https://github.com/nextcloud/server/blob/master/lib/private/legacy/response.php
on line 107

This is confusing for me as an administrator. Should I rather uncomment that policy in my conf file, and hope it stays in the code? Or should I uncomment it in the code, and know it will stay in my conf file?

I am all for giving the server config to the admin.

Your webserver can ignore (or remove) a header and replace it with a custom one. I see no reason to introduce another flag here.

Your webserver can ignore (or remove) a header and replace it with a custom one. I see no reason to introduce another flag here.

How? I've tried doing this, but the set header option in nginx adds a duplicate header instead of replacing the current header. The proxy hide header option didn't seem to do anything either

It's possible for apache2 out of the box. If you use nginx as reverse proxy add_header and proxy_hide_header should do the trick. With fastgci and nginx you might try https://github.com/openresty/headers-more-nginx-module

Maybe I missed something in this discussion but why is X-Frame-Options the only common security header that Nextcloud is adding it with PHP? All the other headers like X-XSS-Protection are added in the main .htaccess file.

As for Apache with PHP-FPM you shouldn't add such headers in PHP. Instead adding it in .htaccess files. In that case Apache is not adding it twice. First Apache is taking a header option from Apache (global ) config files, than by individual config files and after that by htaccess. Apache always update the header but not add it serveral times.

do not add those settings to apache or nginx, nextcloud handles the headers itself

I'd still recommend to keep this issue open.

  • the headers set by NextCloud can't be customized
  • PHP can't set headers in all cases, e.g. 5xx responses or static files
  • it's inconsistent to set some headers in PHP
  • it's harder to hijack a server config a the PHP app

Erm, why was this closed? This bug has been opened precisely because Nextcloud adds its own headers, regardless if the webserver is already adding some. Think about cases where the webserver is not under the user's control and one cannot just disable the headers configured by the webserver. Also, Nextcloud may not be the only application running on a server and again, for that reason the webserver admin may have decided to set some default headers. Right now the only way is to somehow edit out the sections where Nextcloud sets these headers, but a config toggle would be nice. This is what this bug is about.

Since the premise for Nextcloud is hosting your own cloud – preferably somewhere in your home, with a Raspberry even – I think we can easily just assume that the user has full control over the server. If they choose to use some webspace, they should talk to their provider concerning security options / use .htaccess.

At least that is my opinion. I am used to getting my server secure wherever possible. Also, it's one less thing for developers to worry about when addressing security of Nextcloud.

Plus: We already do get the warnings. Some of them can be remedied in PHP, some in the .htaccess / server config - and if the PHP-code collides with the server-config, the server-config should always win.

I say: Have the server config be untouched by PHP, and leave it for the .htaccess / server-config. It only unnecessarily complicates things for us admins. You can just put that in the .htaccess that's being shipped, instead of burying it in the code.

My suggestion for some of the coders of you for a pull request:
Take out the headers set in PHP, and add them to the default .htaccess - make a note of it for when installing on nginx in the documentation.

@p3x-robot Since PHP-FPM it's not possible anymore to handle headers proper with PHP. You have to handle this with the websever, f.ex. Apache in htaccess.

It's not only an issues with security headers, as you see NC is now also not anymore able to present custom error messages by sending them with an error header. When sending an error header, Apache is using it's own error handling and messages.

i don't get all those long discussions. simply add a config flag for it and we are done.

ENABLE_PHP_HEADERS=TRUE

so all admins can adapt the config for their needs.

Not sure if this is related or an entire new issue:
I'm running NextCloud 16.0.4 on Apache/2.4.39, PHP 7.2 CGI. For me, the headers are sent twice - once from the .htaccess and once from here:
https://github.com/nextcloud/server/blob/1b074f48d824107de651a34a3948692cb5ca448f/lib/private/legacy/response.php#L100-L103

Normally, this line should avoid running into the case shown above:

https://github.com/nextcloud/server/blob/9d6eb2daf7c0f9d50aca78db02dbe8418a642768/.htaccess#L21

But the environment variable can't be retrieved by getenv and is not shown in a phpinfo either. Apparently, in some environments, only environment variables starting with HTTP_ can be set in the .htaccess. I tried it and if I change the variable to e.g. HTTP_MOD_HEADERS_AVAILABLE, it works in phpinfo as well as in the response.php.

Maybe someone who has more experience with Apache / PHP-CGI can tell whether this might be a solution for at least some of the issues discussed here?

But the environment variable can't be retrieved by getenv and is not shown in a phpinfo either. Apparently, in some environments, only environment variables starting with HTTP_ can be set in the .htaccess.

I don't see this with Apache/2.4.25 and PHP-FPM 7.2.21. Are you using mod_cgi? You are aware that this is super slow.

@kesselb phpinfo says "CGI/FastCGI".

If I change it to FPM, neither modHeadersAvailable nor HTTP_MOD_HEADERS_AVAILABLE can be accessed by PHP - they seem to be prefixed with REDIRECT_. But FPM somehow seems to avoid sending the same headers twice, so the issue doesn't visibly appear there.

@Harmageddon mind to create a new issue? It seems to be a bit off topic.

Ok, so I've re-read this a bunch o' times, and STILL have no clue how to fix this ...

atm, with NC18b (18.0.0.4), I'm getting reports of

The "X-Content-Type-Options" HTTP header is not set to "nosniff". This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly.
The "X-Frame-Options" HTTP header is not set to "SAMEORIGIN". This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly.
The "X-XSS-Protection" HTTP header doesn't contain "1; mode=block". This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly.

Adding

more_clear_input_headers "X-Content-Type-Options" "X-Frame-Options" "X-XSS-Protection";

to my nginx config appears to have NO effect.

IIUC, there's a fix somewhere up there ^?

I prefer to keep headers in my webserver config -- particularly since it's a proxy in front of a number of various services, including NC.

What exactly is required to make these errors go away?

EDIT:
I've tested here with all variants,

fastcgi_hide_header X-Frame-Options;
fastcgi_hide_header X-XSS-Protection;
fastcgi_hide_header X-Content-Type-Options;
proxy_hide_header X-Frame-Options;
proxy_hide_header X-XSS-Protection;
proxy_hide_header X-Content-Type-Options;
more_clear_input_headers "X-Content-Type-Options";
more_clear_input_headers "X-Frame-Options";
more_clear_input_headers "X-XSS-Protection";

None have any effect -- EXCEPT

proxy_hide_header X-Content-Type-Options;

DOES remove its respective error ...

@J0WI yep, long ago

I also cannot reproduce this on my phpfpm setup although I have seen this in the past as well. Could anyone of you share the output of a info.php file with the following content that is added to your webroot and opened in the browser:

<?php
phpinfo();

It should show the env variable similar to that:
image

There also seems to be a clear_env configuration flag for phpfpm, could you also check the value of that? https://www.php.net/manual/en/install.fpm.configuration.php

@juliushaertl

for phpinfo(), here,

...
$_SERVER['modHeadersAvailable'] true
...

and,

grep clear  php-fpm.conf
  clear_env = no

@juliushaertl did you need add'l/other info?

Is this issue still relevant? The code in question https://github.com/nextcloud/server/issues/8207#issuecomment-363683067 has been changed with Nextcloud 17.

To any response (from nextcloud) the Content-Security-Policy is added. The fallback code to add Referrer-Policy, X-Content-Type-Options, X-Download-Options, X-Frame-Options, X-Permitted-Cross-Domain-Policies, X-Robots-Tag and X-XSS-Protection only runs if modHeadersAvailable is not present (or has a value <> true).

So if anyone asks "how can I disable the security headers set by nextcloud" the answer is: SetEnv modHeadersAvailable true for apache2 or fastcgi_param modHeadersAvailable true; for nginx. I've just tested both ways and they work for me.

Any objections?

@kesselb

here, with clean install of NC tag

    v18.0.0beta3

checking

    sudo -u wwwrun php occ status
        - installed: true
        - version: 18.0.0.5
        - versionstring: 18.0.0 Beta3
        - edition:

in Nginx config

    grep modHeadersAvailable fastcgi_params
        fastcgi_param modHeadersAvailable true;

after login, nav to

    .../cloud/settings/admin/overview

still reports

    The "X-Content-Type-Options" HTTP header is not set to "nosniff". This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly.
    The "X-Frame-Options" HTTP header is not set to "SAMEORIGIN". This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly.
    The "X-XSS-Protection" HTTP header doesn't contain "1; mode=block". This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly.

So, clearly, still getting these ^^

Have I missed something in my config?

Have I missed something in my config?

How should I know? ;) Feel free to visit help.nextcloud.com and share your configuration. Also make sure that the headers are not sent twice like the other report.

With nextcloud 17 the X-Frame-Options are sent conditionally like the other headers too. There is a way to disabled this that works for most people. Is anyone able to provide a docker-compose.yml (or a description how to configure nginx and php-fpm) to reproduce this issue?

What do you think @juliushaertl @J0WI?

@pgnd
Just to clean it up:

Also did you check which headers actually arrive at the client (and how often)? curl -IL your.domain.name

@MichaIng this is still not correct. I have added the headers as per https://docs.nextcloud.com/server/latest/admin_manual/installation/nginx.html , and also set:

fastcgi_param modHeadersAvailable true; #Avoid sending the security headers twice

Yet I still get double headers!

curl -I https://drive.foo.com/
HTTP/2 302
server: nginx
date: Thu, 11 Jun 2020 07:29:57 GMT
content-type: text/html; charset=UTF-8
location: https://drive.foo.com/index.php/login
set-cookie: ockk0f3puuto=fqsng8tvcii0j1o0mo0pqmme99; path=/; secure; HttpOnly
expires: Thu, 19 Nov 1981 08:52:00 GMT
cache-control: no-store, no-cache, must-revalidate
pragma: no-cache
set-cookie: oc_sessionPassphrase=HriJPt%2Bh6SV0OUxIXTQXfVS1hMPH2129Sk2ftLPraKPDSEeRrVSeSVhxSV6kjpOITG6RGQMZMvlYQalHQrB5BVr7gbCEuWP0x2VAfW7I4iCN3Ue2PhXqWF9sa9Y8tFli; path=/; secure; HttpOnly
content-security-policy: default-src 'self'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; frame-src *; img-src * data: blob:; font-src 'self' data:; media-src *; connect-src *
x-xss-protection: 1; mode=block
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
x-robots-tag: none
x-download-options: noopen
x-permitted-cross-domain-policies: none
referrer-policy: no-referrer
x-content-type-options: nosniff
x-download-options: noopen
x-frame-options: SAMEORIGIN
x-permitted-cross-domain-policies: none
x-robots-tag: none
x-xss-protection: 1; mode=block

Is there a setting we can call that will stop the PHP script from sending its own headers? Cos if I comment out ALL the add_header parts from my nginx config, it works fine! (which means ownCloud itself is adding them!)

Here the headers are set:
https://github.com/nextcloud/server/blob/b219eadb8f3f459f2c71e937dfd3542f0792da8e/lib/private/legacy/OC_Response.php#L98-L106

Clearly only if modHeadersAvailable is no true and I just verified it's working as expected. Please assure the location where you added modHeadersAvailable, inside the .php files location directive in front of fastcgi_pass.

@MichaIng Thanks for the reply . It looks like it needed adding into the /etc/nginx/fastcgi_params file, rather than inside the server {} bit. Done, and those messages have gone away :)

Ah yes that is an alternative, although it is loaded likely by other web applications as well, which do not require it. The community Nginx config contains:

include fastcgi_params;

which loads this file. If you add fastcgi_param modHeadersAvailable true; right below this, it will work as well for Nextcloud only. However it doesn't matter much since it does not break anything else 😉.

Was this page helpful?
0 / 5 - 0 ratings