Cross Origin Resource Sharing (CORS)

SOP restricts cross origin websites from reading network response or DOM of other origins for security reasons. But there may be a necessity to allow cross origin response reading or DOM manipulation for specific origin. For ex: example.com might need to access data from api.example.com which might be legit.

CORS was introduced to add flexibility to SOP restriction & define access control for resources interacting with cross origin domains.

What is a Simple HTTP Request ?

A request is Simple HTTP Request only if it matches the below conditions -

  1. Method: GET, HEAD, OPTIONS

  2. Content-Type: The Content-Type request header may contain only application/x-www-form-urlencoded, multipart/form-data or text/plain

  3. No custom headers are included in request other than standard one's like Accept, Accept-Language, Content-Language, Content-Type, Range (only with a simple range header value; e.g., bytes=256- or bytes=127-255).

What is a PREFLIGHT Request ?

Any request other than Simple HTTP Request trigger a PREFLIGHT(OPTIONS) request by browser. The initial PREFLIGHT request doesn't include cookies of cross origin. The value of Access-Control-Allow-Origin, Access-Control-Allow-Credentials, Access-Control-Allow-Methods, Access-Control-Allow-Headers, Access-Control-Expose-Headers in response to PREFLIGHT determine whether real request can be made or not, whether real request may include credentials or not & whether cross origin access is permitted for client requesting the real request.

CORS feature depends on response headers provided by server as discussed below.

Few important CORS Response Headers -

  1. Access-Control-Allow-Origin: This header determines whether client can access cross origin resource or not. Absence of this header means by default cross origin resources cannot be accessed by javascript. It may can contain *, <origin> or null. <origin> can only be single origin as no browser support multiple origin.

    • Asterisk(*): Any Origin can access the resource, Note that Access-Control-Allow-Credentials: true is not allowed if * is present in Access-Control-Allow-Origin.

    • <origin>: Only client request originating from specific origin is allowed. For example: Access-Control-Allow-Origin: http://example.com means, only http://example.com can access http://api.example.com resources(If client request is made for api.example.com).

    • null: When local HTML file are used to make cross origin requests, Origin is set to null, This option is used to facilitate local development for testing purpose, But this can option be abused which will be discussed later.

  2. Access-Control-Allow-Credentials: This header tells browser whether or not browser can include credentials in cross origin requests. It may have true or false, true signifies browser may send cookies when making cross origin requests, false signifies browser cannot send cookies for cross origin requests.

    • For Simple Requests which do not trigger Preflight(OPTIONS) request, browser will include cookies for cross origin sites by default, If Access-Control-Allow-Credentials: false or absent then the browser doesn't allow reading of cross origin response or DOM using javascript.

    • For Requests which trigger Preflight, credentials are not included by default for the preflight request. The real request which takes place after preflight will include credentials only if Access-Control-Allow-Credentials: true is set in response of preflight request.

Vulnerability Checklist -

  1. Access-Control-Allow-Origin value controlled by client request - Test If Access-Control-Allow-Origin is reflection of Client side HTTP request headers(typically Origin header), parameters. Note Access-Control-Allow-Credentials: true must also be set to read the response successfully or do something meaningful. [Portswigger Lab] [Portswigger Blog]

  2. Access-Control-Allow-Origin value contain null - If null origin is accepted & Access-Control-Allow-Credentials: true also present, then we can try to make sandbox iframe with data scheme to exploit.

  3. Access-Control-Allow-Origin contain * : Note although Access-Control-Allow-Origin might contain *, This cannot be used with Access-Control-Allow-Credentials: true, Hence this is not always meaning if authenticated requests are made, But In general Access-Control-Allow-Origin: * is not suggested unless really required.

Last updated