The client browser then establishes a connection to www.bar.com and makes a GET request via HTTP. Cross-site HTTP requests support both GET and POST methods without having to perform a “preflighted” OPTIONS request, which is used to ensure the request is safe to send. When the request is sent, an Origin http header is included with
a value of the domain or site that served the original page, which in this case is http://www.foo.com.
permitted. If it is permitted (or more likely not checked), it responds with a CORS header response and the requested resource. In this example, the www.bar.com website allows cross-site HTTP requests from any domain, which is indicated by the Access-Control-Allow-Origin: * response header.
Basically, the Access-Control-Allow-Origin header tells the browser which origins are permitted to access the requested resource. If the value is an * then any origin domain is permitted to access the resource. If, however, the header in our example instead had a value of www.bar.com, then the XMLHttpRequest would fail, and the content from the request resource would not be available to the browser.
All the major browsers that support HTML5 support CORS. However, IE9 supports CORS with a different object called XDomainRequest rather than XMLHttpRequest.
requests with resources from many different sites.
So how can we make cross-site HTTP requests to resources that require authentication? By default, the cross-site XMLHttpRequest does not send cookies or credentials with the request. However, a specific flag is available in the XMLHttpRequest object that will cause the cross-site HTTP request to include HTTP cookies and HTTP authentication information.
By setting the .withCredentials flag to true, the XMLHttpRequest will include any cookies available in the browser for the target domain. However, this is only half of the story. The server must also respond with an Access-Control-Allow-Credentials: true as a HTTP header in the response, otherwise, the browser will reject the response, and thus not make the response available to the invoking web content.
Let’s assume that all the internal web applications include an HTTP response header of Access-Control-Allow-Origin: *. Let’s also assume that some of the internal web applications require authentication to access specific resource, but also either never expire the session, or have a “remember me” feature that automatically authenticates the user. Remember, these are internal web apps, so, we’re probably not too far off from reality. The attack starts with an ex-employee, with some inside knowledge of the internal environment, sends a malicious link to a number of previous teammates. Of course, they can’t help but click on the link, which takes them to an evil web site. A page is loaded that includes some well-crafted Java Script, along with some entertaining content to keep the user occupied.
While the user is being entertained, the JavaScript makes a cross-site HTTP request to an internal web site; in this case it’s http://www.foobar.com/page. The ex-employee has included the withCredentials flag set to true so he can leverage any cookies that are already in the user’s browser to authenticate to the target site.
The ex-employee’s code can now perform other actions against the internal site, and can send data received from the internal server, back to his server on the Internet, all without the user noticing.
So it’s pretty clear that allowing cross-site HTTP requests from any domain is a bad idea and that it makes sense to set the Access-Control-Allow-Origin header to only those domains that are expected to perform cross-site requests. However, these can be circumvented with a Man-in-the-Middle attack! Remember that it is the browser that enforces the server restrictions set by the HTTP header, so if anyone can manipulate the responses back to the
browser, then the restriction can be circumvented. For instance, with Burp, you can setup automatic match/replace values using regular expressions. This can be found under the Proxy tab, and then under the Options sub-tab, then scroll down to Match and Replace. Replacing the value for the Access-Control-Allow-Origin header with an “*” will tell the browser that cross-site HTTP requests are permitted from any domain, thus any resource data sent to the browser will be accepted.