DexterJS: Auto-Patching DOM-based XSS At Scale

Home Publications Demo Resources FAQ
Auto-Patch Overview


Smiley face
An overview on how our auto-patching mechanism works is illustrated in the figure above. The goal of our auto-patching mechanism is to render string such that the DOM-tree generated in the browser is free from XSS payload and contains ONLY benign markup, obtained from a pre-loaded template. A template contains a set of valid HTML structured allowed to be rendered on a web page and is inferred during a pre-deployment phase. To ensure that only valid markups are rendered, we employ a hot-patching technique by adding a hook at the DCE points where untrusted strings may be rendered into a code (e.g., document.write, innerHTML) through a lightweight instrumentation. The hook points to a function where such strings will be rendered securely -- we call it patch() function. A complete procedure of our patching techniques can be found in our paper.

Why is it secure?
A string that is going to be rendered at the DCE points can be divided into two parts: 1) parts that come from a benign source, that is, trusted data originating from constants , and 2) parts which come from attacker-controlled inputs (such as URL address) and considered as untrusted. Figure below illustrates the two parts of a string.

Smiley face

Using unsafe DOM construction such as document.write() or innerHTML, the underlying browser's parser engine does not know which part of the string is safe to render as a code and therefore it blindly parses ALL the string, including the untrusted ones. The idea is to use the template as a guideline for the browser's HTML parser to build the expected DOM tree structure and renders everything else as a non code-invoking DOM node. To do that, we need to replace such unsafe DOM construction with a set of programmatic DOM constructions. Having obtained the template during the pre-deployment phase, we progressively build up the DOM tree using several DOM APIs such as document.createElement() and appendChild().

Based on the template, it is now easy to distinguish the untrusted string from the trusted one. Like mentioned above, we do not want to render the untrusted data into a code-invoking DOM node. To do that, we employ a non code-invoking DOM API such as document.createTextNode() or setAttribute(). These programmatic constructions will result on the same DOM tree structure as without using the auto-patch.

Does it run cross-browser?
Our client-side patching mechanism employs only web APIs which are implemented cross-browsers. Therefore, our techniques will run on mainstream browsers such as Chrome, Firefox, Opera, and Safari. To verify this, we have tested the auto-patch on Chrome and Firefox using real-world exploits and it runs well on both the browsers. We have yet to verify the same thing on Safari and Opera.



How is the performance overhead?
The auto-patched websites give a reasonable performance overhead. We measure the page load time for the auto-patched webpages. The overhead averaged over 10 runs is modest -- ranging from 5.2% for Google Chrome, 6.45% for Internet Explorer, and 8.07% for Mozilla Firefox. This performance overhead is due to the replacement of the functions at the patch-points with the patch function and the increased number of DOM operations as compared to the vulnerable program. Please see the "Datasets" section below to download the performance reports.

What is the distribution of the discovered tainted flows?
We found three source types and three sink types during our evaluation on Alexa's top 1000 websites. Below is the distribution.

What is the difference between unpatched and patched websites?
Our hot-patching mechanism will ensure that unsafe string that evaluates to a code AND not following the expected template to be rendered as a text. Here we show the resulting rendered DOM between an unpatched and the patched version of a web page hosted at Google's Firing Range.
Smiley face Smiley face

As can be seen from the figure, the string "<img src=/ onerror="alert('XSS attacks')">" is the malicious string injected to execute arbitrary JS code. The unpatched version (figure on left) render the string unsafely using code constructs such as document.write() and innerHTML. On the other hand, the patched website will render such string securely and therfore it is rendered as a text node (figure on right).
Gettting the Software


Our core instrumentation and auto-patching modules come in a VM so that users can easily use and replicate the system. However, we do not publicly issue our VM. Please contact Enrico via e-mail if you are interested in trying out our instrumentation and auto-patching systems. In the e-mail, please also state your name, affiliation, and the reason why you need the VM. Note that we will give access to the VM only for academic purposes.

Open-source modules: Our DexterJS core modules are not open source. However, we release our multithreaded MITM proxy for JavaScript. The proxy, built on top of falafel and cheerio, captures JS on-the-fly and lets you modify it using a callback. For more info please visit our Github page.
Datasets (updated June 30, 2015)


Disclaimer: Use the DexterJS at your own risk.

DexterJS is provided "as is" without warranty or support of any kind, whether expressed or implied. The creators of DexterJS make no guarantee and hold no responsibility for any damage, injury, loss of property, loss of data, loss of any and all resources, or any negative influence what-so-ever that may result from any and all use of DexterJS and associated materials. This includes but is not limited to the downloadable software and documentation available from this website. Negative consequences of your usage of DexterJS and any associated materials are solely your problem and your responsibility. We strongly encourage the use of DexterJS in a responsible manner.

Exploit Reports:

We release a report consisting of 820 DOM-based XSS exploits URLs accross 89 different domains. The exploits URLs can be found here. Note that we have reported such vulnerabilities to the website owner and most of the domains reported are no longer vulnerable.