ECMAScript, Mashups, and Security
A mashup composes a web application by combining programs and data services from multiple originators, and delivers it for presentation on a single web page. Usually, these programs and services interact with each other - housing maps being the canonical example.
The same origin policy (SOP) governs access control in today’s browsers. It prevents documents or scripts loaded from one origin from getting or setting properties of documents from a different origin - it provides total isolation. While this is useful to protect one origin from another, it shackles mashups. A common technique mashup authors have used to break free is by clever use of the script tag. The SOP is not applicable to the src attribute on the <script> tag; a document may contain <script> elements from different origins (or domains). Such third party scripts are treated as originating from the document’s origin and can access all of the document’s resources - they have total trust.
Faced with this all-or-nothing security model, the mashup developer can use the <iframe> structure to confine components such that they cannot interfere with each other, but the SOP isolates them so completely that they are also unable to cooperate, or, use the <script> tag and ECMAScript to enable cross domain data exchange and compose rich client-side mashups.
ECMAScript, thus, finds itself being used as a composition language - composing separately written programs into a single web page. Such composition presents several challenges, one of them being the ability to compose securely. When separately written programs are composed so that they may cooperate, how do you prevent them from interfering in unanticipated ways? Does ECMAScript, as a language, support secure software composition? Several features in the language would suggest otherwise. Here are a few:
Global scope: All script code executing within the same web page (or <iframe>) implicitly share access to the same global scope. Therefore, globally reachable objects cannot be isolated from each other.
Freely mutable state: Certain objects, like Array.prototype, are implicitly reachable even without naming any global variable names. Even if the global scope problem is addressed, the mutability of these objects prevent isolation.
Freely mutable properties: While some built-in properties are constrained to be Internal, ReadOnly, DontEnum, or DontDelete, there is no way to express these constraints in the language. Any object defined in user script code is freely mutated by any other code which can access it.
Lack of encapsulation: Objects need to be able to encapsulate their private state. The best one can do is to use an idiomatic functional style to simulate private members as well as private static members. But it is idiomatic; neither widely taught nor uniformly followed.
for..in loop: The for..in loop enumerates the names of all of an object's properties, whether inherited or not, unless the property has the DontEnum attribute (which the programmer has no way to express). When composing using mixins, programmers must carefully skip over some of these names. Re-inventions of idiomatic mechanisms to achieve this abound.
"this" binding: The rules for binding “this" depend on whether a function is invoked by construction, by method call, by function call, or by reflection. If a function written to be called in one way is instead called in another way, its “this" might be re-bound to a different object or even to the global scope.
eval: There is no simple way to constrain the script or to inspect it before it executes. It runs with the same authority as scripts from the page.
with: with augments the scope chain causing some confusion to the reader about the specific object to which a particular property access gets bound. A bigger problem is probably the with-like semantics implemented by Internet Explorer and Firefox for the exception object within a catch clause of an exception handler. This semantics allows malicious code to inject names into the dynamic scope of a theoretically secure handler. This construct, along with eval, calls for studied usage.
Mashups are not new. The early and simple mashups merely loaded an image from a different site, while the contemporary and more profitable ones pop up relevant advertisements as you browse. Rich media ads are mashups. Most rich ads are served from third-party sites into the context of the existing experience. The ad script has access to all of the information on the page, including cookies and the connection to the originating server. Whenever you include any script on your page, you are implicitly trusting that script will neither interfere, maliciously or otherwise, nor destabilize your page. After all, a poorly coded ad can easily bring down the entire application. Security, then, is critical to the growth and success of mashups.
Within the Web community there are various initiatives that attempt to address this challenge. Facebook with FBML and FBJS attempts to constrain the language and DOM semantics to protect their users. Adsafe and Caja propose a subset of the language and corresponding semantics that can be validated. Many gadget approaches attempt to use IFrames to provide isolation.
Such initiatives are valuable because they are exploring the solution space of the mashup security problem. However, currently they only provide local and limited solutions to the problem. In the long run the best solution is to provide common ubiquitous support for secure mashups within all browsers. This is the realm of web standards, and mashup security should be a high priority item for future revisions.
In the meantime, I am interested in knowing what kind of composition challenges you have faced with JScript and mashups, and how you have addressed each of them.
Pratap Lakshman, JScript
Comments
Anonymous
November 29, 2007
One thing I can tell you: using IFrames for mashups in IE6/7 is a very bad idea. That is what we tried, but as soon as I have 9 applets running in an IFrame IE slows down considerately. Another issue with IFrames is that dynamically adding/removing them can cause memory leaks which are not easy (if not impossible) to remove. I whish I could just import a JavaScript in a namespace and only allow it to step outside this namespace with API's endorsed by the mashup HTML/JAVASCRIPT. This way the mashup developer can restrict what these external scripts are allowed to do... maybe even let the control all the way to the user... but that will be very user unfriendly.Anonymous
November 29, 2007
The major issues I've hit are the inconsistencies between the specs for ECMAScript, and those implemented in JScript. When generating an iframe, I usually don't want the border to display, thus I call iframeObj.setAttribute('frameborder',0); In JScript/IE, this is broken, and I have to do an additional call to set the 'frameBorder' to zero. (see bug details here) http://webbugtrack.blogspot.com/2007/08/bug-242-setattribute-doesnt-always-work.html Beyond this, my problems are those of a XSS fear. Scripting in IE has notoriously opened up some privilege escalation issues, or script injection. I am concerned about what data is shared across frames. IE7 may have fixed most of this, but I'm not very confident, since JScript was all but ignored for IE7 development.Anonymous
November 29, 2007
I just released a small library that enables secure client-side cross-domain communication. More details here: http://www.julienlecomte.net/blog/2007/11/31/ I wish browser vendors would implement at least parts of the HTML 5 draft spec as soon as possible (or some alternative, such as the <module> tag)
- Julien -
Anonymous
January 19, 2008
@Julien: Thank you for pointing to CrossFrame. I view it as a messaging system between a third party iframe and the host page/another iframe. Would you agree that it does not completely solve the ad security issue I point out in my blog post?Anonymous
May 22, 2008
Related to the IE Blog post around mashups in Internet Explorer 8, the Jscript team has a great postAnonymous
May 22, 2008
Please check out http://blogs.msdn.com/ie/archive/2008/05/19/enabling-mash-ups-in-internet-explorer-8-with-cross-document-messaging.aspx for the HTML5/IE8 solution for cross-frame communications.Anonymous
May 22, 2008
Hi, this post can summed up basically, "I don't know what ECMAScript is, but because it's semicolon delimited, I can apply all my existing knowledge in C# to it."Anonymous
May 23, 2008
Can you please sum your reply normally, I don't really get it :PAnonymous
May 23, 2008
You know....if you followed the ECMAScript 4 discussions,you would know that most of these problems are solved....Anonymous
May 23, 2008
There are a number of things that make ECMAScript mashups particularly tricky:
- If a trusted object calls a function of an untrusted object, the "caller" property gives the callee access to a number of the caller's objects, making it difficult to reason about the consequences of calling untrusted script. For this reason, many of the safe subsets ban the use of caller.
- Without a language feature like "final" in Java, untrusted script can often return dangerous objects to trusted scripts. Imagine a trusted function that expects an untrusted function to return a String. The trusted function then sanitizes the string and inserts it into the page's DOM. The untrusted object can act in all ways like a String, but refuse to be sanitized (for example by return the wrong answer for charAt). When the trusted script inserts the "sanitized" "string" into its DOM, the untrusted script escalates its privileges. These and similar problems have plagued direct ECMAScript-to-ECMAScript contact between different trust domains. For example, Mozilla has experienced a long sequence of these issues with their "chrome" (privileged) script interacting with content script from the web. Technologies like postMessage avoid these issues by serializing ECMAScript objects to strings before transferring them between trust domains.
Anonymous
May 25, 2008
The same origin policy (SOP) is very partial. Consider this : <script src="http://anothersite.com/communicationTool.js"></script> Scripts : /* Content of the communication script / var sendAsyncDataCallBacks = []; function sendAsyncDataTo(url, data, callBack) { sendAsyncDataCallBacks.push(callBack); var s = document.createElement("SCRIPT"); s.src = url + "?data=" + escape(data) + "&callBackName=" + escape(sendAsyncDataCallBacks.length); document.body.appendChild(s); } / Content of the URL handler */ <% DoSomethingWithData(Request["data"]) %> sendAsyncDataCallBacks<% Response.Write(Request["callBackName"]) %>; sendAsyncDataCallBacks[<% Response.Write(Request["callBackName"]) %>]=null;Anonymous
May 26, 2008
I find it odd that you use Array.prototype in your example yet we all know that IE is the only browser that doesn't handle this correctly. Never mind mutable, what about follows specs? is a native JavaScript Object? The performance tweaks are much appreciated but [Array] is still a long way off. One other thing not mentioned in the mashup discussion is that if you "own" both domains, you can navigate from A to B, then back to A (quick redirect) it isn't overly pretty, but both can access window.name stuff some JSON data in there, that B can read when it loads, and B can alter before redirecting back to A. It isn't very secure, and it sure is hacky, but it has been used a fair bit to overcome some of these SOP issues, when YOU DO own both domains.Anonymous
June 10, 2008
I want to learn Jscript to, but I have no clue where to begin! Can you show me some resources?Anonymous
July 02, 2008
Hi! I’m Eric Lawrence, Security Program Manager for Internet Explorer. Last Tuesday, Dean wrote aboutAnonymous
March 16, 2009
    안녕하세요! 저는 인터넷 익스플로러 보안 프로그램의 책임자인 에릭 로렌스라고 합니다. 지난 화요일, 딘(Dean)이 신뢰성 높은 브라우저 에 대한 저희의 생각을Anonymous
April 17, 2009
yeah I would realy like too learn it too only too just start en look search for your own I would Like too have a Tutorial any one has a link ?Anonymous
April 25, 2009
yeah thats a fine Idee I am learning it now and it realy helps me too do things better and Way more faster then I did befor. sorry I don't know any Tutorials Kind regards.Anonymous
April 12, 2010
Thanks for the great post. @ hypotheek berekenen: I also want to learn javascript. I should focus on the basics first.