Security Tip: Is Your Referrer Leaking Information?

[Tip #81] Do you know what information is being leaked by the Referer header when your users click on external links?

Security Tip: Is Your Referrer Leaking Information?

The Referer header is sent as part of an HTTP request to indicate where the request originated. This is useful for requests within your application to track how the user is moving between pages, as well as for requests between different sites for analytics - so you can see which sites are sending the most traffic your way.

The header name of Referer was actually a misspelling of the word Referrer, which was accidently used in the original proposal for the header. Some 0ther headers use Referrer, just to confuse you!

While passing around referrer information inside your app is incredibly useful, it can quickly become a security risk when it's passed outside your application onto third party sites.

For example, here's the top referrers list from Securing Laravel's Fathom Analytics:

Top referrers for Securing Laravel.

You'll notice most are unknown, however, under that list we've got some familiar faces! (Including LinkedIn, surprisingly!)

If I keep looking down the referrers list, I'll come across some referrers that look like this:

These are all private apps that are broadcasting their existence out to the world!

If I had malicious intentions, I could use this list to form a list of targets, start conducting recon, and ultimately try to compromise each site. Some would be publicly accessible, either behind a password login (credential stuffing time!), or just open to the world and relying on an obscure domain. Others would be internal, but knowing the domain name opens up the possibility for a CSRF attack, etc.

If you know the domain or IP address of an internal site, and you can get users of that internal site onto a site you control (which we do), you can use javascript running on the site you control to scan the internal site and check if it's vulnerable to things like CSRF attacks.

How do we stop leaking referrer information?

This is where the Referrer-Policy header comes in. It controls what information is sent in the Referer header during HTTP requests, and you can use it to control how much (or little) is sent in each request.

Here are the main options you need to care about:

Referrer-Policy: strict-origin-when-cross-origin

Note, this is currently the default when you don't have a Referrer-Policy set.

Internal requests will send the full URL, i.e., while external requests will only send the protocol and domain, i.e., but only if it's not going to HTTP from HTTPS.

Use this to broadcast your site's domain, but not the full path or query string to external sites.

Referrer-Policy: no-referrer-when-downgrade

Send the full URL, i.e., on all internal and external requests, unless it's going from HTTPS to HTTP.

Use this to broadcast the full originating path to external sites. This is the setting Securing Laravel uses to broadcast which article the user originated from.

Note, this can leak sensitive information, such as hashes and signatures in URLs. So ensure you only enable this on pages where URLs can be public knowledge.

Referrer-Policy: same-origin

Only send the full URL, i.e., on internal requests. The referrer will not be included on any external requests.

Use this to prevent the Referer header from leaking any information about your site, such as on internal or private pages.

I've only covered those three, but there are a number of other options which you might need in specific situations. Here's the full list:

Referrer-Policy: no-referrer
Referrer-Policy: no-referrer-when-downgrade
Referrer-Policy: origin
Referrer-Policy: origin-when-cross-origin
Referrer-Policy: same-origin
Referrer-Policy: strict-origin
Referrer-Policy: strict-origin-when-cross-origin
Referrer-Policy: unsafe-url

To learn more about how they work, head over to the mdn web docs.

Worried about your app being hacked? Book in a Laravel Security Audit and Penetration Test! I can find the vulnerabilities before a hacker does, and help you fix them!
Learn to Think Like a Hacker with my hands-on practical security course: Practical Laravel Security!