According to https://en.wikipedia.org/wiki/Cross-site_request_forgery#Cookie-to-header_token

The protection provided by this technique can be thwarted if the target website disables its same-origin policy using one of the following techniques:

Permissive Access-Control-Allow-Origin Cross-origin resource sharing header (with asterisk argument) ...

Is that correct? How does a Access-Control-Allow-Origin=* header thwart the protection? Cookie access is not governed by Access-Control-Allow-Origin headers. An attacker can never read that cookie's content via JavaScript if they are in a different origin, am I missing something?

Also if the value is * then withCredentials is automatically false (https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors/CORSNotSupportingCredentials)

And even if it was possible, XHR doesn't allow you to read another domain's cookie, even if successfully set (https://fetch.spec.whatwg.org/#forbidden-header-name)

Is that claim wrong or perhaps I'm missing something? Or maybe the article meant that this in combination with the other items together is needed to thwart this method?

EDIT To clarify, the Cookie-to-header-token does not include a hidden input field, just a Cookie.


Usually a CSRF token is available in the body of a response from the server. They're commonly inside a hidden input inside a form in an html response. If that page includes a Access-Control-Allow-Origin=* header, then any website on the internet could make a request for that page and get the CSRF token.

|improve this answer|||||
  • Yes, but I'm talking about the Cookie-to-header token method, there is no hidden field, just a cookie. – Eran Medan Feb 20 '19 at 23:46
  • Oh, right. I can't see how that warning applies to that strategy either. I assume that warning was copied from another section or article about general CSRF protections. – Macil Feb 20 '19 at 23:49
  • Yeah, looks like a copy paste error – Eran Medan Feb 20 '19 at 23:52
  • p.s. just tried it, (permissive cors, set a CSRF token that is session based, went to jsfiddle and did an XHR with credentials to that page, since it sends credentials, it sends my session cookie, thus shows the same page I see e.g., shows the hidden field with my token like a charm, important lesson on how critical is avoiding * CORS headers, as even if you are only serving JSON, one day you'll return an HTML page and forget... wow) this is surprising as I thought * blocks withCredentials according to: developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors/… – Eran Medan Feb 21 '19 at 0:15

An attacker can never read that cookie's content via JavaScript if they are in a different origin, am I missing something?

You might be missing something regarding HTTP cookies but it's probably not the main issue here, but it's important to fully understand the subtle aspects of cookie semantics because they are widely used for security sensitive purposes.

Cookies' "origin"

You can only read cookies by JS if they are associated to the page and sent to the server in the HTTP request: it's a necessary condition (but not sufficient obviously as cookies can be made "HTTP only"). So what you are saying is that an HTTP request to an URL with origin A only sends cookies set by pages from A. But this is not true.

Actually you very often get cookies from a different (but not arbitrary) origin:

  • http://x and https://x are different origins, but HTTPS URLs receive HTTP cookies (and there is no way to refuse that or even sort out cookies by actual origin); the common fix for that is to make a domain HTTPS only in the browser via prelisting or HSTS headers.

  • for any secure or insecure scheme, domain.register and sub.domain.register can share cookies: cookies set in domain are visible in the subdomain, the subdomain can choose to make some cookies visible at a wider domain, limited to "register", the domain where the browser believes people can register domain (which isn't even always a perfectly well defined concept); again there is no way for a server to determine who set which cookie, so unless you control all every related domain you might get additional cookies.

Not only that, the interaction of cookies of the same name was never well defined and browser independent and different browsers had different behavior.

Now by hypothesis an attacker cannot invent an arbitrary subdomain in your domain and make a secure connection to it work; if he could, it would be as easy to just intercept a secure connection to the main domain, as by hypothesis the attacker would either be able to get a certificate that he isn't allowed to get, or to make users dismiss security warnings. So if you set a secure cookie for domain, the attacker can't intercept it by playing with subdomains.

The purpose of permission/authentification cookies

Back to the original issue, which was never to protect a cookie value but the rights linked to an authenticated requested, linked with an arbitrary and meaningless value: a cookie as in the older X server authentication cookie is just a meaningless number that has no value in itself, only in connection with a server that attributes meaning to that cookie.

You are not just trying to keep a numerical value secret, you want to protect the functionality of that value. Say you have an electronic card containing a secret key that can't be copied, and that can only be used on a safe to open it; if the card can be stolen from you and used without your knowledge, the content of the safe isn't secure; although the secret code was always inside the card, and no attacker ever learns that code.

Protecting HTTP cookies that represent a permission on the server (or an authentification status, or anything that a random anonymous user on a website cannot do) means preventing the cookies from being misused even in ways that don't allow an attacker to learn a meaningless numeric value.

That's where "HTTP only" isn't magical and does not guarantee complete security if you allow arbitrary Javascript from the same origin as your Website managing private information.

[Note that the designers of the HTTP only flag explicitly warned against over reliance on it as a protection against JS injection - something that many people decided to ignore thinking that the "HTTP only" is only needed protection against XSS for sites that have valuable authentication cookies.]

A secret cookie protects access to a Web ressource and allowing arbitrary operations to be done by any external agent (running on an arbitrary domain) via a browser defeats the purpose of protecting that secret - even if the secret says secret, like an access card you would let anyone use.

|improve this answer|||||

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.