Monday, March 25, 2013

Cross Origin Resource Sharing Policy and its impact

Cross Origin Resource Sharing (CORS) policy is introduced in HTML5 specification. It allows control over cross domain calls and the application can control over the resource or content. CORS specifications are part of W3C specifications and posted over here - http://www.w3.org/TR/cors/. In the specification extra HTTP headers are added to control the content delivery and loading mechanism. Hence, both HTTP request and response would have few extra headers and they are validated before the actual usage.
The core idea of this specification is to have a key decision based on “origin”. Every request will have their own origin based on their current domain. For example, a browser is at the URL say http://www.store.com/ then their origin at this point is www.store.com. If the loaded page would like to use the API to make a call to say http://google.com then HTTP request will send “origin” information to the server and now it’s up to the server to treat this call or not. Having this mechanism in place empowers the target domain to decide whether or not to share resources over the Internet. This gives a  close control over resource and content sharing for every domain and application. XHR level 1 APIs were not allowed to make a cross domain call but with XHR level 2 specifications one can make cross domain calls provided they abide by CORS. This is a major shift in Internet paradigm and applications now get seamless control over various domains and their content. It adds a security risk as an obvious outcome.
The following are extra headers that are added for HTTP requests. Hence, when a browser transmits HTTP requests that originate from APIs like XHR, it automatically adds some of these headers.
Origin
Access-Control-Request-Method 
Access-Control-Request-Headers
Similarly, when applications send the response back over HTTP, they will also add a range of headers. The browser can take decisions based on these headers and accordingly load content in browser’s DOM (or not load at all). This gives close control and provides a feedback loop. The following are HTTP headers in the HTTP response.
Access-Control-Allow-Origin
Access-Control-Allow-Credentials
Access-Control-Allow-Expose-Headers
Access-Control-Allow-Max-Age 
Access-Control-Allow-Allow-Methods 
Access-Control-Allow-Allow-Headers
This is a much better way of controlling the content over the old method like JSONP. In the past we could make cross domain calls and involve JSON with Padding (JOSNP). For this we make a call to a cross domain using the SCRIPT tag and pass on the function name as a parameter. The cross domain application can thendecide whether to serve or not, and if it decides to serve, then it will send JSON content padded with the same function name. This will automatically get executed in the browser.
For example
The browser will have a function say setProfile like below.
Function setProfile(data){
// do some stuff on JSON
}
Now, when an application wants to make a cross domain call to say http://example.com/ then it will send a request as below.
http://example.com/JSONfeed?name=shah&callback=setProfile
If http://example.com/ would like to serve this call then it will create a JSON for profile where name is shah as mentioned in the URL and wrap with function setProfile like below.
setProfile(JSON-data)
Now, the browser will pass on the JSON-data to the function setProfile and execution will begin from that point onwards. This sounds very bad and not so graceful way to bypass the same origin policy. To avoid this type of methodology, CORS has been implemented in the browser.

Inner working of the CORS

CORS is implemented at the browser end and if developers want to share resources with a cross domain then they can add appropriate code and support at the server end. Hence, the focus of the CORS is primarily at the browser end.
Let’s take two hypothetical domains – redacme.com and blueacme.com. We load a page from redacme.com and it has the following function.
function getMe()
{
    var http;
    http = new XMLHttpRequest();

    http.open("GET", "http://blueacme.com/", true);
    http.onreadystatechange = function()
    {
        if (http.readyState == 4) {
                var response = http.responseText; 
                alert(response);
                document.getElementById('result').innerHTML = response;                 
    }     

}
http.send();
}
This getMe() function is simple XHR call. It is making a cross domain GET call to blueacme.com and try to load the response into specific locations within the DOM defined by “div” tag. When this function being called we get the following request on the wire (Chrome being used)
GET / HTTP/1.1
Host: blueacme.com
Proxy-Connection: keep-alive
Origin: http://redacme.com
User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.75 Safari/537.1
Accept: */*
Referer: http://redacme.com/cors.html
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
As you can see there is one extra HTTP header being added to this particular request and it is as shown below.
Origin: http://redacme.com
This defines the origin from which the call is initiated. The HTTP request is being made irrespective of the policy which is defined on the server.
The server will send following response headers.
HTTP/1.1 200 OK
Date: Sun, 12 Aug 2012 08:01:57 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
X-AspNet-Version: 2.0.50727
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 13539
As no CORS specific headers were sent, this application does not allow the pages to be consumed by the browser. Hence, the page will not get loaded in the browser.
The browser will throw the following error on the console.
XMLHttpRequest cannot load http://blueacme.com/. Origin http://redacme.com is not allowed by Access-Control-Allow-Origin.
This is where CORS kicks in - if “Access-Control-Allow-Origin” is set to “*” or a specific domain then the browser will load the page.
For example, if we were to have the following response then the browser will load the page on redacme.com since it allowed.
Access-Control-Allow-Origin: http://redacme.com
Additionally, the following response header will allow content to be loaded on any domain since the allow access is set to “*”
Access-Control-Allow-Origin: *

Preflight call and negotiation

There are certain limitations at the CORS level. If you want to change certain key parameters like method, content-type etc., then that particular call will not get initiated by the browser but it will make a preflight call to verify the CORS policy set on the server side. Hence, it will send first an additional request in terms of OPTION and then analyze the response. If HTTP response allows that particular method or content-type with respect to the origin then it will make next request.
Consider the following routine.
function getMe()
{
    var http;
    http = new XMLHttpRequest();

    http.open("POST", "http://blueacme.com/", true);
    http.onreadystatechange = function()
    {
        if (http.readyState == 4) {
                var response = http.responseText; 
                alert(response);
                document.getElementById('result').innerHTML = response;                 
    }     

}
http.send("test");
}
We are making POST request and sending some data onto the server. This will actually fire the following HTTP request on the wire to blueacme.com
OPTIONS / HTTP/1.1
Host: blueacme.com
Proxy-Connection: keep-alive
Access-Control-Request-Method: POST
Origin: http://redacme.com
User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.77 Safari/537.1
Access-Control-Request-Headers: origin, content-type
Accept: */*
Referer: http://redacme.com/cors.html
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
You can see some additional headers that are added from CORS perspective. They are as follows.
Access-Control-Request-Method: POST
Origin: http://redacme.com
Access-Control-Request-Headers: origin, content-type
Here, the browser asks the application/server whether it supports these extra HTTP headers or not. If the server responds with allow access true for this particular origin then the browser will make the actual call else it will not initiate the HTTP POST request. Preflight call gives some initial protection against attack vectors like CSRF and so on.

Saturday, January 19, 2013

HTML5/Browser Evolution and Threats

It all started in 1991 when HTTP and HTML came into picture and browser started to evolve. From that time onwards several new set of technologies gradually coming into the browser as per requirements. By introduction of HTML5 it has bounced to the next level. Here is a quick curve of technologies with time.
Figure 1 - HTML5 Evolution
As technologies evolve it brings new feature and threats along. Technologies are making browser much more complex in nature at the same time opens up attack surface for attacker and attack agents.
a.) HTTP and HTML were very static to start with. There is no need of dynamic manipulation within the browser. At some point server side technologies moved out from typical CGI and started to introduce strong feature. At that point one of the biggest limitations of HTTP protocol was realized and that is not having state to the connection. Hence, Cookie came into existence and new complexity added to the browser. At that point browser started to become an attack point and having some “confidential” information.
b.) As infrastructure started to move on the web more dynamic manipulation requirement started to come in and that is where JavaScript, Java and DOM added to the technology stack. It definitely brought new threat vectors to the browser and field became very dynamic. It is well supported by server side technologies like ASP, PHP, Perl etc. It took browser to the next level. At the same time traffic’s integrity and confidentiality became an important aspect. Hence, SSL brought in and point to point tunneling over encrypted channel established. It provides certificate based traffic which helps in maintaining confidentiality and integrity of the information. Again new threat and man in the middle attack vector started to gain popularity.
c.) Applications have started to use HTML, JavaScript and CSS extensively and specifications are empowered by powerful DOM and event models. Specifications are now empowered with new tags, attributes and events. All these are embedded by JavaScript. This new approach gives rise to vulnerabilities like Cross Site Scripting, Cross Site Request Forgery and few other tricks.  Evolution started to reach a point where extensive exposure and attack surface on the browser made open for attackers.
d.) Browser requirements started to grow and plugins like flash being introduced and that took browsers to the next level. Browser’s surface expanded by add-ons, plugins and other similar thick features. At the same time JavaScript and DOM specifications started to spiced up for feature requirements. At the end more attack vectors and exploit opportunities come into existence. Vectors and exploit kits started to use JavaScript extensively.
f.) Developers and world need still better and more generic thick feature solutions. Hence, Ajax driven approach introduced with Web 2.0 technologies. People have started to use XMLHttpRequest object along with powerful DOM manipulations across browser stack. This turns out to be game changer and browser usage started to move towards generic and not plug-in driven. DOM based attacks started to grow from this point onwards. DOM exploitation and information harvesting through JavaScript became a prime attack point from security standpoint. Lot of requirement for secure coding on browser side came as prime requirement.
h.) Finally, HTML5 started to kick in, powerful specifications Canvas, Web Fonts, WebGL, Storage, WebSQL, Web Workers etc. came up and still evolving. HTML5 turns out to be a group of specifications taking browser to the next level. Browser based applications started to evolve and turning out to be powerful single DOM and single page application or software. This is a major change we are getting into. This platform is not restricted to desktop but extended to the mobile as well. All these bring next generation threats and new techniques to existing vectors. As shown on the chart above we have group of new technologies baked in the browser around 2012 and security aspects need greater attention. To analyze and understand overall security picture we need to scope out threat model and threat vectors clearly. It helps in providing secure coding practices around client side components.
Browser architecture would look like below to support HTML5 technology stack.
Figure 2 - Browser with HTML5 stack
During this evolution various different threats and attack vectors evolved. Here is a simple threat bubble for client side attack points.
Figure 3 - HTML5 threats and bubble
As we can see top two vectors were XSS and CSRF, both are leveraging JavaScript extensively. Over period these vectors are used extensively to exploit client side sessions. It allows attacker to get session cookies and hijack the session. It allows access to confidential information and unauthorized session to the targeted web applications. CSRF allows to forcefully replaying cookie along with critical call. It allows generating a request from the browser without user’s consent or knowledge. Those two bubbles grown up over period and became very significant attack vectors. Also, OWASP and other standards have given them ranking in top 10 and must resolved error status. Usually XSS falls into critical bucket and CSRF depends on the type of form or target request.
Other bubbles for attacks were ClickJacking, Abuse of functionality and open redirect. These vectors allow different level of threats to the end users. ClickJacking hijack user’s click without knowledge or consent by injecting iframes and other similar methodologies. Browser’s are having mechanism to allow redirect for business logic and smooth site-to-site flow. This specific feature can be exploited to inject open redirect and compromise user’s trust. At the same time applications are using DOM and related functionalities extensively so abuse around browser side functionalities crop up by attackers and various other toolkits. This is second layer of attack vectors.
Finally, there are several other small bubbles of threats lingering on browsers like Denial of Services (DoS), Phishing, SSL and Crypto issues. All these vectors again bring different level of threats and scenario of exploitation. All these were traditional attack vectors and as technology started to get complex these stack of vectors got their way through into the browser’s threat model. Both browser’s specification weakness and poor programming on the developer’s side lead to wide spread exploitation and great concern for browser security. Browser became the most important window to the world of Internet and its security is utmost important in this era where banking, trading, social networking etc. simply runs on the browser platform. Now, with HTML5 threat are more exposed and mode for evaluation need to change.