CORS for Pentesters

CORS is a way to selectively violate the same-origin policy.

The same-origin policy is what makes the web work as it does. It’s what keeps one website from seeing content that comes from another website. If you’re gonna make exceptions to such a fundamental thing, you best do it carefully.

Interesting Bits for Testing

This is just a start:

Access-Control-Allow-Origin or ACAO

Access-Control-Allow-Credentials or ACAC

Setting ACAO: * and ACAC: true would mean every host on the internet has same-origin access to the content. That’s so obviously bad that a browser won’t go along with it.

Nearly as bad is echoing the Origin header from the request into ACAO in the response. This can be fine, so long as the server validates that the origin is an expected one before echoing it. But it’s easier to just echo anything, and that’s how you get CORS Arbitrary Origin Reflection.

CORS Arbitrary Origin Reflection

This is when you have both ACAO: [reflected arbitrary origin] AND ACAC: true.

  1. If you don’t have ACAC: true it’s probably not a security problem (but look for other sensitive headers like Authorization or Cookie in Access-Control-Allow-Headers.
  2. If you do have ACAC: true AND if the authorization token is NOT in a cookie, it’s probably less of a worry (because the attack requires the browser to send credentials, and while a browser will send a cookie with every request (see below) to that cookie’s server, you need JS to set an Authorization: Bearer header, and that JS needs access to the token, obvs, and both cookies and DOM Storage are protected by the Same Origin policy.) So exploiting this requires XSS or similar.
    1. (this is “below”) And yes, setting SameSite=None will prevent the cookie being sent 100% and SameSite=Lax will prevent it in most cases.

Sample HTML to test for permissive CORS (you’ll need to edit it a bit. Ask bbk if you need a hand. He wants to re-do this one with the Fetch API anyhow.

https://gist.github.com/ropnop/08499c86ca4d3f5a5e7a29f6cedd51d3