3

It seems that the entire problem could be solved very elegantly by simply adding a new flag to the HTTP cookie specification.

Similarly to how cookies flagged Secure will only be submitted by the user agent over secure connections and those which are flagged HttpOnly will be forever inaccessible via DOM access, why not specify a new flag, say, NoCSR, or SameOriginOnly, which, when set, would prevent the cookie from being submitted with requests triggered by cross-origin referrers?

Of course, it would default to off so as not to break the previously expected behavior for already existing web sites, as per HTML5 Design Principle #2.1. I suppose there does exist one security hole, but not one that can't be easily solved: it can't be indiscriminately depended on, because old browsers would presumably just ignore the unrecognized flag.

So why not just create a whitelisted enumeration of NoCSR-implementing user agents versions' corresponding UA strings, and then only accept/process authorization-requiring and sensitive requests that carry one of those User-Agent: values? For requests submitted with no or non-whitelisted UA headers, an error could be returned that reasonably demands that the user upgrade to a supported browser version.

The whitelisting could be DRYed out with canonical implementation libraries (it would probably be more like a single simple function) for various server side languages.

Doesn't this seem much simpler than the current system of generating, keeping track of, and reading secure CSRF tokens?

Thoughts, anyone?

migrated from stackoverflow.com Sep 9 '12 at 23:07

This question came from our site for professional and enthusiast programmers.

  • 1
    For requests submitted with no or non-whitelisted UA headers, an error could be returned that reasonably demands that the user upgrade to a supported browser version. which would definetly break the previously expected behavior for already existing web sites. – Jonas Schäfer Sep 9 '12 at 14:31
  • 1
    Cookies are not the only means of authentication. You could also use HTTP authentication, client certificate based authentication, or even IP address based authentication. – Gumbo Sep 9 '12 at 14:32
  • I think you'd be borderline retarded to use anything as unpredictably volatile as IP addresses for authentication. I don't know what client certificate based authentication refers to, but is HTTP authentication vulnerable to CSRF attacks, as well? I suppose it would be, wouldn't it.. That said, I feel like my solution would still work for the overwhelming majority of sites using cookie-based auth schemes, wouldn't it? @Gumbo – adlwalrus Sep 9 '12 at 14:38
  • 1
    @adlwalrus, yes, HTTP authentication and client certificate based authentication are also vulnerable to CSRF. – D.W. Sep 10 '12 at 0:41
4

Basically you are right, your solution would prevent CSRF tokens from being necessary against such attacks. But then we could also check the Referer header to make sure it comes from an allowed domain or subdomain, right? And using the referrer would already be more flexible than an NoCSR-flag: you can whitelist domains or subdomains.

The problem is replay attacks, or when a user accidentally submits twice. For this reason you would already need a token that changes unpredictably every request (a.k.a. nonce). This might be as simple as a salted hash of the current time, but still need to do it.

Also cookies are necessary to keep someone logged in. Having to have seperate cookies to identify CSRF attacks and when someone is logged in is kind of annoying. (The one to identify CSRF attacks would carry the NoCSR flag.) And you do want to know whether someone is logged in, the menu will probably need to be different, even when he is referred there from another website.

  • I don't believe that the HTTP spec requires referrer transmission. But if one assumes that their users have internal referrer transmission enabled, I assume just verifying that would do the trick too, wouldn't it? – wwaawaw Sep 10 '12 at 8:06
  • But what I don't understand is how a replay attack is an attack at all. Seems more like an innocent accident or a bug or a mishap. Also, isn't the risk of that mitigated by disabling / "greying out" the button on it's click event? I read a post about that one time, I think it was on codinghorror. I'd also redirect after the POST receiver script got hit. Finally, how would you verify the nonce when you received it back? – wwaawaw Sep 10 '12 at 8:09
  • @adlwalrus "I don't believe that the HTTP spec requires referrer transmission." No, it doesn't, that's my single issue with this. All browsers support it though, and those who disabled it because of privacy reasons will discover soon enough. Same with Javascript, if it's disabled stuff might break. Just make sure to give appropriate errors. – Luc Sep 10 '12 at 9:41
  • Well that makes sense then. There really isn't any additional privacy leak to sending same-site referrers, though, and that's really all that's called for here. I believe the browsers that offer a way to disable referer transmission only allow disabling it for external link clicks. Of course there're extensions to both big browsers that disable it completely. But yeah, obviously there'd be a reasonably explanatory error message. – wwaawaw Sep 10 '12 at 10:29
  • @adlwalrus "But what I don't understand is how a replay attack is an attack at all." Besides what Wikipedia has to say on this, a replay attack could be used to redo the action that has just been done, like receiving money/credits from another account twice, or ordering something twice, etc. "how would you verify the nonce when you received it back?" 1) make sure it has been issued, and 2) that it hasn't been used in the past. Also make sure the entropy of the nonce is large enough (same as with session tokens), or an attacker might be able to guess it. – Luc Sep 10 '12 at 11:26
3

I'd say mostly complication. A link sent through another application would carry no site referrer, so that is a hole that needs to be considered. One could focus on only passing requests from within the site, but there could be an XSS vulnerability that would create CSRF-like behavior that would be stopped by using a nonce.

In very short summary: the nonce method already works and isn't very complicated to implement. This proposed method may end up being much more complicated to implement, would break backwards compatibility, and would require the already existing nonce method as a stop-gap.

Finally, there are other non-repetition behaviors for which you might still desire a nonce.

  • I don't think it actually would break BC, if you read the post carefully. Is "nonce" synonymous with "CSRF token"? – wwaawaw Sep 10 '12 at 8:10
  • 1
    @adlwalrus Essentially yes. – Jeff Ferland Sep 10 '12 at 15:42
  • @adlwalrus A CSRF token does not necessarily need to be used only once. The only requirement it must fulfill is that it is only known to the properly authenticated user. Theoretically, it is perfectly fine to generate a token only on user registration. Although regenerating the CSRF token reduces the risk of the possibility of a valid CSRF token getting leaked or guessed. But nonce rather implies that the value is only valid for a single request. – Gumbo Sep 10 '12 at 17:12
  • @Gumbo that's a great point. – wwaawaw Sep 10 '12 at 17:20
2

Since this question was asked, just such a cookie flag has been added to modern browsers: SameSite. From the spec:

5.3.7. The SameSite Attribute

If the attribute-name case-insensitively matches the string
"SameSite", the user agent MUST process the cookie-av as follows:

  1. If cookie-av's attribute-value is not a case-insensitive match for "Strict" or "Lax", ignore the "cookie-av".

  2. Let "enforcement" be "Lax" if cookie-av's attribute-value is a case-insensitive match for "Lax", and "Strict" otherwise.

  3. Append an attribute to the cookie-attribute-list with an attribute-name of "SameSite" and an attribute-value of "enforcement".

5.3.7.1. "Strict" and "Lax" enforcement

Same-site cookies in "Strict" enforcement mode will not be sent along with top-level navigations which are triggered from a cross-site document context. As discussed in Section 8.8.2, this might or might not be compatible with existing session management systems. In the interests of providing a drop-in mechanism that mitigates the risk of CSRF attacks, developers may set the "SameSite" attribute in a "Lax" enforcement mode that carves out an exception which sends same-site cookies along with cross-site requests if and only if they are top- level navigations which use a "safe" (in the [RFC7231] sense) HTTP method.

Lax enforcement provides reasonable defense in depth against CSRF
attacks that rely on unsafe HTTP methods (like "POST"), but does not
offer a robust defense against CSRF as a general category of attack:

  1. Attackers can still pop up new windows or trigger top-level navigations in order to create a "same-site" request (as described in section 2.1), which is only a speedbump along the road to exploitation.

  2. Features like "<link rel='prerender'>" [prerendering] can be exploited to create "same-site" requests without the risk of user detection.

    When possible, developers should use a session management mechanism such as that described in Section 8.8.2 to mitigate the risk of CSRF
    more completely.

It's supported as of IE 11 (on Windows 10 only), Edge 16, Firefox 60, Chrome 51, Safari 12, and Opera 39, according to caniuse.com.

  • Even if that spec itself says SameSite won't fully prevent CSRF, this cookie attribute should be more widely known. – Xenos Aug 25 '18 at 18:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.