Section: New Results

JavaScript Implementation and Browser Security

We have pursued the development of Hop and our study on efficient and secure JavaScript implementations.

JavaScript Property Caches

JavaScript objects are dynamic. At any moment of their lifetime, properties can be added or deleted. In principle a property access requires a lookup in the object itself, and, possibly, in all the objects forming its prototype chain. All fast JavaScript implementations deploy strategies to implement this lookup operation in nearly constant time. They generally rely on two ingredients: hidden classes and property caches. Hidden classes describe object memory layouts. Property caches use these descriptions to access objects directly, avoiding the normal name lookup operations. Hidden classes and property caches make property accesses comparable in speed to field accesses of traditional languages like C and Java.

Hidden classes and property caches are not new. They were invented for Self, the first dynamically typed prototype-based languages, following Smalltalk's idea that already used caches at that time for optimizing method calls. For the past ten years they have enjoyed a revival of interest after it was shown how effective they are at improving Object-Oriented languages performance in general and specially JavaScript. Today most JavaScript implementations such as V8, JavaScriptCode, and SpiderMonkey use them. Hidden classes and property caches apply in specific situations, which unfortunately means that some accesses are unoptimized or not treated very efficiently.

  1. Property addition problem: hidden classes support the accesses of existing properties but they do not handle efficiently property addition commonly found in object constructors.

  2. Prototype properties problem: hidden classes and property caches optimize accesses of properties directly stored in the object. They do not optimize accesses of properties stored in one of the objects composing the prototype chain.

  3. Polymorphic properties problem, as property caches require strict hidden class equivalence for optimizing accesses, polymorphic data structures and polymorphic method invocations need special treatment to not be left unoptimized. This has been addressed by the Polymorphic Inline Cache technique proposed by Holzle et al. in previous studies, which resorts to a dynamic search in the cache history. As a linear or binary search is involved, it is not as efficient as plain property caches.

Problem 1 is critical for all existing JavaScript programs as it impacts the performance of object construction. Problems 2 and 3 will become prominent with the advent of ECMAScript 6 class-like programming style that is backed up by object prototypes. We propose solutions to these problems. At the cost of one extra test inserted at each property access, we optimize prototype property accesses. Resorting to a static analysis, we propose a technique that we call speculative caches for optimizing object construction.

Trading memory space for speed, we propose cache property tables that enable accessing polymorphic objects in constant time. For the analogy with C++ virtual tables we call these cache tables vtables.

We have implemented these techniques in Hopc, the Hop static JavaScript compiler and we have presented them in a conference publication [17]. We have shown how the complement and enhance property caches used for accessing object properties of JavaScript like languages. We have shown that they take over classical caches when the searched property is either stored in an object of the prototype chain or defined using accessors. They also support efficiently polymorphic and megamorphic property accesses. Finally, they also support efficient object extensions. These techniques do not apply as frequently as simple property caches that cover a vast majority of accesses. However, since they impose no overhead when not used, they can be integrated in any existing system at no run time cost. We have validated the approach with an experimental report based that shown that the presented techniques improve performance in situations where simple cache miss.

Secure JavaScript

Whereas the dynamic nature of JavaScript plays an essential role in the advantages it offers for easy and fast development, a malicious JavaScript program can easily break the integrity and confidentiality of a web or IoT application. JavaScript dynamic semantics and sharing are deeply intricated and attacker code can trivially exploit these.

We have developed a compiler, called SecureJS to offer security guarantees for JavaScript on clients, servers, and IoT devices. Our compiler is applicable to ECMAScript 5th legacy code, which in particular means that we allow for built-in JavaScript functions. Moreover, we go beyond the JavaScript language and handle a common web API, XMLHttpRequest module. The challenge is to cover most of the JavaScript language efficiently while providing strong security guarantees. For the latter, we formally define and prove the compiler's security guarantees by means of a new security property, coined as dynamic delimited release, for JavaScript integrity and confidentiality.

Compiled programs can be effortlessly deployed in client, server, and IoT JavaScript environments and do not require an external isolation mechanism to preserve integrity and confidentiality.

We have validated SecureJS experimentally using ECMAScript Test262 test suits. First, we have shown that SecureJS preserves the correct SecureJS semantics. Second, we have shown that it successfully implements the memory isolation needed to enforce the security property.

The current SecureJS implementation as been architectured to support low-power platforms that only supports ECMAScript 5. In the future we plan to accommodate more recent version of JavaScript for the platforms that supports it. This will extend the possibility of communications between trusted and untrusted codes and this will enable more efficient implementation techniques. A paper describing this work is currently under submission.

Empowering Web Applications with Browser Extensions

Browser extensions are third party programs, tightly integrated to browsers, where they execute with elevated privileges in order to provide users with additional functionalities. Unlike web applications, extensions are not subject to the Same Origin Policy (SOP) and therefore can read and write user data on any web application. They also have access to sensitive user information including browsing history, bookmarks, credentials (cookies) and list of installed extensions. They have access to a permanent storage in which they can store data as long as they are installed in the user's browser. They can trigger the download of arbitrary files and save them on the user's device. For security reasons, browser extensions and web applications are executed in separate contexts. Nonetheless, in all major browsers, extensions and web applications can interact by exchanging messages. Through these communication channels, a web application can exploit extension privileged capabilities and thereby access and exfiltrate sensitive user information.

We have analyzed the communication interfaces exposed to web applications by Chrome, Firefox and Opera browser extensions [18]. As a result, we identified many extensions that web applications can exploit to access privileged capabilities. Through extensions' APIS, web applications can bypass SOP and access user data on any other web application, access user credentials (cookies), browsing history, bookmarks, list of installed extensions, extensions storage, and download and save arbitrary files in the user's device. Our results demonstrate that the communications between browser extensions and web applications pose serious security and privacy threats to browsers, web applications and more importantly to users. We discuss countermeasures and proposals, and believe that our study and in particular the tool we used to detect and exploit these threats, can be used as part of extensions review process by browser vendors to help them identify and fix the aforementioned problems in extensions.