We’re constantly working on adding more security features and hardenings to Nextcloud, after all it’s your data and it has to be protected properly. While the Nextcloud 9 release fixes a critical security issue (we have informed upstream about this but in the meanwhile recommend upgrading as soon as possible) it also adds another new very mighty security hardening.

Introducing Same-site cookies

Same-site cookies are a relatively new Internet-Draft already implemented in Chrome 51 and higher. Same-site cookies are aimed to provide additional security against information-leakage and CSRF attacks.

Before we go into details on how same-site cookies work it is necessary to have a rough understanding how cookies do work and what CSRF vulnerabilities are. In a nutshell when you authenticate on a web page usually the following happens:

  1. Your browser connects to “nextcloud.com”.
  2. You press login and enter your credentials.
  3. The web server returns a cookie with a shared secret value identifying the user. The shared secret is also stored in the server database.
  4. On all consequent requests the cookie is sent by the web browser to this website as well.

A cookie is basically a small text value that websites can set and browsers will resend it with every request. When the cookie is sent the server can then lookup for which user the cookie has been issued. That’s how cookie-based authentication works in a nutshell.

Preventing Cross-Site Request Forgery (CSRF) with same-site cookies

Cookie-based authentication does however introduce another form of problems: Cross-Site Request Forgery problems. Cookies are normally sent with any request to a specific domain, that means if you are on “nextcloud.com” and you submit the “Create user form” the cookies are sent the same way like they are sent if “evilcloud.com” would embed the form. Effectively, “nextcloud.com” cannot differentiate whether you did the action by intention or whether another site forced your browser to send this request.

So the web server needs to have a way to determine that the request has in fact been sent by intention. Usually this is done by embedding a CSRF token on the web site in question. This works the following way:

  1. You press the submit button on “nextcloud.com”.
  2. Via JavaScript the CSRF token that is embedded on “nextcloud.com” somewhere is added to the request.
  3. The web server verifies that the CSRF token has the correct value.

Since the same-origin policy prevents “evilcloud.com” to read most content on “nextcloud.com” the CSRF token is unknown to the attackers’ website and the “nextcloud.com” server can reject the request.

Same-site cookies fix the CSRF problem by adding an additional attribute to the cookie telling browsers to only send the cookie when the request originated from the same domain. This means that only requests coming from “nextcloud.com” will contain the cookie, requests coming from another domain will not and thus the web server assumes the user is not authenticated.

Preventing information leakage with same-site cookies

Another problem caused by cookie-based authentication is the fact that it often can be used to leak sensitive information. In the case of ownCloud this can for example be used to determine whether an user has access to a specific file on the ownCloud server.

This is possible because again cookies are sent with all requests and there are diverse endpoints that allow users to download files without passing any CSRF token. Using a simple JavaScript hosted on another domain an attacker can simply check whether files or folders exists or not by comparing the timing of the response. Note that attackers cannot access the content of the specific files.

We’re at the moment not publishing any detailed proof of concept on this attack vector for obvious reasons. By leveraging the “strict” same-site cookie policy we have mitigated this issue in Chrome 51 and above.

Technical implementation details

Same-site cookies come with two different enforcement modes: “strict” and “lax”. The specification contains more details about them, but in a nutshell one of the most important differences is:

  1. Cookies with a “lax” policy are still sent from other domains if they do a GET request or if clicked on a link.
  2. Cookies with a “strict” policy are only sent when the request originates from the same domain.

A good example is a link in a mail. Here, if you click a link in a mail to your Nextcloud server the cookies with the “lax” policy are sent but not the ones with the “strict” policy. In Nextcloud we have implemented both policies:

API endpoints:

Are protected by expecting a “strict” cookie. We do not expect people to directly open the API endpoints within their browser. This protects against information leakage attacks as pointed out above as well as CSRF attacks.

View/templates endpoints:

Are protected by expecting a “lax” cookie. It is likely that people do click on a link to want to view the file listing or something. Since the views are however simply used for display and invoke other REST APIs there is no information leakage involved. The “lax” policy however adds a nice security hardening against CSRF attacks.

Any other legacy endpoints:

Are protected by expecting a “lax” cookie. This acts as a second layer of defense against CSRF attacks. For some legacy endpoints we also manually added a “strict” policy check or inherited it if we can assume that the endpoint is not directly opened from another page. (e.g. if the page is CSRF protected)

Since PHP does not natively allow us to configure the session cookie to use any other attributes we are now sending two additional cookies with every request:

  • nc_sameSiteCookielax
  • nc_sameSiteCookiestrict

Both cookies are automatically added when the user visits Nextcloud and the server is verifying on all subsequent requests whether the sent cookies match the required policy.

Cookies displayed in Chrome