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?
- 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.
Easy XSS is easy, DOM XSS is not easy.
This is how I find simple reflected XSS:
- 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”).
- I send the request to the page and search the response for this needle.
- If I don’t find it, I return to step 1.
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.
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>
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.
- 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):
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.
- 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.