This site is the archived OWASP Foundation Wiki and is no longer accepting Account Requests.
To view the new OWASP Foundation website, please visit https://owasp.org

CORS OriginHeaderScrutiny

From OWASP
Revision as of 20:00, 25 February 2019 by Collin Sauve (talk | contribs) (Countermeasure B does not help AT ALL. Main recommendation here should be: Don't use the Origin header to validate the sender, as it is not reliable. Why are we recommending adding some overly-complicated mechanism that doesn't actually work?)

Jump to: navigation, search
This Page has been flagged for review. Please help OWASP and review this Page to FixME.


Last revision (mm/dd/yy): 08/16/2013

Introduction

CORS stands for Cross-Origin Resource Sharing.

Is a feature offering the possbility for:

  • A web application to expose resources to all or restricted domain,
  • A web client to make AJAX request for resource on other domain than is source domain.

This article will focus on the role of the Origin header in the exchange between web client and web application.

The basic process is composed of the steps below (sample HTTP resquest/response has been taken from Mozilla Wiki):

  • Step 1 : Web client sends a request to get a resource from a different domain.
GET /resources/public-data/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Referer: http://foo.example/examples/access-control/simpleXSInvocation.html
Origin: http://foo.example

[Request Body]

The web client tells the server its source domain using the HTTP request header "Origin".

  • Step 2 : Web application response to request.
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 00:23:53 GMT
Server: Apache/2.0.61 
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/xml
Access-Control-Allow-Origin: *

[Response Body]

The web application informs the web client of the allowed domains using the HTTP response header Access-Control-Allow-Origin. The header can contains either a '*' to indicate that all domains are allowed OR a specified domain to indicate the specified allowed domain.

  • Step 3 : Web client process web application response.

According to the CORS W3C specification, it's up to the web client (usually a browser) to determine, using the web application response HTTP header Access-Control-Allow-Origin, if the web client is allowed to access response data.

Risk

A reminder : This article will focus on the web application side because it's the only part in which we have the maximum of control.

The risk here is that a web client can put any value into the Origin request HTTP header in order to force web application to provide it the target resource content. In the case of a Browser web client, the header value is managed by the browser but another "web client" can be used (like Curl/Wget/Burp suite/...) to change/override the "Origin" header value. For this reason it is not recommended to use the Origin header to authenticate requests as coming from your site.

Countermeasure

Enable authentication on the resources accessed and require that the user/application credentials be passed with the CORS requests.

If the CORS resources exposed are classified as sensitive (and CORS exposition is mandatory) it's a good option but if the objective is only to ensure that the request originator is really one of the allowed (to avoid rogue call), there somes drawback with this option, among others:

  • The target application must manage users (or applications) credentials repositories including features like password expiry, password reset, brute force prevention, account lock/unlock,...
  • The client application must store (in a secure way) the credentials to use,
  • The client application must manage/configure credentials transfer in HTTP request in order that credentials are send only in case of CORS requests to target application.

We use the method above because it's not possible to be 100% certain that any request comes from an expected client application, since:

  • All information of a HTTP request can be faked,
  • It's the browser (or others tools) that send the HTTP request then the IP address that we have access to is the client IP address.

Informations links