
Scriptlock 2.1
The code execution prevention system for JavaScript
Comparison of code execution prevention mechanisms in Javascript
William Coppock 21/09/2012
Revised 30/09/2014
Abstract
Two emerging technologies promise to provide a solution to cross site scripting (XSS). Content Security Policy (CSP) is a class of Browser Enforced Policy that removes the ability to ‘inline’ JavaScript code in a protected HTML document, and maintains a whitelist of permissible sources for any externally-loaded scripts. ScriptLock is a token based Code Execution Prevention System that password protects vulnerable parts of JavaScript and the DOM that can be exploited to modify or transmit data outside of a webpage, meaning that only code sourced from a trusted store can perform these tasks.
In sort, CSP disables JavaScript, where as ScriptLock disarms JavaScript.
Both systems mitigate the effects of XSS, but work in completely different ways giving them distinct strengths and weaknesses. This paper explores these strengths and weaknesses in order to provide webmasters with a better insight as to which mechanism to choose, or whether they should implement both mechanisms.
Introduction
Cross site scripting (XSS) is summed up by an attacker “injecting” a script into a website in a manner that results in the execution of the script [10].
There are three typical forms of XSS attack, summarised as follows:
Reflected (or non-persistent) XSS, where by a website inadvertently allows mark-up or obfuscated mark-up submitted in a URL request string to be incorporated into the webpage. An attacker places a link in a second website or an email and coaxes a user into clicking the link, which contains the script. The requested webpage “reflects” the injected script resulting in the execution of the script and the possible disclosure of the details of the user who clicked on the link;
Persistent XSS, where by a website inadvertently allows mark-up to be saved to the server or where by a hacker is able to install mark-up or script on one or more pages through SQL-Injection or direct hacking of a server. The affected website subsequently incorporates the mark-up or script each time the affected webpages are loaded. The code contained in the mark-up executes for each user that accesses the affected pages;
Self-XSS, where by a user is coaxed through careful social engineering to inject script directly into the browser address-bar or command prompt in the debugger.
Content Security Policy Described
Content Security Policy (CSP) is a class of Browser-Enforced Policy that aims to thwart the XSS attacks by preventing injected script from executing [1].
CSP is configured by means of the Content-Security-Policy HTTP header. When the CSP header is detected by a browser, it examines the policy and applies the rules before loading and rendering the rest of the document [1].
In order to distinguish between legitimate script and injected script, CSP would normally be configured to prevent inline script from executing and to allow external script to be executed only if it is sourced from a white-list of URL’s, which will as a minimum include the same domain as the page. Consequently all script used by a website, including that used by event handlers, must be placed in external script files [8].
The principal is that script embedded in the webpage is completely untrusted; such script has traditionally been the primary vector used in reflected and persistent XSS. Conversely external script on the white list of URL’s is, in principal, completely trusted as there is usually no easy pathway for Reflected or Persistent XSS to reach these scripts.
Implementing CSP requires a considerable amount of web page restructuring. Inline JavaScript code has to be moved to separate files and loaded into the main page via script tags. JavaScript functions linked to HTML events must now be added using the addEventListener method [9]. Any dynamically generated mark-up that previously incorporated script into the document will need adapting. Third party libraries, such as JQuery, may also need to be adapted [5].
One problem area identified when the micro blogging site Twitter implement CSP is that many browser add-ons exist that inject script directly into web pages. In the research for this paper it was found that the Symantec add-on for Google Chrome, does precisely this. They also found that many ISP’s cache documents and modify image and script links to point at their own caching servers, thus violating the CSP. The solution to the ISP cache problem is to force CSP protected pages to be delivered over SSL [11], though HTTPS does not prevent browser add-ons from making modifications.
From the outset, the authors of CSP make it clear that it is designed to reduce the harm of XSS, not prevent XSS or act as a first line of defence [10].
ScriptLock Described
ScriptLock is a token/password based Code Execution Prevention System, which rewrites native vulnerable native functions of JavaScript and the DOM to require the presentation of a password in their parameter list in order to function.
The system is delivered as a script loaded in the header of the web page. The positioning of the script means that it executes before any other code on the web page, thereby installing the protection before any inline or other external script is encountered.
As ScriptLock rewrites the native functions of JavaScript and the DOM, it locks the changes in place by use of the latest ECMAScript property descriptor functionality, therefore rendering the protection irreversible[12].
ScriptLock broadly classifies all script as untrusted with the exception External Script served from a Trusted Script Store. The Trusted Script Store uses place-holders in the source code where a protected function requires the presentation of the password. Scripts served from the Trusted Script Store are served with a session dependent password substituted into the place of the place-holders[14].
Implementing ScriptLock requires a certain amount webpage restructuring and modification to source code including: moving any script that utilises protected JavaScript/DOM functions to external script files placed in the Trusted Script Store; adapting all source code, including third party libraries, that use the protected JavaScript/DOM functions, to use ScriptLock compatible function calls; analysing and adapting any API’s to close loop holes that may allow circumvention of the protection[14].
Limitations of CSP Identified
1) Self XSS through the debugger.
While many browsers now block Self-XSS injection through the address bar, they still provide an easily accessible console as part of the debugging tools. CSP does not prevent the execution of JavaScript injected through the console. Therefore the threat of Self-XSS still exists under CSP.
2) Browser add-ons.
Under CSP browser add-ons are still permitted to modify web pages. (The specification [1] states that “Enforcing a CSP policy should not interfere with the operation of user-supplied scripts such as third-party user-agent add-ons and JavaScript bookmarklets.”). While they can no longer inject script into a page, as illustrated by the Twitter implementation of CSP, they can still modify the content, which is enough for malicious add-ons to transmit data outside of the website, especially where image sources are not white-listed.
3) Persistent XSS
While CSP prevents Persistent XSS from utilising script injected directly into the webpage, if a hacker is able to contaminate the trusted script store, then a persistent XSS attack may succeed. [5]
4) HTTP Response Splitting
Where input or request string values are utilised in the HTTP response header, a website can be vulnerable to the injection of carriage return (CR) values in the response header[13]. Two carriage returns are used by HTTP to signify the end of the header. So a hacker can inject CR characters into the header and prevent essential control information from being processed by the client browser. Therefore since CSP relies on HTTP headers it is vulnerable to HTTP response splitting.
5) Script source URI injection
If a website utilises dynamically generated external scripts then a Persistent or Reflected XSS attack may succeed by injecting a script tag into the HTML document. A carefully crafted URI may be formed to manipulate the behaviour of the dynamically generated script. This is a particular issue for “call-back” style scripts, where a call-back JavaScript function is passed as a parameter in the URI request for the script [7]. The function can easily be replaced with JavaScript.
Browser compatibility
CSP is only compatible with the latest versions of most browsers (as of 2013). Compatibility with older browsers restricted to just Firefox and Chrome[16].
Discussion
CSP has caused little change with respect to the first two vectors identified (Self XSS through the debugger and browser add-ons).
The fourth vector (HTTP response splitting) is an important one as it shows that CSP can literally be turned off by a hacker, though it is also easily remedied.
It may seem that the risks associated with the fifth vector are small. However, the nature of CSP forces the developer’s hand somewhat and makes this vector much more probable. This we will explore in the next sections.
Limitations of ScriptLock Identified
For ease of discussion the same limitations are listed here as for CSP, even though they may not be limitations for ScriptLock.
1) Self XSS through the debugger.
Unlike CSP, ScriptLock prevents code injected through the debugger or the browser address bar from being able to access protected JavaScript or DOM functions. It should be noted though that “alert” is not a protected function in ScriptLock and therefore injecting alert(“this page is vulnerable”) does in fact yield a false positive.
2) Browser add-ons.
Browser add-ons evaluate before the DOM of a page is loaded, which means that add-on code is executed before the ScriptLock protection is applied. However, since there is not yet a DOM in place at this time there is little that the browser add-on code can do. This is why browser add-ons have a tendency to use an event listener to invoke code after the DOM is loaded.
Any code that executes after the DOM is loaded is prevented from modifying or transmitting data by ScriptLock. So, most browser add-ons will be prevented from modifying a ScriptLock protected page.
However, there is the potential for a malicious browser add-on to be coded that uses the ECMAScript property descriptor functionality to lock down the native functions of JavaScript before the page DOM has loaded and therefore prevent ScriptLock from applying its protection.
This problem could be mitigated in the future by the ScriptLock rewriter script existing as a browser add-on or as an integral part of the browser.
3) Persistent XSS
If a hacker were able to contaminate the trusted script store, then a persistent XSS attack may succeed. Like CSP, a persistent XSS attack on the main HTML page is fully protected against.
4) HTTP Response Splitting
Even though ScriptLock does not rely on HTTP response headers, an HTTP Response Splitting attack could still inject code or mark-up that would prevent the ScriptLock protection from being applied.
5) Script source URI injection
The present incarnation of ScriptLock only supports the serving of scripts from a static script store and therefore this limitation does not apply. However, since it is in principle possible to implement the technology on dynamically generated scripts, such as those used for call-backs. It is therefore possible for a URI injection attack to succeed in such circumstance.
6) Reflected XSS
A well implemented ScriptLock protected website will be protected against the effects of Reflected XSS. That is injected JavaScript will not be able to execute functions that modify or transmit data outside of the webpage.
Since ScriptLock does not prevent inline JavaScript from reflecting and executing like CSP does, it is possible for API’s or careless source code to provide a loophole or backdoor that will allow a call to a protected function indirectly. It is therefore still possible for a reflected attack to succeed in this circumstance.
7) Compatibility
ScriptLock is compatible with Internet Explorer 8, 9, Safari 5.1, Chrome 18 and Firefox 6.0+, meaning 78% of internet users can be covered by the protection [17],[18].
Discussion
As with CSP, the fourth vector (HTTP response splitting) shows that ScriptLock can be turned off by a hacker.
The main limitation of ScriptLock identified here is the sixth (Reflected XSS). If a mistake is made in the implementation or an API is not properly adjusted then there is scope for a Reflected XSS attack to succeed.
Implications of Content Security Policy
Moving code to external files
Until the advent of CSP, developers used inline script for two common purposes:
1. To embed page or element specific script directly in event attributes. For example.
<button id="somebutton" oncick="javascript:somefunction(some parameters)"/>
2. To embed API calls with page specific parameters. For example the popular TinyMCE text editor component is usually invoked using inline script containing information about how the editor should appear.
If such embedded code is no longer permitted, then another means is required for passing information from the webpage to the event or API.
There are two ways the programmer can address this issue:
1. The API can be turned from passive to active. I.e. it is no longer a black box that is called upon, but an active mechanism that examines the loaded web page and decides what it is to do. Such an API could extract information about the page from cookies, meta tags, class or id attributes and element content.
This type of API abandons the classic OO concept of the API knowing nothing about where it is being called from, to knowing or expecting something from its calling environment.
Some existing component based APIs such as the aforementioned TinyMCE use the class attribute to identify components that they need to convert, though it stops there, they still need their configuration information to be delivered directly to an API function. The proposal here would be to embed quite complex information in the elements class attribute or some other custom attributes in a different name space meaning all the configuration information can still be embedded in the HTML document.
It should be noted that utilising non-standard attribute names or different name spaces is not backwards compatible with older browsers.
In most cases it would be most practical for the web developer rather than the third party API vendor to carry out the task of making an API active, by writing an intermediate script. For instance if a website utilised a third party calendar control, then a script could be written to seek out input buttons marked up with a "calendar" class and link up the on-click event listener to a function that invokes the existing calendar control API.
2. Classical API's can be employed by use of a connector or intermediate script that the web developer would write around his own website. This could either be static for simple sites or dynamically generated for more complex sites.
In both cases there would be a different script for each page on the site. In the static case, index.html would have an associated index.js containing all the previously embedded script. In the dynamically generated case, the script servlet would take the same request parameters as the HTML page that the script is to be associated with. This would mean far more page-specific information can be passed to the API without it being embedded in the HTML.
Take the calendar control example: On one of the input buttons above, the calendar control needs to be limited to a specific date range. To achieve this with the class attribute, as described in solution 1, would be a challenge. So instead, a page-specific script contains code that locates this specific input field by its id and sets the on-click event listener to a function that invokes the calendar control API with the tailored date range.
Both the methods for restructuring websites to support CSP open new possibilities for Persistent and Reflected XSS. Rather than targeting the inline script, hackers will now be targeting the information that is passed to the script files, either as data in the HTML page, or as a URI in the case of dynamically generated script files (Script source URI injection).
In the case of the active API, the hacker could manipulate the behaviour of a website by targeting the inline data, and given the complexities of API's, this could be enough to launch an attack.
In the case of dynamically generated intermediate script files, there remain exactly the same XSS injection issues as before the advent of CSP. That is, the parameters in the query string may end up in the script body without sufficient sanitisation (Reflected XSS). Or, the data used to build the script from the underlying database may be contaminated and result in code being injected (Persistent XSS).
Performance
Though this is not a direct security issue, it is worth noting that CSP causes a performance issue with websites. Since inline script now needs to be moved to an external script file (see solution 2, above), each web page requires two separate HTTP requests in order to load. Moreover, if the external script file is dynamically generated to match the HTML document, then it can only be presumed that the same or similar database queries will be required to produce script files. So in a worst case scenario a CSP enabled website may experience twice the requests and twice the database hits of a non-CSP website.
While not covered in this paper, it would be a worthwhile avenue of investigation to see how programmer’s efforts to mitigate these performance issues affect the development of websites and therefore the creation of vulnerabilities.
Ease of implementation
The ideal configuration of CSP can cause problems with what have become de facto or essential technologies. Take this example:
For proper protection the CSP should cascade its protection to child IFRAMES [2]. However there are a number of software platforms that exploit dynamic generation of JavaScript in IFRAMES or the main document in order to work. An example is the popular TinyMCE editor, which causes errors in Google Chrome when a "script-src 'self' 'unsafe-eval'" CSP policy is in place[3].
Such problems mean that developers are likely to settle for a non-ideal configuration, for example by adding the “unsafe-eval” policy, and therefore leave the door open to certain types of cross site scripting attacks.
Another consideration is that web developers now have to split their thinking between two sets of files, leaving much more scope for errors, also being a security consideration.
Changing the trust/untrust boundary
In a traditionally constructed webpage it was quite safe to say that external JavaScript had a very low probability of contamination and could therefore be trusted, but the embedded JavaScript had a high probability of contamination and was therefore untrusted. This is because external script files were generally static files which could only realistically be modified by direct hacking of the webserver.
With this need to transmit information to the external script files, CSP has muddied the water somewhat by increasing the probability of external script file contamination, in effect mixing the trusted and untrusted script up in one place.
Implications of ScriptLock
Moving code to external files
ScriptLock requires some code to be moved from inline script to external files. Namely calls to protected functions. Since developers can create suitable wrapper functions for safe placement in an inline-code position, there is no onus on developers to introduce complex mechanisms for passing information from the HTML to external script files, as seen with CSP. Therefore it is less likely that Script Source URI injection will be become a more frequently used XSS vector.
Session dependency
Though not an exploit, ScriptLock is dependent on a unique identifier to make sure that the password is different for every user of a website. The ideal form of identifier is a session identifier, though a client IP address is also sufficient. Therefore ScriptLock is best deployed on websites with proper session handling.
Performance
ScriptLock requires that at least the ScriptLock rewriter script be loaded externally. While the payload of this script is quite low, it is session dependent which means any server-side caching will create a different cached copy for each website user.
There is a minor client-side performance hit with the execution of the ScriptLock rewriter. Most of the protection is applied at the prototype level, which is a fixed and quite small overhead. On some platforms, namely Safari and Google Chrome there is some degree of patching done to the DOM once it is loaded, which means a document-size-dependent overhead.
Since code can be in-lined, it is not necessary to have dynamically generated external scripts, as with CSP and therefore there it is not necessity to increase the number of database hits in order to generate such external scripts files.
Unlike CSP, ScriptLock causes no problems with proxy server/ISP caching, since it is not policy driven. This means that it can be used without forcing SSL to be enabled. Therefore the performance effects of SSL are not a necessary sacrifice.
Ease of implementation
ScriptLock does require a substantial amount of modification of the source code. Most of these changes are trivial search and replaces of standard function calls with the ScriptLock compatible version[14]. However there is also a requirement for developers to carefully examine their APIs in order to close loop-holes. This also includes third party API’s. In complicated websites employing multiple third party API’s it is quite likely therefore that an exploitable loop-hole exists.
Discussion
Both CSP and ScriptLock can be added to websites that contain no script and offer immediate protection. Beyond this neither mechanism is trivial to implement and require a degree of competence on the part of the programmer.
None of the limitations explored here cast any doubt on the fact that where CSP is implemented the direct injection of script into the HTML page is a thing of the past, which does indeed close the door to many of the more common attacks. But, what has been highlighted by this investigation is that CSP has opened as many doors for XSS as it has closed and that it has muddied the waters in what can and cannot be trusted in a website.
Under CSP the biggest door opened is for script source URI injection. By forcing the developer’s hand CSP has the potential to turn script source URI injection from what is presently a rarely used vector in to the most commonly used vector.
This investigation has shown that, unlike CSP, ScriptLock manages to apply its protection without changing the risk landscape, i.e. without promoting script source URI injection. It has also shown that ScriptLock is able to address more risk areas than CSP, such as browser add-ons and that it is unaffected by ISP caching.
However, the present version of ScriptLock is significantly more complex to implement than CSP when it comes to third party libraries and, since inline code is still permitted, it is possible for a programmer to inadvertently expose protected JavaScript functions and thus render the protection ineffective.
The difference between CSP and ScriptLock
The difference between CSP and ScriptLock can be summed up as simply as this: CSP disables JavaScript. ScriptLock disarms JavaScript
In practical terms this difference means that ScriptLock has one area of use where CSP is inneffective. Protecting pages with user-submitted Active Content[19], such as the Active Selling pages on ebay[20]. In short, this is the ability of end users of a website to add rich content to their pages on that website.
Websites can mitigate the risk of XSS in these instance by embedding the active content in an inline frame (IFRAME) served from another domain. However, while this prevents the IFRAME from discovering information from the parent page, it does not prevent a malicious poster of active content from inserting code that tricks the user into entering their personal details, such as a user name and password.
Since ScriptLock disarms JavaScript, but leaves it enabled, Internet Service Providers, who insist on providing this ability to users, can force their users of Active Content to use an API and only that API for inserting, modifying or deleting content. There by restricting the sort of content that can be created and eliminating this risk of social engineering attacks.
Conclusion
This investigation has uncovered that both systems have a number of distinct limitations or pitfalls. So long as these limitations are understood both mechanisms should be equally effective. ScriptLock has the advantages that it can be used to protect Active Content pages; it can prevent browser add-ons from functioning, though this may be seen as a disadvantage to some; it is unaffected by ISP caching; and it is compatible with older browsers.
No reason has been identified to prevent both protection mechanisms being used at the same time. So the strengths of both mechanisms can be drawn on if required.
References
1. Content Security Policy 1.0. W3C Working Draft 10 July 2012
Brandon Sterne, Mozilla Corporation , Adam Barth, Google, Inc.
http://www.w3.org/TR/CSP/#key-concepts-and-terminology
2. <iframe srcdoc> and Content-Security-Policy
Adam Barth, Mon, 7 May 2012 11:18:09 -0700
http://lists.w3.org/Archives/Public/public-whatwg-archive/2012May/0100.html
3. http://loopingrecursion.com/?t=csp
or http://stackoverflow.com/questions/11360557/debugging-csp-violation-in-google-chrome
Mikko Rantalainen
5. Twitter Implements Content Security Policy on Mobile Website
Lucian Constantin , March 23rd, 2011, 16:53 GMT
6. Firefox 4 compatibility issues with SharePoint 2010 : Content Security Policy
Tom Van Gaever
http://www.tomvangaever.be/blog/index.php?entry=entry110419-142605
7. The subtle / deadly problem with CSP
lcamtuf's blog, August 26, 2011
http://lcamtuf.blogspot.co.uk/2011/08/subtle-deadly-problem-with-csp.html
8. Shutting Down XSS with Content Security Policy
Brandon Sterne, 19 June, 2009
http://blog.mozilla.org/security/2009/06/19/shutting-down-xss-with-content-security-policy
9. CSP: Thwarting cross-site scripting and click-jacking attacks
Daniel Bachfeld, 29 March, 2011
10. Cross-site scripting
Wikipedia article, 05 August, 2012
http://en.wikipedia.org/wiki/Cross-site_scripting
11. Improving Browser Security with CSP
Mark Percival, Twitter Engineering Blog, March 22, 2011
http://engineering.twitter.com/2011/03/improving-browser-security-with-csp.html
12. A method and apparatus for preventing unwanted code execution
UK Patent publication GB2496107
13. HTTP response splitting
Wikipedia article, 21 September, 2012
http://en.wikipedia.org/wiki/HTTP_response_splitting
14. ScriptLock XSS Implementation Guide
William Coppock, CliqueCloud Limited, 28 May 2012
http://www.cliquecloud.com/?screen=scriptlock&tab=implementation
15. Usage of session cookies on the web
W3Techs, 26 September 2012
http://w3techs.com/technologies/details/ce-sessioncookies/all/all
16. Can I use Content Security Policy?
caniuse.com, 25/07/2013
http://caniuse.com/contentsecuritypolicy
17. ScriptLock XSS Overview
William Coppock, CliqueCloud Limited, 28 May 2012
18. Current browser market share statistics, May 2012
http://marketshare.hitslink.com/
19. Definition - What does Active Content mean
http://www.techopedia.com/definition/4847/active-content
20. eBay under pressure as hacks continue
http://www.bbc.co.uk/news/technology-29310042