7

Imagine a generic web application with a login form to access the application. Regardless of how the actual authentication is performed, what are the implications of not checking the referer header to verify the submit request is coming from within the same application/domain/approved URLs?

Another way to think about this is if you drop the referer header check and are checking something that verifies its coming from a known source. What are the implications of not checking the form data source?

Specifically in a passive scenario, e.g. purely browser based.

The biggest implication I see is that I can submit the credentials from another site and log in successfully.

But what risks are there in this? I realize it depends on each application and the threat models for it, but can this be generalized?

Steve
  • 15,155
  • 3
  • 37
  • 66

3 Answers3

7

A CSRF attack tries to exploit "the trust that a site has in a user's browser" (so says the Wikipedia page, and it is well said). It is about the server accepting a request from the client, on virtue of the request coming with some authentication characteristic which makes the server believe that it comes from the genuine user (which it does) and under the conscious control of the genuine user (which is false). The "authentication characteristic" would classically be a cookie value (acceptable for the server), or HTTPS with certificate-based client authentication.

For a login page, the server does not trust the request from the client. That's the point of a login page: to initialize trust. The login page expects a login and a password precisely because there won't be anything that the request can come with, which will make the server happier and distract it from its intended action, which is to verify the login+password pair. As such, CSRF attacks don't apply to this page.

You can still check the Referer field to check for "fishy business" (if it is absent or wrong, then something is definitely amiss), but it won't really change the security.

Tom Leek
  • 168,808
  • 28
  • 337
  • 475
  • "if it is absent or wrong, then something is definitely amiss" -- Yeah, like the user directly bookmarking the page. Or disabling Referer headers to reduce tracking. Or their browser autocorrects Referer to Referrer, because only the latter is a word, and the former is [a typo](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referer)... – Nic Jul 11 '19 at 20:25
6

What is the implication of verifying it? The referer header:

  • can be spoofed by the client
  • can be completely omitted by the client (notoriously when going through TOR/proxies)
  • is no guarantee that the user actually came from there

There referer header is sent as a courtesy from your browser, it is not a HTTP RFC requirement. See here for details on the header: http://www.w3.org/Protocols/HTTP/HTRQ_Headers.html#z14 .

It should be therefore obvious that this header holds no value whatsoever, and should not be a guarantee of anything. In addition, anyone smart enough can spoof this. If you want real guarantee that your log-in form data did come from your log-in form, build a check that attempts to find a unique, randomly-generated, user-based (or navigator-based) value. This will be a lot more reliable (but, depending on the implementation, not necessarily bullet-proof) than a Referer header.

  • The referer header protects against client stupidity though. It applies to the wider audience of people who don't know about csrf. – Manishearth Apr 17 '13 at 19:10
  • Well yes, okay. Let me update my question to narrow the focus a bit. – Steve Apr 17 '13 at 19:11
  • 2
    @Manishearth: I don't know. Personally, if I had a choice between a silver bullet and a dodgy-at-best referrer (with false positives **and** negatives), I'd personally pick the CSRF token. Hide it (input[type="hidden"]) in the form, and you're sure that it will go through on selected forms. – Sébastien Renauld Apr 17 '13 at 19:12
  • @SébastienRenauld: Of course. I'm just saying that it isn't entirely useless. – Manishearth Apr 17 '13 at 19:17
  • 1
    Its only utility is statistics and possibly post-attack forensics. I hope we agree on this :-) – Sébastien Renauld Apr 17 '13 at 19:25
2

For a login form -- not so much. The most that could happen is a well-known site like Facebook could go rogue and use their clients' machines (via POST requests from an embedded form triggered by javascript) as part of a botnet-like entity to bruteforce your login form.

But that's rather unlikely, so there's no problem with not checking referers on login.

Note that the rest of the website, after login, should check referers on any sort of request (GET or POST) with side effects. Otherwise, I could create a site which has an embedded iframe with contents like:

<form method=post action="www.yoursite.com/makepayment.php">
<input type=hidden name="to" value="123453323">
<input type=hidden name="amount" value="$10000">
</form>

and JS-trigger the form, submitting a POST request that transfers money from you to me (or whatever).

You want to avoid that, so check referers there.

Even better, use a CSRF token (a temporary token that is attached to a specific account for a small period of time) in an <input type=hidden> on every form on the page that has side effects (i.e., does not simply load a new page but also mutates the data stored on the server or elsewhere)

Manishearth
  • 8,237
  • 5
  • 34
  • 56
  • CSRF tokens are the only way to go. HTTP headers including Referer are trivial to spoof, and may be dropped by browsers for privacy reasons. – dr jimbob Apr 17 '13 at 19:43
  • Is it really true that _all_ requests should use CSRF tokens? I thought the utility of CSRF tokens was in safeguarding requests which have side-effects. If we're writing well-behaved web applications, GET requests would not fall into this category. – David Sanders May 19 '14 at 22:50
  • 1
    @DavidSanders Good point, changing – Manishearth May 20 '14 at 04:10