13

When testing a single page application, I've identified that the REST endpoints return CORS headers that allow cross-domain access:

access-control-allow-credentials: true
access-control-allow-methods: GET, POST, DELETE, PUT
access-control-allow-origin: *

These endpoints handle confidential data, so my initial reaction to this is to raise a high-risk vulnerability.

However, when I attempted to exploit the issue I found I couldn't. The site uses a bearer token in the authorisation header instead of a session cookie. While it is possible to make cross-domain requests, it isn't possible to attach the required header.

What are the risks with this model? Is this a sensible way to do things?

  • Do they return the same CORS headers no matter what origin send the request? – Anders Jun 27 '16 at 12:17
  • 1
    @Anders - yes they do, and also if there is no origin header – paj28 Jun 27 '16 at 14:49
  • Why can't you attach the authentication header with the bearer token to cross domain requests? This is perfectly possible with a proxy like BurpSuite, isn't it? – Silver Jun 30 '16 at 8:22
  • @Silver - The problem is that you don't know the token. Also, in an attack scenario the attacker has to work in the victim's browser, they can't use BurpSuite. – paj28 Jun 30 '16 at 9:07
  • Ok, but that's the same problem as with a session cookie, right? – Silver Jun 30 '16 at 9:29
9
+50

There are a few things that will mean exploitation is unlikely.

To start with

access-control-allow-credentials: true
access-control-allow-origin: *

is an invalid combination:

Important note: when responding to a credentialed request, server must specify a domain, and cannot use wild carding. The above example would fail if the header was wildcarded as: Access-Control-Allow-Origin: *. Since the Access-Control-Allow-Origin explicitly mentions http://foo.example, the credential-cognizant content is returned to the invoking web content.

Another thing is that the authorization header is not a simple header, so would require a preflight that results in an Access-Control-Allow-Headers response returning that header. The server not returning this would also prevent any CSRF attack, because the pre-flight will block it.

Unless it allows the header, it is not usually possible to add a custom header cross domain unless you attempt an exploit with Flash that used to work on certain browsers.

What are the risks with this model? Is this a sensible way to do things?

As it is invalid to specify this combination of headers, indeed this is not a sensible way to do things. There may be some odd browser out there that would allow it and the site would be vulnerable (should any potential victim be using it). Allowing all origins but not credentialed requests allows the victim browser to be used as a sort of proxy in order to reach otherwise inaccessible resources. However, as the bearer header cannot be attached (without a Flash exploit) and being allowed through Access-Control-Allow-Headers, I wouldn't say this is high risk. Additionally, as the attacker does not have their victim's bearer token, any cross domain requests that would be made would be under the attacker's session rather than their victim's.

I would probably point it out as an advisory item that they should review that their CORS headers match their intention.

-1

IMO bearer token + permissive CORS compounds two poor decisions into one that's potentially disastrous.

Bearer token approach greatly increases token exposure via (1) network communications, thus relying on TLS to be setup properly, and (2) at the user agent (browser, mobile device) end where the token will need to be protected and carefully handled.

Unfortunately, the permissive setup of CORS compounds their client side security woes further. Since the user agent is permitted to connect to any other domain to download JS libraries, they better make sure these other sites are not only trustworthy but have excellent security so they cannot be easily compromised. You do not want the token residing in the user agent to be stolen by some malicious script downloaded from some other site - that's the risk introduced when you combine these two choices.

Recommendations to mitigate against token theft:

  • If bearer token is absolutely necessary, restrict CORS to prevent cross domain access.
  • On the other hand if cross domain is necessary, then use authorization code grant where token resides entirely on server side and is never exposed to the user agent.
  • I dont see how your arguments corelate to the permissive CORS headers. If the user agent (in knowledge of a bearer token) executes malicious scripts, the CORS setup of the resource host is entirely irrelevant. – marstato Jun 30 '16 at 9:04
  • 1
    The site does use TLS, and it only takes JS libraries from trusted domains. But anyway, if there were flaws in the JS libraries, this would affect the site even if it used normal session management (e.g. cookies + no CORS). – paj28 Jun 30 '16 at 9:08
  • Since user agent possesses the token, you want to minimize the risk of malicious external scripts. Permissive CORS is relevant because it is where those malicious external scripts can be introduced. – HTLee Jun 30 '16 at 14:34

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.