Is Qooxdoo protected against XSS

361 views Asked by At

I'm looking for informations about security on Qooxdoo. I want to check my app vs OWASP top 10 A point to review is the XSS OWASP A3 XSS

How can I be sure that Qooxdoo is secure against XSS attacks ? Does Qooxdoo use some sanitizer tools ?

SOLVED

A short answer from all the discussions. Yes Qooxdoo is XSS safe. By default, no javascript value in any field will be executed.

But, if you use rich=true, you have to check input/output

1

There are 1 answers

8
Tobi Oetiker On BEST ANSWER

A common XSS attack vector are situations where an attacker somehow inputs JS code into a web application, such that this code then shows up in the DOM of a webpage and gets thus activated.

To protect against this kind of XSS, you must make sure that the backend server does not send user generated (un-cleaned) html towards the browser ... (this has nothing to do with qooxdoo).

That said, the regular qooxdoo widgets do not in general display data as html so you are reasonably safe even without a clever server. The exception is the qx.ui.basic.Label widget and its descendants. The Label widget has the ability to display HTML directly if you set the rich property. The rich property is set to false by default, but if you enable it, you have to make sure you don't display 'dangerous' html content.

Only very few (non essential) qooxdoo widgets allow you to insert HTML code into the DOM. In these instance you have to take care to sanitize the data. The widgets in question are:

qx.ui.embed.Html
qx.ui.table.cellrenderer.Html
qx.ui.progressive.renderer.table.cell.Html
qx.ui.virtual.cell.Html
qx.ui.virtual.layer.HtmlCell
qx.ui.virtual.layer.HtmlCellSpan

If you do use qx.html.* and qx.bom.*and qx.dom.* objects to work with the DOM directly, you are beyond the reach of qooxoo and have to take care to act accordingly.

Another important attack vector are authentication cookies. Most of the attacks work by getting the browser to send a request together with the cookie to its server without the user being aware it.

Qooxdoo itself does not require you to use cookies at all. Since qooxdoo applications by design run in a single browser window, you can work without ever using cookies. An easy way of implementing something like this is to have a 'server access singleton' which takes care of all the communication with the backend and supplies the access token in a special header added to every request.

The code below could serve as a guide ... for the cookie problem.

qx.Class.define('myapp.Server', {
    extend : qx.io.remote.Rpc,
    type : "singleton",

    construct : function() {
        this.base(arguments);
        this.set({
            timeout     : 60000,
            url         : 'QX-JSON-RPC/',
            serviceName : 'default'
        });
    },

    properties: {
        sessionCookie: {
            init: null,
            nullable: true
        }
    },

    members : {
        /**
         * override the request creation, to add our 'cookie' header
         */
        createRequest: function() {
            var req = this.base(arguments);
            var cookie = this.getSessionCookie();
            if (cookie){
                req.setRequestHeader('X-Session-Cookie',this.getSessionCookie());
            }
            return req;
        }
    }
});

and if you provide a login popup window in myapp.uiLogin you could replace the standard callAsync by adding the following to popup a login window if the backend is unhappy with your request.

 /**
 * A asyncCall handler which tries to
 * login in the case of a permission exception.
 *
 * @param handler {Function} the callback function.
 * @param methodName {String} the name of the method to call.
 * @return {var} the method call reference.
 */
callAsync : function(handler, methodName) {
    var origArguments = arguments;
    var origThis = this;
    var origHandler = handler;
    var that = this;
    var superHandler = function(ret, exc, id) {
        if (exc && exc.code == 6) {
            var login = myapp.uiLogin.getInstance();

            login.addListenerOnce('login', function(e) {
                var ret = e.getData();
                that.setSessionCookie(ret.sessionCookie);
                origArguments.callee.base.apply(origThis, origArguments);
            });

            login.open();
            return;
        }

        origHandler(ret, exc, id);
    };

    if (methodName != 'login') {
        arguments[0] = superHandler;
    }

    arguments.callee.base.apply(this, arguments);
},

take a look at the CallBackery application to see how this works in a real application.