Browse Source

HUE-7536 [frontend] Avoid XSS in the table row display modal, HueDatatable and TableExtender2

Enrico Berti 8 năm trước cách đây
mục cha
commit
6da4969

+ 3 - 3
apps/metastore/src/metastore/static/metastore/js/metastore.model.js

@@ -435,9 +435,9 @@ var MetastoreTable = (function () {
     self.loadingQueries = ko.observable(true);
 
     //TODO: Fetch table comment async and don't set it from python
-    self.comment = ko.observable(options.comment ? options.comment.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '') : null);
+    self.comment = ko.observable(hueUtils.deXSS(options.comment));
     self.commentWithoutNewLines = ko.pureComputed(function(){
-      return self.comment() ? self.comment().replace(/<br\s*[\/]?>/gi, ' ').replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '') : '';
+      return self.comment() ? hueUtils.deXSS(self.comment().replace(/<br\s*[\/]?>/gi, ' ')) : '';
     });
 
     self.comment.subscribe(function (newValue) {
@@ -713,7 +713,7 @@ var MetastoreColumn = (function () {
     var self = this;
     self.table = options.table;
     if (options.extendedColumn && options.extendedColumn.comment) {
-      options.extendedColumn.comment = options.extendedColumn.comment.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
+      options.extendedColumn.comment = hueUtils.deXSS(options.extendedColumn.comment);
     }
     ko.mapping.fromJS(options.extendedColumn, {}, self);
 

+ 7 - 0
desktop/core/src/desktop/static/desktop/js/hue.utils.js

@@ -367,6 +367,13 @@ if (!('addRule' in CSSStyleSheet.prototype)) {
     return a && b && a.toLowerCase() === b.toLowerCase();
   };
 
+  hueUtils.deXSS = function (str) {
+    if (typeof str !== 'undefined' && str !== null && typeof str === 'string') {
+      return str.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
+    }
+    return str;
+  }
+
 }(hueUtils = window.hueUtils || {}));
 
 if (!Object.keys) {

+ 4 - 4
desktop/core/src/desktop/static/desktop/js/jquery.huedatatable.js

@@ -384,7 +384,7 @@
             if ($t.data('fnDraws') === 0) {
               var html = '';
               for (var i = 0; i < data.length; i++) {
-                html += '<tr class="ht-visible-row ht-visible-row-' + i + '" style="height: 32px"><td>' + data[i][0] + '</td><td colspan="' + (aoColumns.length - 1) + '" class="stripe"></td></tr>';
+                html += '<tr class="ht-visible-row ht-visible-row-' + i + '" style="height: 32px"><td>' + hueUtils.deXSS(data[i][0]) + '</td><td colspan="' + (aoColumns.length - 1) + '" class="stripe"></td></tr>';
               }
               appendable.html(html);
               if ($t.data('plugin_jHueTableExtender')) {
@@ -398,7 +398,7 @@
               if (force) {
                 var html = '';
                 for (var i = $t.find('.ht-visible-row').length; i < data.length; i++) {
-                  html += '<tr class="ht-visible-row ht-visible-row-' + i + '"><td>' + data[i][0] + '</td><td colspan="' + (aoColumns.length - 1) + '" class="stripe"></td></tr>';
+                  html += '<tr class="ht-visible-row ht-visible-row-' + i + '"><td>' + hueUtils.deXSS(data[i][0]) + '</td><td colspan="' + (aoColumns.length - 1) + '" class="stripe"></td></tr>';
                 }
                 appendable.html(appendable.html() + html);
               }
@@ -410,7 +410,7 @@
                 var row = data[i];
                 if (row) {
                   for (var j = 0; j < endCol; j++) {
-                    html += '<td ' + (!aoColumns[j].bVisible ? 'style="display: none"' : '') + '>' + row[j] + '</td>';
+                    html += '<td ' + (!aoColumns[j].bVisible ? 'style="display: none"' : '') + '>' + hueUtils.deXSS(row[j]) + '</td>';
                   }
 
                   if (endCol < aoColumns.length) {
@@ -419,7 +419,7 @@
                 }
               }
               else {
-                html = '<td>' + data[i][0] + '</td><td colspan="' + (aoColumns.length - 1) + '" class="stripe"></td>';
+                html = '<td>' + hueUtils.deXSS(data[i][0]) + '</td><td colspan="' + (aoColumns.length - 1) + '" class="stripe"></td>';
               }
               appendable.children().eq(i).html(html);
             }

+ 1 - 1
desktop/core/src/desktop/static/desktop/js/jquery.tableextender2.js

@@ -486,7 +486,7 @@
       var tHtml = '';
       var aoColumns = self.$element.data('aoColumns');
       self.$element.data('data')[rowNo - 1].forEach(function(col, idx){
-        tHtml += '<td ' + (aoColumns && !aoColumns[idx].bVisible ? 'style="display: none"' : '') + '>' + col + '</td>';
+        tHtml += '<td ' + (aoColumns && !aoColumns[idx].bVisible ? 'style="display: none"' : '') + '>' + hueUtils.deXSS(col) + '</td>';
       });
       $clone.html(tHtml);
       $clone.appendTo(self.headerRowContainer.find('tbody'));

+ 4 - 0
desktop/core/src/desktop/static/desktop/spec/hueUtilsSpec.js

@@ -60,5 +60,9 @@
       hueUtils.changeURL('/jasmine');
     });
 
+    it("should remove JS code from a string", function() {
+      expect(hueUtils.deXSS('hello <script>alert(123)</script>world')).toEqual('hello world');
+    });
+
   });
 })();

+ 1 - 1
desktop/core/src/desktop/templates/common_header_footer_components.mako

@@ -544,7 +544,7 @@ from metadata.conf import has_optimizer, OPTIMIZER
             value = $el.data('data')[data.idx][colIdx];
           }
           var link = typeof value == 'string' && value.match(/^https?:\/\//i) ? '<a href="' + escapeOutput(value) + '" target="_blank">' + value + ' <i class="fa fa-external-link"></i></a>' : value;
-          html += '<tr><th width="10%">' + $(col).text() + '</th><td>' + link + '</td></tr>';
+          html += '<tr><th width="10%">' + hueUtils.deXSS($(col).text()) + '</th><td>' + hueUtils.deXSS(link) + '</td></tr>';
         }
       });
       $t.html(html);