Roundcubemail: Privacy: Avoid referrer leaking

Created on 6 Aug 2018  路  5Comments  路  Source: roundcube/roundcubemail

Motivation

Avoid unnecessary information leaking about user.

Example:
Embedded image is loaded. The referrer to external resource is:
Referer: https://mail.example.com/?_task=mail&_caps=pdf%3D1%2Cflash%3D0%2Ctiff%3D0%2Cwebp%3D0&_uid=1445&_mbox=INBOX&_safe=1&_action=show

Leaked information:

  • size of the inbox: _uid=1445
  • name of the folder: _mbox=INBOX
  • capabilities of the browser: _caps=pdf...

Browser support?

At the moment the browser support is good: https://caniuse.com/#feat=referrer-policy .

Backwards compatible?

Yes, older browser ignore the policy.

Implementation status?

There are two old and pending pull requests: #5422 #5674 #6038

Problem with the pull requests

There are different ways to implement referrer-policy:

  • meta-html-tag
  • http-header sent by php
  • http-header sent by .htaccess (would only work on apache)

There is a missing statement from maintainers which way should be chosen and what should be done to get them merged.

Further reading

Specification:
https://www.w3.org/TR/referrer-policy/

Old Specification:
https://wiki.whatwg.org/wiki/Meta_referrer

Blog article:
https://scotthelme.co.uk/a-new-security-header-referrer-policy/

edit: add: .htaccess pr, doc

Security enhancement

All 5 comments

If you review samples in .htaccess file, you'll see it can be done on a different level. No need for a configuration option. I'm not saying we'll not add such an option, but I'd like to see it more robust, see my comment https://github.com/roundcube/roundcubemail/pull/5422#issuecomment-250823993

I took the arguments from https://github.com/roundcube/roundcubemail/pull/5422#issuecomment-250823993 .

  1. Some users may actually want referrer to work on the login screen. So, maybe better to use this only for authenticated pages.

We could take "same-origin" option, more details see 2.

  1. We already use noreferrer for links and no one complained, so maybe making this new feature configurable is useless. I propose to always use "no-referrer" value for best privacy.

The "noreferrer" for links only affects external sites, but the referrer-policy affects external and internal sites.
If we put "no-referrer" as default it could brake roundcubes referer_check or other fancy custom check implementations.
I think "same-origin" would be the best solution under backwards compatibility aspects. It would deny the referrer for external sites and keeps a basic referrer for internal sites.

  1. Some browsers (Edge, Safari) does not support "no-referrer" (and other values), but support "never", it would be good to set the value according to detected browser.

The statistic shows that only 15% use this browsers. Is it worth to program a switch?
As alternative the legacy and the new value can be send as described in https://w3c.github.io/webappsec-referrer-policy/#unknown-policy-values . edit: after some research: old browsers struggle with the new values, because they do a different parsing -> does not work :(

  1. Finally, .htaccess file already contains an example how to do the same with Content-Security-Policy header.

The referrer control by CSP is deprecated. It was part in CSP1.0 but not in the current version.
The commit was created by me 3 years ago as optional settings for experienced users. But 3 years are a long time in web development. I will make a update pull request.

If you review samples in .htaccess file, you'll see it can be done on a different level.

If we want it as default we should not use .htaccess, because it only works on Apache servers and not on nginx.

@alecpl After a lot of research and testing, I got following conclusion:

Compatibility table

| Referrer-Policy | meta-html-tag | http-header | Compatible old draft | Works with RC referer_check | Leak to external | Full privacy |
|-------------------|:-------------:|:-----------:|:---------------------:|:---------------------------:|:----------------:|:------------:|
| None setting | - | - | - | - | x | - |
| Same-Origin | - | x | - | x | - | partially |
| No-Referrer | - | x | - | - | - | x |
| Origin | x | - | x | x | partially | - |
| Same-Origin | x | - | - | x | - | partially |
| No-Referrer,Never | x | - | x | - | - | x |

Recommendation

  • Usage of Referrer-Policy No-Referrer,Never by meta-html-tag

    • Backwards compatibility to old draft browser

    • No browser switch required

    • Full privacy

  • To avoid problems: remove referer_check caused problems #3306 #4221 and is replaced by modern CSRF check

Alternative recommendation

  • Usage of Referrer-Policy Origin by meta-html-tag

    • Backwards compatibility to old draft browser

    • No browser switch required

    • Can keep referer_check

    • Disadvantage: Still leaks domain to external


Some background information from research

Settings with compatibility to old draft browser for

  • send referrer is difficult (Same-Origin and Origin can not be used at same time)
  • no referrer is possible

It is only partially possible to get a complete backwards compatibility to browser which only support the old draft of the specification.

Problem:
Browser with old draft do not ignore unknown values. If they parse a unknown value they reset the referrer policy to default behavior and not as defined in the new standard to the latest valid value.

Tested with IE11:

<meta name="referrer" content="never">
<meta name="referrer" content="no-referrer"> <!-- unknown by IE11-> set policy to default  -->

Result: referrer sent :-1:

Tested with IE11:

<meta name="referrer" content="no-referrer"> <!-- unknown by IE11-> set policy to default  -->
<meta name="referrer" content="never"> <!-- known ->correctly parsed and set --> 

Result: no referrer :+1:

Tested with Firefox61:

<meta name="referrer" content="no-referrer"> <!-- known ->correctly parsed and set --> 
<meta name="referrer" content="never"> <!-- unknown -> ignored, referrer policy not changed -->

Result: no referrer :+1:

So, we have #5674, #6477, #5422. We need one solution. Some notes:

  1. We already removed referer_check option.
  2. We should not care about old browsers much in this case, imo.
  3. I think I'd prefer same-origin and no meta-tag use.
  4. I really think we should not set that header on logon page.
  5. I'm not sure we need a config option for that, probably not.
  6. Maybe we should add a plugin api hook in rcube_output::common_headers() where the Referrer header would be set. So, it could be controlled by a plugin.

Implemented in 186f21c4c.

Was this page helpful?
0 / 5 - 0 ratings