No Referals [sic] Please

Aug. 28, 2018, 5:23 a.m. (no-referrals-please)

TL;DR


I found a post on Hacker News with a link to webbkoll which tries to check how privacy-friendly a particular site is. Of course I had to check against my own site!

Webbkoll reported that my referrers were being leaked and that I was using a Google as a third-party service. My site does make requests to Google for some fonts, so that was expected. The privacy checker gave a helpful explanation on why someone might not want to make requests to a third-party (well the actual description singled out Google specifically, but the same is true for any third-party). I could host these fonts myself (as suggested) but the risk seems low to me and loading the fonts from Google means that users are more likely to have the fonts already cached (making my site load faster... not that anyone reads this).

But, what's this referrer business? Turns out that browsers send information on what page a user comes from. This information is stored in the headers under the Referer field. Yes, referer and not referrer. According to wikipedia, this mispelling is found in multiple RFCs.

This information seems pretty innocuous, but can be used (in tandem with other techniques) to track people online. Sites can associate its users with their referring pages. Webbkoll provides a good example: Let's say you're logged in on Facebook. You visit a page with the URL http://www.some-hospital.com/some-medical-condition. On that page, you click a link to their Facebook page. Your browser then sends Referer: http://www.some-hospital.com/some-medical-condition to facebook.com, along with your Facebook cookies, allowing Facebook to associate your identity with that particular page.

Luckily for us tinfoil hat folk, there is a Referrer Policy (referrer spelled correctly this time) and a helpful MDN page. I was excited to stick it to the surveillance state and quickly fired up my terminal and SSH'd into my server to update my NGINX configuration with add_header Referrer-Policy "no-referrer";. I checked afterward and sure enough my browser did not send a referer! I had chores I wanted to avoid so I frantically logged in to make a post... but I was greeted with this:

Forbidden (403)

CSRF verification failed. Request aborted.

You are seeing this message because this HTTPS site requires a 'Referer header' to be sent by your Web browser, but none was sent. This header is required for security reasons, to ensure that your browser is not being hijacked by third parties.

If you have configured your browser to disable 'Referer' headers, please re-enable them, at least for this site, or for HTTPS connections, or for 'same-origin' requests.

If you are using the <meta name="referrer" content="no-referrer"> tag or including the 'Referrer-Policy: no-referrer' header, please remove them. The CSRF protection requires the 'Referer' header to do strict referer checking. If you're concerned about privacy, use alternatives like <a rel="noreferrer" ...> for links to third-party sites.

More information is available with DEBUG=True.

Apparently Django has an extra security measure for HTTPS pages (see step 4). In short, the Referer header is used to make sure that a request comes from the same site. zinfandel has a better explanation on Stack Overflow. Bummer. But this can be worked around by using the same-origin policy instead of no-referrer.