fooplugins / FooTable

jQuery plugin to make HTML tables responsive
https://fooplugins.com/plugins/footable-jquery/
Other
2.13k stars 637 forks source link

Cross Site Scripting vulnerability #741

Open bradbm opened 7 years ago

bradbm commented 7 years ago

Example JS fiddle: https://jsfiddle.net/16L0usfo/1/

When loading data over AJAX (or otherwise parsing it from some JSON) Footables is vulnerable to XSS. The fix from issue #581 doesn't seem to resolve this as the fiddle demonstrates. This would be fine in HTML type columns, but text type columns should always escape HTML content.

jahrralf commented 6 years ago

Any update here? This is important. I cannot use a library which I purchased if it has know security issues. Thanks! I have just updated the jsfiddle to 3.1.6: https://jsfiddle.net/beL2yg0x/1/

steveush commented 6 years ago

Hi @bradbm & @jahrralf ,

I've updated both fiddles (https://jsfiddle.net/beL2yg0x/3/ & https://jsfiddle.net/16L0usfo/8/) with the below snippet which I believe resolves the issue:

(function($, F){
    // Add a new escape method to the Text column that is used in the formatted output
    F.Column.prototype.escape = function(value){
        return value
                .replace(/&/g, '&')
                .replace(/"/g, '"')
                .replace(/'/g, ''')
                .replace(/</g, '&lt;')
                .replace(/>/g, '&gt;')
                .replace(/\//g, '&#x2F;');
    };

    // Override the default formatter to escape all supplied values
    F.Column.extend("formatter", function(value, options, rowData){
        return value == null ? '' : this.escape(value);
    });

    // Add a new sanitize method to the HTML column that is used during the parsing of the supplied value
    F.HTMLColumn.prototype.sanitize = function(value){
        return $.parseHTML('<div>' + value + '</div>', null, false);
    };

    // Override the default parser and use the sanitize method on any supplied HTML strings
    F.HTMLColumn.extend("parser", function(valueOrElement){
        if (F.is.string(valueOrElement)) valueOrElement = $(this.sanitize(valueOrElement));
        if (F.is.element(valueOrElement)) valueOrElement = $(valueOrElement);
        if (F.is.jq(valueOrElement)){
            var tagName = valueOrElement.prop('tagName').toLowerCase();
            if (tagName == 'td' || tagName == 'th'){
                var data = valueOrElement.data('value');
                return F.is.string(data) ? $(this.sanitize(data)) : valueOrElement.contents();
            }
            return valueOrElement;
        }
        return null;
    });

    // Override the inherited Text formatter as we do not need to escape the value as (1) it was sanitized when it parsed
    // and (2) the value is a jQuery object which would cause an error to be thrown by the escape method.
    F.HTMLColumn.extend("formatter", function(value, options, rowData){
        return value == null ? '' : value;
    });
})(
        jQuery,
        FooTable
);

To use this snippet you just need to include it into your page after the FooTable files but before you initialize any tables.

@jahrralf please note this should only be an issue if you are loading data from an unreliable source. If you are encountering this issue using local data captured by yourself then apart from adding the above snippet you should also check where that data is being input into your system and sanitize it prior to it being saved.

Let me know if the snippet resolves this issue for you.

Thanks