Presentation on HTML5 Security, Part-2 - OWASP Hyd

In continuation my previous talk on HTML5 Security at OWASP Hyd, I have covered few more interesting concepts at OWASP Hyd August meet. Slides are more or less the same as my previous session but it was more demo driven where I've shown known security problems and secure coding practices to be followed while using HTML5. 

I've been committing some of the basic demos whenever I find time into my github account. I shall blog more about some interesting topics very soon.

A note on JSONP & misconceptions of Cross Origin AJAX

Web developers who have worked on accessing APIs using JavaScript would be very much familiar with the term “JSONP”. Many web devs whom I have met offline or in online discussion forums seem to have some misconceptions about JSONP. Below are some of the basic & common definitions which I have come across:

  • JSONP is a technique to work with remote APIs
  • It is nothing but Cross Origin AJAX
  • If we add a query string like “?callback=someCallback” and fire jQuery’s $.ajax or $.getJSON, what we are doing is nothing but a JSONP call.
  • May be a slightly complicated definition: Cross origin AJAX is possible only when the response thrown is JavaScript
  • and many more..

The truth in the above statements is very little and such definitions add more confusion, bringing in misconceptions. In my recent presentation “Content Isolation with Same Origin Policy”, I put up the below slides (check slides 4 & 5 in the ppt)

image

image

 

 

 

 

 

 

 

 

 

 

For all practical purposes, the first one is possible and second one is not. Apart from the tweaked definitions of JSONP as stated above, the below reasoning complicates the topic:

  • In the first case, the content requested is of the type “text/javascript” while in the second case it is HTML. So browsers look at content type of the response header and decide whether they should block the content or not (actually, a very good observation).
  • There is a “?callback=?” parameter in the first case enables jQuery to make the cross origin call in the first case
  • Server side framework should have special capabilities (Iike inbuilt serialization/deserialization) for the first case to work

I thought it would be nice to summarize few facts and hence this post. Read on.

What's an Origin?

The combination of scheme://host:port is what browsers treat as an Origin. e.g., http://abc.com, https://abc.com, http://abc.com:81 belong to different origins as they differ in one of scheme, host or port. Remember that http://abc.om/user1 and http://abc.om/user2 are different URLs but not different origins. Also, a domain (http://abc.com) and its subdomain (http://sub.abc.com) belong to different origins (this particular restriction can be relaxed using a technique called domain relaxation, which is out of scope of this topic).

Can my client script read your emails?

Browsers restrict JavaScript calls to server (read as AJAX) based on Origin. This is governed by a policy called Same Origin Policy. In other words, client script in your page can make calls only to your server (strictly speaking, origin). If this rule wasn’t there, it would have been possible to write a script in some arbitrary web page which can read your web based email conversations.

Cross Origin AJAX? Really?

For the reason stated above, a page can make an AJAX call to the same origin from which it originated. If I am allowed to coin an acronym stressing on the boundaries of AJAX, I would coin “AJAX-FOO”, which expands to “Asynchronous JavaScript And XML For Own Origin”. As soon as a new XMLHttpRequest is fired to a remote origin, browsers check the origin of the page with the destination of the request. If both are same, the call is allowed. Else, the call is blocked with an appropriate error message. So there is nothing like Cross Origin AJAX.

Understanding JSONP (TL;DR: It’s all about script tag hack!)

As they say, necessity is the mother of invention. When web2.0 APIs were introduced, they desperately wanted cross origin interactions. JSNOP was discovered as a hack/work-around to bypass the restrictions of Same Origin Policy.

The idea behind it is very simple. Same Origin Policy doesn't apply for scripts (and a couple of other elements too). A <script> tag in a web page can load JavaScript from any origin (i.e., when you embed jQuery.js pointing to a CDN, loading from a remote origin is allowed). Using this loophole, one can create cross origin requests.

Simple example to create your own JSONP service

1. Create a HTML page having two JavaScript files. In script1.js, create a function “processData”

function processData(data){ 
console.log('Hello '+data.firstName+' '+data.lastName);
}

2. In script2.js execute the above function by passing valid JSON data:

processData({firstName:'Krishna', lastName:'Chaitanya'}); 

3. When you load the page, both the script files load, code in the second file executes the function defined in the first file. This is an expected behavior.

4. Create a file “service.abc” (yes, create it with this dummy extension. This is going to be your web service) and place it in the same folder. Open it and write the same code as in step 2. Now open your web server (IIS or your preferable one), go to your site, open mime types section and add a new mime type “.abc” having the mime type value “text/javascript”.

5. Now remove reference to “script2.js” and add a reference to this new file “service.abc” in the head section like this:

<script type="text/javascript" src="service.abc"></script>

6. When you load the page now, you get the same behavior as that of script2. So far, everything is in the same origin. Place the file “service.abc” in another origin (simply create another website on a different port number-recollect that different ports means different origins) and reference it in script tag and the code still works.

What you have done is, you have loaded content from a remote service via script tag injection. This is the essence of JSONP. The idea of having a random file format “.abc” is just to show that any file which can serve script content will hold good for this. You may use your “.aspx”, “.asmx”, “.ashx” or whatever to achieve this.

Hence, JSONP is always a script Injection and has nothing to do with XMLHttpRequest object and AJAX.

How JavaScript libraries like jQuery help (mislead) you

If you use libraries like jQuery, they give you a common syntax which works for AJAX as well as JSONP hack. They do a lot of work behind the screens to make a JSONP script injection

$.getJSON('http://graph.facebook.com/zuck?callback=?', function (data) { 
console.log(data);
}

In the above API for Facebook, if the value for callback is given by the developer as “https://graph.facebook.com/zuck?callback=fetch”, facebook returns json data by wrapping it in the function “fetch” (open the link in your browser and check the output. Note: IE will ask to save the response as ".js" file.). If the function name is omitted, jQuery handles it in an interesting/tricky manner. It takes the success callback as the function to be executed (similar to “processData” function as declared above), creates a random function name and assigns the callback to it. The server too responds by wrapping its json data in the random function name which it got from the request (see the first screenshot in this blog post). Once the http transaction is done, jQuery destroys the random function.

(Note: To test the trick jQuery uses, I used burp proxy to intercept and pause the request sent by jQuery. While pausing, I typed jQuery’s random function name in browser’s console and it printed the definition of the function. After the response is received, I did the same and I got that function is undefined. This way I was able to deduce the trick jQuery uses for JSONP).

In this process, jQuery does not fire an AJAX call. All it does is injection of script tag and serving javascript in its response. Since the syntax for AJAX and JSONP are maintained the same, web developers tend to confuse about JSONP.

So what mime-type should be served for a successful JSONP request?

Well, this is a topic of confusion, at least for me. Since the served content is JavaScript, the preferred mime-type should be “application/javascript” or “text/javascript” or may be "application/json". In my demo, I’ve changed the mime type of the above service to “image/gif”, “text/css” etc and the script still worked in all modern browsers without any warnings. Also, there are cases where browsers show a "save file" dialog when wrong mime type is served. Enabling adhoc mime types has security concerns and research is being done in this area for standardizing mime-type. At least for now, “application/javascript” can be used and anyways CORS is the future, so no more content type worries.

Hope the article provided useful info. Share your thoughts or discuss if you see the need for any corrections. Happy coding Smile

Browser Internals: Content Isolation with Same Origin Policy-Microsoft UG Dev Day

Microsoft User Group Hyderabad (MUGH) has organized Developer Day at Broadridge Financial Solutions, Hyderabad this weekend. It was a half day event with very good line up of sessions and I had the opportunity to present on a very exciting topic-"Content Isolation with Same Origin Policy".

"Same Origin Policy (SOP)" is one of the foundations of web security, which is built into web browsers. Web developers often do not understand this policy clearly and work with several misconceptions. The goal of this session is to show how important SOP is for the web, how it is bypassed using hacks and what HTML5 offers as a standard to overcome its limitations. Getting a full understanding of SOP isn't easy in a one hour session as it is relatively vast and complex. However, I have tried to simplify several ideas and put them in one place in the slides. Folks who couldn't attend the session will also be benefitted from the slides.

Along with my talk, there was an interesting talk "One Service, Any Device, Any Platform-Web API" by fellow MVP Shravan and "A Lap around the new Windows Azure" by our super techie Phani, cofounder of BrainScale. It is really motivating to see close to 100 techies coming to learn cutting edge stuff over a weekend. That was a great time spent! See you in the next tech event. Happy coding :)

Presentation on HTML5 Security-OWASP Hyderabad

Happy to say that I had the opportunity to present at OWASP Hyderabad chapter on "HTML5 Security" on 19th May, 2012. The event had awesome audience from diverse backgrounds in security domain-security researchers, penetration testers, security consultants, few developers etc. The talk went for about 2.5 hours(yes!!) and was quite interactive. The audience were very patient, passionate and we had lots of discussions on several interesting topics.

 

I have built some cool demos for the presentation but the code is not well organized. I shall clean the code and upload to my github account shortly. I would be continuing this talk in next month's OWASP meet too.

JSFoo Chennai 2012–”JavaScript is mischievous. Handle 3rd party content with care!”

It is always exciting to attend a technical conference focusing on a particular theme and even more if you get the opportunity to present. Continuing their good run, HasGeek has organized JsFoo Chennai 2012, India’s first JavaScript conference series, at IIT Madras Research park. There were several interesting proposals made and mine got voted for the final schedule along with other awesome entries.

My session is about the security considerations one should think of while integrating 3rd party JavaScript content into their site (in other words, security of web mashups). 

mashups

Presentation: Click here

Demos: Recursive Mashup Attack and Clickjacking

Learning aside, the best part is, I’ve met several awesome passionate geeks, few whom I know on twitter and few I would have never met otherwise. Loved the event even more, since people working on different platforms and having good expertise in JavaScript came under one roof and discussed. Diverse opinions and lots of learning!!

For those who missed, check JsFoo site for videos of sessions, which will be uploaded shortly. Also, here is an interesting review written by one of the attendees.

It is this easy to steal your click!-DevCon 2011

The memories of DevCon 2010, where I presented on “Facebook Apps Development” are still fresh in mind and DevCon 2011 is back! This time I have presented on “Clickjacking”, one of the popular modern web based attacks, using which an attacker can steal user’s click. The session is heavily inspired by the research done by Stanford Security Lab & Internet Explorer Team. It focuses on explaining how users fall prey to clickjacking attacks and what care web developers should take to defend against them.

The event, organized by Microsoft User Group Hyderabad (MUGH), had more than 300 audience and was held at Microsoft Hyderabad campus. 

agenda!

Presentation: check Slideshare

Demos source code: check GitHub

There were several interesting sessions presented by speakers on cutting edge topics such as Windows Azure, ASP.NET MVC3, Bringing HTML5 experiences to ASP.NET website, Patterns & Practices in C#, SharePoint 2010, SQL Server Denali and Knotting Windows phone 7, Azure & Kinect. The audience were very enthusiastic and interactive, which made the sessions lively. Nice to meet several techies in the event. The learning I had was huge while preparing for this session and answering Q &A :)

The need for HTML5 postMessage API

The postMessage API in HTML5 specification is useful for making cross domain calls across frames. This is typically useful for mashups, Web 2.0 sites (e.g., pageflakes.com) where different widgets might need to communicate with each other.

HTML5 postMessage Demo

Few developers have already started using HTML5 postMessage in their projects, without knowing why they are using. Here are a couple of questions an inquisitive developer might have in mind:

1. How are mashups and rich Web 2.0 applications built even before HTML5 postMessage API came into existence?

2. What is the trust model which Web 2.0 sites have? (Who trusts whom?)

3. Is there really a need for a new API when workarounds met the needs?

This post tries to answer these questions and explains why postMessage API is important. Though the usage of API looks trivial, the birth of this API is the outcome of several insightful research papers, which are also a motivation for this post.

In the screenshot, the web pages loaded in the top window and iframe are from different domains. On clicking the submit button, the message in textbox is sent to iframe and displayed in the last line. Notice that the top window url (http://localhost/postMessage) has a default port number(80), while the iframe has a different port number (81). Hence the site in iframe is treated as that from a cross domain.

HTML5 postMessage API is as simple as the below JavaScript code.

<script language="javascript">
        window.onload = function () {
            win = document.getElementById("ifrDomain2").contentWindow; //get the target iframe window
            frm = document.getElementById("frmPost");  //get the form which needs to post a message
 
            frm.onsubmit = function (e) {
                msg = document.getElementById("txtMessage").value;  //get the message to be posted from the textbox
                win.postMessage(msg, "http://localhost:81/");  //post the message to the destination URL
                e.preventDefault();  //prevent default action (suppress postback)
            };
        };
</script>

Now let us see why such an API is needed in the first place and try to answer the above questions.

Same Origin Policy and Trust Model:

As most of you know, the Same Origin Policy (SOP) of browsers disallows scripts loaded from one origin to access DOM of another origin (Two sites do not belong to same origin if they differ in at least one of the three- protocol, domain name or port number). Due to this, an AJAX call cannot be made from one domain to another domain from a browser. So far so good, since if this policy is not in place, an attacker can make an AJAX call to your site and grab your cookie.

However, the SOP is not applicable to scripts themselves! Developers can always embed script tags which point to different domains (just as we include reference to jQuery or any JS library from CDNs). If there are scripts from multiple sources, the application is not secure. But this is how mashups and most of our web applications are built! Isn’t this ironical? Moreover, the scripts which are loaded from different domains run under the privilege of the host site. So whether it is external script file or JSONP script injection, the developer should have ‘complete trust’ on the scripts being injected.

As Douglas Crockford rightly points, “A mashup is a self-inflicted XSS attack”. It is more of a work around than a standard.

Instead of loading external scripts in an integrated site, an alternative is to use iframes to load external sites. Since iframes provide complete isolation mechanism, aggregating content is secure, but genuine communication between frames goes for a toss.

Most of the modern Web 2.0 sites rely on external JS libraries, AJAX and JSONP techniques for fetching, manipulating content. In this case, communication between widgets (divs) is not a problem since entire DOM is accessible to any script (bad design w.r.t security as discussed above). Sites using iframe for isolating widgets rely on “fragment identifiers” (e.g., yoursite.com#message) for communicating between widgets (has confidentiality but no authentication and integrity). These (flawed?) solutions answer our 1st question.

So the trust model we have is, you as a developer/site owner should either trust all (in case of scripts) or trust none (in case of iframes), but nothing in between. This answers our 2nd question. You may trust the JavaScript provided by Google analytics, maps, facebook widgets etc., but this dependency on ‘trust’ does not scale well.

Browser vs. OS:

The modern web has seen data intensive, rich and interactive web applications, which mimic desktop applications. Mashups, which are applications that combine data from multiple data sources, have changed the boundaries of a web browser. Concepts like Web OS started evolving which guided researchers to draw a parallel between browsers and OS.

  • The “system calls” in OS are analogous to “DOM calls” in browsers
  • “Processes” in OS are analogous to “Frames” in browsers
  • “Disk storage” in OS is analogoius to “cookies, localStorage, IndexedDB etc.” in browsers
  • In an OS, “Users” are the principals (which need to be distinguished), whereas in a browser, “Origins” are the principals.

Browsers, which were designed to handle pages from a single domain at a time are now forced to handle pages/data from multiple domains. In other words, as researchers say, web browsers have evolved from a single-principal platform to multi-principal platform. However, unlike OS which can easily handle multi-user scenarios, web browsers prior to HTML5 postMessage did not have the capability to abstract multi-principal scenarios. Their trust model remained the same as discussed above.

Hence, there is a need for a newer standard supported by browsers, which can securely abstract multiple principals and provide communication between them, thereby improving the trust model (answers 3rd question). There were several recommendations like JSONRequest, Verifiable Origin Policy, CommRequest etc.,as described in the references, for solving these problems and finally, the HTML5 postMessage API came into existence.

//Syntax of HTML5 postMessage
otherwindow.postMessage(message, targetOrigin); //Clearly, the "targetOrigin" parameter improves trust!

The postMessage channel, which is designed for cross site communication, guarantees confidentiality, integrity and authentication and improves trust (A frame can now communicate with a trusted frame by specifying the target). With this standard in place, frames can now be attractive feature to integrate 3rd party content, create widgets with improved trust. It is supported by majority of modern browsers (IE8+, FF3+, Chrome, Safari, Opera 10+).

Hope the article helped in understanding why HTML5 postMessage is needed and possibly pointed out the mistake you are doing by not using it for your requirements. Let us build a more secure and standard compliant web, one website at a time Smile

References:

1. “Securing Frame Communication in Browsers” – by Stanford web security lab

2. “Protection and Communication Abstractions for Web Browsers in MashupOS” – by Microsoft Research & Stanford web sec lab.

Frame navigation policies in web browsers | One big reason why you should get rid of old browsers

Whether you are aware or not, frames are commonly used in most of the websites we use, for various purposes such as widgets in mashups, containers for advertisements, at the least for loading arbitrary documents into web pages. To serve this purpose <iframe> is used, while <frameset> and <frame> which were initially used for navigation are made obsolete in HTML5.

Frames are used primarily to isolate untrusted content such as remote scripts of widgets/ads etc., from interacting with rest of the DOM. Frames comply with Same Origin Policy if they load remote pages. This means, if an iframe is loaded with a page from same domain, it allows DOM manipulations to and from its parent page. Where as if it is loaded with a page from a different domain, it will restrict DOM manipulations and provides an isolated environment. The below code snippets should make this clear.

<!-- This is allowed -->
<iframe src="sameDomainPage.html"> </iframe>
alert(frames[0].contentDocument.body);  //works fine
 
<!-- This is **NOT** allowed -->
<iframe src="http://google.com"> </iframe>
alert(frames[0].contentDocument.body);  //throws error

As a developer, our knowledge of using frames ends here. We are happy with the secure isolation of content and don’t care beyond. But if we look a little deep into how browsers decide what should go into a frame, the scenario becomes scary!

Frame Navigation-who decides what:

Though the same origin policy of browsers isolates frame content of different domains, it has nothing to do with navigation of frames. i.e., if you know the id of a frame, you can navigate it to a different URL. (The browser window can be considered as a top level frame, having a visible address bar which iframes lack).

//Open google.com/ig and execute this script in console
myFrame=document.getElementsByTagName('iframe')[2];
myFrame.src="http://google.com"

Did you see the problems here? So if your trusted components are in iframes, what if someone can redirect the frame to a malicious URL? Which iframe has the permission to navigate which  other iframe on a complex mashup page like iGoogle? Even worse, can iframes on a different window/tab navigate the iframes on your page? What about popups? Do you feel the sense of insecurity now?

Well, the fact is, none of these are under the control of web developers. The policies used by browser vendors answer the above questions and developers should know these policies to understand how secure their websites are. Below are the navigation policies used by browsers. These are quite complex to have a deep understanding, so I just mention an outline :

1. Permissive policy: This policy prevailed in all browsers prior to 1999. It simply states that a frame can navigate any other frame. The frames can be in the same window or in different windows. This dangerous policy gave rise to what are called “Cross window attacks”. Several sites like CitiBank kept their password fields in iframes for secure sandboxing. So, an advertisement in another window or a popup containing malicious script can redirect the password frame to an evil frame  and grab credentials! IE6, Safari 3 and Flash by default used permissive policy.

2.  Window policy: Starting 2001, browsers implemented  a new policy called window policy, in order to prevent the cross window attacks. As per this, a frame can navigate frames in its own window and hence external popups/ads cannot affect frames of a different window. However, this gave rise to new line of attacks called “Same window attacks”. Using this policy, advertisements in the same window or evil gadgets (widgets)  in mashups (e.g., iGoogle) can redirect legitimate gadgets to malicious URLs. So Gadget hijacking became the fashion of the day due to this policy. Firefox 2 and Opera 9 followed this policy which is dangerous to work with today’s gadget rich Web 2.0 applications.

3. Child Policy: This is a stricter policy, which says that a frame can navigate only its direct child. IE6 team wanted to enable this by default but did not since majority of the existing sites are not compatible with this. Such a strict implementation will prevent even the navigation of legitimate frames which are from same origin as the parent. So this policy could not be implemented.

4. Descendant policy: This is another stricter policy which was designed by IE7 team and it provides the best trade-off between security and compatibility. As per this, a frame can navigate only its descendants. So this prevents the cross window as well as same window attacks. HTML5 working group has standardized this policy

Frame navigation policies in browsersThe above picture explains the policies better. The outer blue box is the browser frame, the inner blocks are iframes and the arrows indicate who can navigate the content of what. Notice that child policy is a subset of descendant., descendant is a subset of window., window is a subset of permissive policies.

All modern browsers (IE8+, FF3+, Safari 3+, Opera >9) follow the descendant policy to navigate frames and hence are more secure than their older  counterparts. This is one of the several hundred reasons why you should get rid of older browsers when you use modern web 2.0 applications.

While we discussed about frame navigation so far, the next problem is how do legitimate frames communicate with legitimate content. e.g., communication between partner gadgets in a mashup. Though there are hacks like using fragment identifier or APIs like HTML5 postMessage, attacks like Reply attack, Recursive mashups attack are made possible with a good understanding of these policies. I shall cover on these and few more interesting scenarios in my upcoming posts e.g., what happens if your website can be framed by attackers and leverage descendant policy for backdoor communication?

Reference: The Stanford security researchers have published an excellent research paper-"Secure Frame Communications in Browsers (pdf)", which is the motivation for this post. Due credits to the authors. Suggest you to go through it for better picture.

Happy secure coding :)