Zac
Zac
Third-Party Javascript code inclusion is a cornerstone of todays Web 2.0 applications. Without it, rich, personalized start pages, such as on iGoogle and My Yahoo!, would be un- thinkable. Facebook wouldnt be as rich as it is without external applications. Even targeted advertising, such as Google AdSense, would be impossible. However, despite external codes usefulness, including it poses a threat to the hosting page. JavaScript can modify the pages layout and functionality to a potentially arbitrary degree. Web 2.0 is a concept that takes the network as a platform for information sharing, interoperability, user-centered design, and collaboration on the Internet or World Wide Web. A Web 2.0 site allows users to interact and collaborate with each other in a social media dialogue as creators (prosumers) of user-generated content in a virtual community, in contrast to websites where users (consumers) are limited to the passive viewing of content that was created for them. Examples of Web 2.0 include social networking sites, blogs, wikis, video sharing sites, hosted services, Web applications, mashups and folksonomies. ZAC(Easy Access Control) is a practical lightweight library for access control in JavaScript based on aspect orientation. The ZAC access control architecture is stack-based, very similar to the ones of Java and C#. However, ZAC integrates other interesting features for more expressive access control. First, access control policies can be enforced at the level of objects, which permits more fine-grained control over the access to resources. Second, policies in ZAC can base their decisions on the execution history of scripts, which permits to express policies that are impossible to define using other models, such as bounded-time execution. AOP (Aspect Oriented Programming) is designed to handle cross-cutting concerns by providing a mechanism, the aspect, for expressing these concerns and automatically incorporating them into a system. AOP does not replace existing programming paradigms and languages; instead, it works with them to improve their expressiveness and utility. It enhances our ability to express the separation of concerns necessary for a well-designed, maintainable software system. Some concerns are appropriately expressed as encapsulated objects, or components. Others are best expressed as cross-cutting concerns.
Page | 1
Page | 2
presence of the untrusted entity on the stack. This is exemplified in the following piece of code, in which accessing a sensitive resourcethe networkis forbidden:
var trusted = { newRequest: function(url){ return new XMLHttpRequest(url); } }; var untrusted = { m: function(){ var req = trusted.newRequest(...); } }; untrusted.m();
(top) Stack
Stack inspection
When the function m is executed, the untrusted object invokes newRequest on trusted to create a new XMLHttpRequest object. Assuming that the stack inspection algorithm is triggered as in Java with a call to checkPermission (signaled by the CP gray square on the above figure), the instantiation is prevented by throwing an exception. This is so because the stack inspection algorithm eventually checks the permissions of untrusted and discovers that it does not hold the necessary permission to access the network. Privileged execution. In some scenarios, it is necessary for an entity to access a sensitive resource on behalf of anotherpossibly untrustedentity. For this, the JVM supports privileged execution. For instance, suppose that we want to provide a netService object that allows any client to access the network, provided that the target site pertains to a list of known sites. In this case, the creation of an XMLHttpRequest object should be allowed even when there are untrusted objects participating in the current call stack. A self call to doPrivileged initiates a privileged action. Consequently, stack inspection only considers the permissions of objects on the stack corresponding to the dynamic extent of the privileged action, including the initiator of the action; i.e. the stack inspection algorithm stops at the frame of the initiator of the call to doPrivileged.
Page | 3
var netService = { newRequest: function(url){ if(/* url pertains to the known sites list */){ return this.doPrivileged(function(){ return new XMLHttpRequest(url); }); } return null; } }; var untrusted = { m: function(){ var req = netService.newRequest(...); } }; untrusted.m();
XMLHttpRequest create(url) (CP) anonymous fun netService doPrivileged(..) netService newRequest(url) untrusted m() :
Stack Inspectio n (top) Stack
Permission contexts. When accessing a sensitive resource, it can be necessary for an entity to use the permissions present at another point in the execution of the application. The JVM provides the means to capture a permission context and restore it later on. In JavaScript, this can be used to capture the permission context at the time a network connection is initiated, and reinstall it when the response from the server is received (asynchronously). This way, the response processing is performed with the same permissions as the call, similarly to a synchronous communication. Note that since JavaScript is a single-threaded language, this is the only way to correctly manage the switch permissions.
Page | 4
FEATURES OF ZAC
ZAC combines very interesting features: Dynamic enforcement of policies enables the execution of programs that are safe but use unsafe constructs. For example, programs that use eval only to deserialize JSON objects from strings, and not to execute arbitrary code, are safe. However, because they use a potentially unsafe construct, such programs are rejected by systems like AdSafe. Being based on dynamic aspect-oriented programming (AOP) allows ZAC policies to reason about program execution in its entirety. For instance, it is possible to define a policy that prevents a script from never ending, or taking too much time for acceptable Web interaction. This kind of policy is impossible to express in the object-capability model because the property does not depend on object references, but rather on computation itself. Extensible access control specifications is crucial considering that different usage scenarios imply different requirements. This is acknowledged by other proposals like BrowserShield and Caja. Object-level granularity is a unique feature of ZAC. Allowing the coexistence of different policies for different scripts within a Web page is fundamental. Going beyond the script level down to the object level also enables a secure interaction among scripts: objects from one script can use objects from other scripts, possibly with different policies; the correct policy will be unequivocally enforced. This is not the case with capabilities, where an untrusted object that obtains a reference to a sensitive resource can use it without limitations. The principle of ZAC is that foreign code can use every feature of JavaScript, including eval, and also can access every reference to any object in the system. However, the access control policy assigned to the foreign code when loaded forbids dangerous actions before they happen at runtime. In other words, ZAC follows a blacklisting approach, which, despite being considered less safe than a whitelisting approach, is actually used in real systems for access control. Even more, it turns out to be equivalent to the access control architectures of widely-used languages such as Java and C#.
Page | 5
Finally, ZAC also inherits the great expressive power of the underlying general-purpose library for aspect-oriented programming AspectScript , as will be shown later on in this article.
ZAC IN ACTION
ZAC is based on assigning access control policies when scripts are loaded. At runtime, ZAC enforces the policy for every action these scripts perform. A. Loading Scripts Enforcing access control policies with ZAC is very easy through the use of a simple API. For example, to load a third-party script it is only necessary to use the ZAC.load method:
FIGURE 1. ZAC.load. This method loads a third-party script subject to the default access control policy.
Loading the evil.js script using load, its execution is automatically subject to the restrictions in the policy specified as the second argument. Policies in ZAC are sets of restrictions. Figure 3 shows the restrictions in the policy returned by ZAC.newDefaultPolicy(), targeted to restrict the access to common sensitive resources. For instance, the ZAC.R_ALERT restriction forbids the use of alert dialogs. These dialogs are normally used to provide valuable information to the user, but they can also be used to turn a page (or even the whole browser) unusable by endlessly showing an alert dialog. Another example is ZAC.R_LOCATION, that forbids redirections of the page. This restriction prevents malicious scripts from sending the browser to potentially dangerous sites. B. Policy Enforcement When loaded using ZAC.load, a script is unable to bypass the specified access control policy, directly or indirectly. This means that the script itself will not be able to perform any action forbidden by the policy, and also that it will not be able to lead other (possibly trusted) code to do it on its behalf. The reason is that ZAC supports stack-based access control similar to Java and C#. The Page | 6
semantics of stack-based access control says that each time a sensitive action is about to be performed, the current stack of evaluation is inspected to determine whether all the participating entities (in the case of JavaScript, objects and functions) are allowed to perform the action. If one entity is not allowed, then the action is aborted, typically by throwing an exception. In order to diminish the performance overhead, ZAC does not inspect the stack every time a sensitive action occurs, but maintains the security state of the application at each necessary point (see Figure 4 for more details). Figure 2 shows three different attempts to call the alert function, all ending with an exception raised by the access control policy. The first one is a direct call, the second one uses delegation: the untrusted code. invokes the (trusted) info function, which in turn tries to call alert.
alert(..) evil.js
R_ALER
alert(..)
T
info(..) evil.js
R_ALER
R_ALER
T
R_ALER
evil.js
R_ALER
Execution stack
Execution stack
Execution stack
FIGURE 2. Policy enforcement in ZAC. (a) Direct invocation. (b) Indirect invocation using delegation. (c) Indirect invocation using eval. (d) Scheduled invocation. All these attempts will fail with an exception raised by the access control policy.
All these attempts end with an exception because the stack contains an object whose policy does not permits calls to alert. The third attempt is interesting, because it uses eval. ZAC ensures that restrictions of the code that calls eval are inherited by the eval-ed code: therefore, this attempt also fails. The last attempt is more intricate: although ZACs policies are specified at the level of scripts (loading them using load), they are enforced at the level of individual objects. The consequence is that if an object is created during the execution of a script subject to a certain policy, that objects execution will always be subject to that policy: wherever the object goes, the policy follows it. Therefore, in the example, the policy is present in the stack when the anonymous function calls info. This is the reason why the third attempt also ends with an exception. It is important to highlight that this kind of access control is impossible to achieve with any other proposal (Figure 1). For example, in capability-based access control, if the anonymous function manages to get a reference to the Page | 7
info function, there are no means to prevent it from calling info to display an alert dialog. Once an object obtains a reference, it can use that reference at will, no matter which was the policy originally assigned to it.
Constant (ZAC.) R_ALERT R_LOCATION R_C_STYLES R_ INNER_HTML R_COOKIES R_GLOBAL R_EVAL R_ZAC_POLICIES prevents alert calls. prevents redirection of the browser. prevents calls to computedStyles(). sanitizes strings property. assigned to the innerHTML Description
prevents access to cookies. prevents access to properties of the global object. prevents arbitrary deserialization). use of eval (only JSON
Fig. 3. Restrictions in ZACs default access control policy. Constants are accessed as properties of the ZAC global property.
C. Defining Custom Policies As typical sets, policies in ZAC can be modified by adding or removing restrictions (using the add and remove methods respectively). There are several scenarios where this can be useful. For instance, it seems natural to specify different policies for different foreign scripts, depending on the level of confidence the host page has in each of them. Another scenario is when a policy must be constructed programmatically (e.g. according to the preferences of the user). The API of ZAC permit to modify policies even after using them to load a script. These modifications will affect all the scripts already loaded using the policy. In addition to default policies, empty policies can be created using ZAC.newPolicy(). In the following piece of code, two policies are configured to enforce different restrictions in two different scripts:
Page | 8
var softPolicy = ZAC. newPolicy ( ) ; / / fresh policy (norestrictions) / / restrict only page redirections and evaluation of code in notSoEvil . j s softPolicy .add(ZAC.R_LOCATION, ZAC.R_EVAL) ; ZAC. load ( http : / / evilsite.net/notSoEvil.js, softPolicy ) ; / / get a default policy and remove only the R_ALERT restriction for evil.js var hardPolicy = ZAC. newDefaultPolicy ( ) ; hardPolicy . remove(ZAC.R_ALERT) ; ZAC. load ( http : / / evilsite.net/evi l.js, hardPolicy ) ;
EXTENDING ZAC
Each restriction in a policy is targeted to restrict the access to common sensitive resources. ZACs policies can be extended by adding new restrictions targeted to protect other resources. A. Defining Restrictions A restriction is a JavaScript object with two properties, both of which are functions. A rule property is in charge of identifying the access to the resource, and an action property is in charge of specifying the action to take when the resource access occurs. For example, the ZAC.R ALERT restriction is implemented as follows:
ZAC.R_ALERT = { rule : function(event ){ return event . isCall ( ) && event.fun === alert ; }, action : function(event ){ throw Cannot callalert ; } };
Properties fun, args target, fun, args target, fun, args, context, reflective target, fun, args target, name target, name, value
Common properties
Common methods
parent
Page | 9
fun: the function being used as a constructor (New and Init), or being called/executed (Call and Exec). args: the arguments of the event. target: the target of the event. context: the object performing the call. reflective: whether the call was performed using call or apply. parent: the parent event (like a stack of execution). proceed: executes the event. clone: clones the event (useful to store a reference). is<eventName>(): boolean-returning utility methods to identify the kind of event. The function bound to the rule property identifies calls to the alert function by returning true when such calls occur. It uses the event parameter, which is a representation of the event occurring in the script. Figure 6 shows the complete list of event types supported by ZAC, and the corresponding properties (fields and methods) in each case. The function bound to the action property simply throws an exception because invoking alert is completely forbidden. An alternative to simply throwing an exception is to provide, possibly under certain circumstances, an alternate safe behavior. For example, the eval function of JavaScript is widely considered dangerous because it permits to execute arbitrary, potentially malicious, code. IHowever, eval has a very useful application: the deserialization of a JSON [11] object from a string. Because JSON objects serialization format do not permit functions, no arbitrary code can be executed when evaluating a serialized object. In other words, using eval for deserializing JSON objects is safe. The code below shows the ZAC.R EVAL restriction that only forbids the evaluation of code that is not in JSON format:
ZAC.R_EVAL = { rule : function(event ){ return event . isCall( ) && event.fun === eval ; }, action : function(event ){ try{ return JSON. parse(event.args[ 0 ] ) ;} catch (e){ throw Eval can only be used to deserialize JSON object s . ;} } };
Just like in the ZAC.R ALERT restriction, the rule property identifies calls to a certain function, in this case, eval. The action property, instead of immediately throwing an exception, first tries to evaluate the first argument of eval (event.args[0]) as a JSON string. If it effectively is a JSON string, the resulting object is returned. Otherwise, an exception is thrown by JSON.parse; the restriction action then throws an exception itself.
Page | 10
B. Adding New Restrictions ZAC comes with a set of predefined restrictions (recall Figure 3), which corresponds to common cases. It is possible to define whole new kinds of restrictions as Ill. Let us define a new restriction that limits the number of windows a script can open:
function nWindowsRestriction(n){ return { nWindows: 0, rule : function(event ){ return event . isCal l ( ) && event.fun === document.open; }, action : function(event ){ i f (++this .nWindows > n){ throw Cannot open more than + n + windows . ;} return event .proceed ( ) ;} }; } / / add the restriction to a fresh policy var policy = ZAC.newPolicy( ).add(nWindowsRestriction(3) ) ;
Page | 11
ADVANCED FEATURES
Taking Advantage of AspectScript: AspectScript is an extension to JavaScript adding support for aspect-oriented programming. In Aspect-Oriented Programming, execution of a program is represented as a series of join points (a function call, a property access, an object creation, etc. A pointcut identifies a set of join points, and a piece of advice is the action to be taken at a join point matched by a pointcut. In AspectScript, an aspect is a pointcut-advice pair, where both pointcuts and advices are plain JavaScript functions that receive a join point as parameter. AspectScripts aspects corresponds exactly to ZACs restrictions, where the rule property is the pointcut, and the action property is the piece of advice. The policy enforcement (stack-based access control and privileged actions) is implemented based on dynamic deployment of aspects and expressive scoping . ZAC depends only on AspectScript to be secure: if AspectScript generates all the events associated to the execution of all untrusted objects, these objects will not be able to do anything without ZAC being aware of it. This is the reason why ZAC policies cannot be circumvented. The fact that ZAC is implemented on top of AspectScript brings many benefits, of which we highlight two: the ample variety pointcuts included in AspectScript, and the ability to reason about the program execution. AspectScript includes several predefined pointcuts that can be composed to identify more intricate actions. For example, the following pointcut identifies the calls to alert that occur inside the body of any method of obj: var PCs = AspectScript . Pointcuts ; var pc = PCs. call ( alert ) .and(PCs.within ( obj ) ) ;
Page | 12
Pointcuts in AspectScript can also match sequences of events, optionally restricted by temporal conditions. This can be useful in access control to, for instance, forbid the invocations to alert that occur too frequently, say more than one per second. The ability of ZAC to reason about the execution of a program derives from the fact that AspectScript generates join points for every action in the scripts, evaluating pointcuts for each one of them. In a capability-based model, for instance, reasoning about the history of program execution is impossible. This is because the model considers accessing a reference and executing some methods as the only way to threaten a system. However, there are other interesting security properties that are related to the actual computation of programs. An example of a security property based on actual computationwhich is actually checked by most browsersis to ensure that a third-party script does not degrade the interactive experience of the user: if a script takes too long to execute, the browser suspends its execution and asks the user whether to simply abort the script. While such a restriction is beyond the realm of capabilities, it is straightforward to define with ZAC:
function nInstructionsRestriction (n){ return { nInstructions : 0, rule : function(event ){ return ++nInstructions > n;}, action : function(event ){ if( confirm( This script is running for too long . Abort it? ){ throw Cannot execute more than + n + instructions ;} nInstructions = 0; return event .proceed ( ) ;} }; }
Page | 13
CONCLUSION
The ubiquity of the JavaScript language and the myriad of ways in which it is being used turn access control into a crucial element for a safe web experience. ZAC, a lightweight practical library for access control in JavaScript comprising very interesting features which permit to express security properties not enforceable with other approaches, such as per-object restrictions and bounded-time execution. ZACs implementation is based on aspect orientation, which, apart from constituting a solid ground currently under active development, brings many practical benefits in terms of expressiveness.
Page | 14
REFERENCES
[1]. ZAC: Access Control in JavaScript- Rodolfo Toledo, Eric Tanter PLEIAD Laboratory Computer Science Department (DCC) University of Chile Chile [2]. Secure and Modular Access Control with Aspects- Rodolfo Toledo, Eric Tanter PLEIAD Laboratory Computer Science Department (DCC) University of Chile Chile [3]. Modular and Flexible Causality Control on the Web- Paul Leger, Eric Tanter, Remi Douence PLEIAD Lab, Computer Science Department, University of Chile ASCOLA Project, INRIA [4]. AspectScript: Expressive Aspects for the Web- Rodolfo Toledo, Paul Leger, Eric Tanter PLEIAD Laboratory Computer Science Department (DCC) University of Chile Chile [5]. An Open Trace-Based Mechanism- Paul Leger, Eric Tanter PLEIAD Laboratory Computer Science Department (DCC) University of Chile Chile [6]. http://msdn.microsoft.com/en-us/library/aa288717(v=VS.71).aspx [7]. http://www.ibm.com/developerworks/rational/library/content/RationalEdge/feb04/2782.pdf
Page | 15