Making Easy DOM XSS Actually Easy With Eval Villain

This blog post is an introduction to Eval Villain, which is a web extension for Firefox designed to improve the detection of DOM XSS.

My Discovery of DOM XSS.

I am ashamed to say, the first time I found DOM XSS it was on accident. I saw the “#” in the URL and thought, “That’s a strange URL parameter, I will put XSS there”. Thankfully, the popup appeared, forcing me to wrestle with the following questions:

  • Why is Burp not sending the payload after the hash?
  • Wait, how is this even working then?
  • Ah! I understand, it’s in the DOM! What’s a DOM again?
  • Why is this JavaScript file 5MB?
  • How on earth am I am going to find the injection point in all this junk?
  • Can I just make the client find the vulnerability?

DOM XSS - A quick primer.

DOM XSS seems like reflected XSS. A pretty comprehensive understanding can be gained from reading the OWASP entry.

To be brief, consider DOM XSS in contrast to reflected XSS. Reflected XSS occurs when the remote server inserts unfiltered user input into the HTML document before returning it to the browser. DOM XSS accomplishes the same result, except it is the JavaScript on the client's computer, that puts the user input into the HTML, after the browser has received the response. This means that the HTML response received from the web server does not contain the injection.

Easy XSS is easy, DOM XSS is not easy.

This is how I find simple reflected XSS:

  1. Using a proxy, I replace any parameter value with a “needle” - an arbitrary string that would not otherwise appear in the page. (I use “asdf”).
  2. I send the request to the page and search the response for this needle.
  3. If I don’t find it, I return to step 1.
  4. Otherwise, if I do find it, I look at the surrounding HTML to see if I can trick the browser into parsing the needle as JavaScript.

Forget trudging through server side code, enumerating code paths, etc. Instead, fuzz it, check what goes in and what comes out. Using a web proxy like Burp makes this very easy and fast. We only care about one request, so we only need to send one. Notice, however, that the above method will never find DOM XSS.

We can try to find DOM XSS by applying a similar approach as the one above. Finding the relevant inputs for DOM XSS is not too hard. We just have to remember to use the browser and pay attention to things like `window.name`. The real difficulty is following the output. Searching ‘View Source’ or an HTTP response in a web proxy is equally useless. To find DOM XSS, we must search the “output” only after the DOM has been manipulated by JavaScript.

JavaScript is where things get hard. On a recent test, just one of the JavaScript files hosted by a website amounted to 95,000 lines of code (after beautifying). It took Firefox more than 5 minutes to beautify the code. The moment I refreshed the page, the results were gone... Searching the JavaScript source for the use of `eval` and finding 5 results is exciting until you see it rewritten everywhere: `k = eval;... d9z=eval;... Znr = eval;`. Now you have to search for each of those functions, and only within the scope in which they are defined.

Consider the following JavaScript:

a.innerHTML = ‘loading ‘ + decodeURI(location.hash) + ‘ please wait’; 
a.innerHTML = load();

This is a trivial example of DOM XSS. It is also easy to miss because there is a race condition. If the `load` function completes instantly, you will never see the “loading” string hit the DOM. Reflected XSS means you send one request and get one response. The server response never changes after you receive it, unlike DOM XSS. With DOM XSS by the time you get your dev tools open, the users injected string may have already been removed. DOM XSS is like giving a friend edit permissions to a Google Doc. As you go to edit one statement into a joke, all of it vanishes and is replaced by something stupid better (edited by Collin).

Introducing Eval Villain, a web extension for Firefox.

Eval Villian sends out its henchmen into each web page in the dead of night - before pages finish loading, while even the inline scripts are sleeping. The henchmen hide themselves inside of whatever functions you want and then wait. When the henchmen observe any interesting characters going into the function, they will notify you via the console.

The functionality of the web page is not changed. Instead, the input to any hooked function and a stack trace are logged to the console. Additionally, there are searching and filtering features to improve usability and decrease console spam. Here is an example:

Source of ev.html:

<!DOCTYPE html>
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
</head>
<div id="me"></div>
</br>
</br>
<script>
	document.getElementById("me").innerHTML = "loading.. " + document.location;
	document.getElementById("me").innerHTML = "";
	eval('a = "needle test-> asdf";');
</script>
</html>

There are a couple things I want to point out here. First, if you look at the above HTML you will see there is practically nothing there. The JavaScript does not have to wait on any external resources, it should run very quickly. Second, the page looks blank in the screen capture. Text is first added to the DOM (the loading message), but it it is then re-written to nothing. Despite the speed and simplicity of this page, Eval Villain still won the race, hooked `innerHTML`’s setter and displayed the important function call in the console.

This picture also demonstrates some other features of Eval Villain. The first result for `innerHTML` is considered interesting because the “asdf” needle and the `location.hash` were found in the function's input. Since it is “interesting”, a more vibrant formatting is used. The resulting console group is automatically expanded because the “Auto Open” setting of the plugin has been enabled (as seen in the screenshot). The uninteresting `innerHTML = “”;` was not automatically opened. Not shown in the screenshot is how I filtered out the irrelevant `eval` results.

Some Other Features.

Searching Input:

  • Quickly find interesting results by searching function input for strings or regular expressions.
  • Filter out uninteresting results based on input or URL patterns.
  • Reconfigure which functions are hooked.
  • Format console output with custom CSS, optionally annoying CSS. (Below you will see an example of annoying CSS):

Free:

This software is free and open source. It does not use any external libraries. There are no advertisements or tracking of any kind. The plugin does not access your history, remember where you have been or what you did. Currently, (Version 1.2) it does not send a single request. This may change, but only so that you will be notified of updates.

Thanks.

  • Ian at Hurricane Labs for hooking me up with a sweet icon.
  • Collin from Hurricane for testing the code and giving valuable feedback.
  • Hurricane Labs for providing company time and resources to get Eval Villain published.



Close off Canvas Menu