From bb3b7a7e91862742cae228c43b3091bad476dcc0 Mon Sep 17 00:00:00 2001 From: iglocska Date: Mon, 18 Apr 2022 00:49:21 +0200 Subject: [PATCH] fix: [security] stored XSS fixed in event graph - unsanitised javascript insertion of tag name in the filters - as reported by Dawid Czarnecki of Zigrin Security on behalf of the Luxembourg Army --- app/Controller/AppController.php | 2 +- app/webroot/js/action_table.js | 670 +++++++++++++++---------------- 2 files changed, 336 insertions(+), 336 deletions(-) diff --git a/app/Controller/AppController.php b/app/Controller/AppController.php index bdc05ac47..99ada8318 100755 --- a/app/Controller/AppController.php +++ b/app/Controller/AppController.php @@ -34,7 +34,7 @@ class AppController extends Controller public $helpers = array('OrgImg', 'FontAwesome', 'UserName'); - private $__queryVersion = '138'; + private $__queryVersion = '139'; public $pyMispVersion = '2.4.157'; public $phpmin = '7.2'; public $phprec = '7.4'; diff --git a/app/webroot/js/action_table.js b/app/webroot/js/action_table.js index 96a45b5bb..2bd54af97 100644 --- a/app/webroot/js/action_table.js +++ b/app/webroot/js/action_table.js @@ -1,371 +1,371 @@ class ActionTable { - constructor(options) { - this.__globalCounter = 0; - this.options = options; - this.id = options.id; - this.container = options.container; - this.classes = options.classes; - this.table_title = options.title; - this.header = options.header; - this.onAddition = options.onAddition; - this.onRemove = options.onRemove; - this.header.push("Action"); - this.row_num = this.header.length; - this.data = options.data === undefined ? [] : options.data; - this.tr_id_mapping = {}; - this.control_items = options.control_items; - this.header_action_button = options.header_action_button === undefined ? {} : options.header_action_button; - if (options.header_action_button !== undefined) { - this.header_action_button_style = this.header_action_button.style === undefined ? {} : this.header_action_button.style; - this.additionEnabled = this.header_action_button.additionEnabled === undefined ? true : this.header_action_button.additionEnabled; - this.additionButtonDisabled = this.header_action_button.disabled === undefined ? false : this.header_action_button.disabled; - } else { - this.header_action_button_style = {}; - this.additionEnabled = true; - this.additionButtonDisabled = false; - } + constructor(options) { + this.__globalCounter = 0; + this.options = options; + this.id = options.id; + this.container = options.container; + this.classes = options.classes; + this.table_title = options.title; + this.header = options.header; + this.onAddition = options.onAddition; + this.onRemove = options.onRemove; + this.header.push("Action"); + this.row_num = this.header.length; + this.data = options.data === undefined ? [] : options.data; + this.tr_id_mapping = {}; + this.control_items = options.control_items; + this.header_action_button = options.header_action_button === undefined ? {} : options.header_action_button; + if (options.header_action_button !== undefined) { + this.header_action_button_style = this.header_action_button.style === undefined ? {} : this.header_action_button.style; + this.additionEnabled = this.header_action_button.additionEnabled === undefined ? true : this.header_action_button.additionEnabled; + this.additionButtonDisabled = this.header_action_button.disabled === undefined ? false : this.header_action_button.disabled; + } else { + this.header_action_button_style = {}; + this.additionEnabled = true; + this.additionButtonDisabled = false; + } - this.row_action_button = options.row_action_button === undefined ? {} : options.row_action_button; - if (options.row_action_button !== undefined) { - this.row_action_button_style = this.row_action_button.style === undefined ? {} : this.row_action_button.style; - this.removalEnabled = this.row_action_button.removalEnabled === undefined ? true : this.row_action_button.removalEnabled; - } else { - this.row_action_button_style = {}; - this.removalEnabled = true; - } + this.row_action_button = options.row_action_button === undefined ? {} : options.row_action_button; + if (options.row_action_button !== undefined) { + this.row_action_button_style = this.row_action_button.style === undefined ? {} : this.row_action_button.style; + this.removalEnabled = this.row_action_button.removalEnabled === undefined ? true : this.row_action_button.removalEnabled; + } else { + this.row_action_button_style = {}; + this.removalEnabled = true; + } - this.selects = {}; + this.selects = {}; - this.__create_table(); - } + this.__create_table(); + } - __get_uniq_index() { - this.__globalCounter++; - return this.__globalCounter-1; - } + __get_uniq_index() { + this.__globalCounter++; + return this.__globalCounter-1; + } - add_row(row) { - if (!this.__data_already_exists(row)) { - var id = this.__add_row(row); - this.tr_id_mapping[this.data.length] = id; - this.data.push(row); - } - } + add_row(row) { + if (!this.__data_already_exists(row)) { + var id = this.__add_row(row); + this.tr_id_mapping[this.data.length] = id; + this.data.push(row); + } + } - delete_row(row_id) { - var tr = document.getElementById(row_id); - var array = this.__get_array_from_DOM_row(tr); - var data_index = this.__find_array_index(array, this.data); - tr.outerHTML = ""; - this.data.splice(data_index, 1); - } + delete_row(row_id) { + var tr = document.getElementById(row_id); + var array = this.__get_array_from_DOM_row(tr); + var data_index = this.__find_array_index(array, this.data); + tr.outerHTML = ""; + this.data.splice(data_index, 1); + } - delete_row_index(row_pos) { - var tr = this.get_DOM_row(row_pos); - var array = this.__get_array_from_DOM_row(tr); - var data_index = this.__find_array_index(array, this.data); - tr.outerHTML = ""; - this.data.splice(data_index, 1); - } + delete_row_index(row_pos) { + var tr = this.get_DOM_row(row_pos); + var array = this.__get_array_from_DOM_row(tr); + var data_index = this.__find_array_index(array, this.data); + tr.outerHTML = ""; + this.data.splice(data_index, 1); + } - get_DOM_row(row_pos) { - var row_id = this.tr_id_mapping[row_pos]; - var tr = document.getElementById(row_id); - return tr; - } + get_DOM_row(row_pos) { + var row_id = this.tr_id_mapping[row_pos]; + var tr = document.getElementById(row_id); + return tr; + } - get_data() { - return this.data; - } + get_data() { + return this.data; + } - clear_table() { - var dataLength = this.data.length; - for (var i=0; i= 0; - } + __data_already_exists(data) { + return this.__find_array_index(data, this.data) >= 0; + } - __find_array_index(value, array) { - for (var i in array) { - if (JSON.stringify(array[i]) === JSON.stringify(value)) { // compare array - return i; - } - } - return -1; - } + __find_array_index(value, array) { + for (var i in array) { + if (JSON.stringify(array[i]) === JSON.stringify(value)) { // compare array + return i; + } + } + return -1; + } - __create_table() { - if (this.table_title !== undefined) { - var label = document.createElement('label'); - label.innerHTML = this.table_title; - this.container.appendChild(label); - } - this.form = document.createElement('form'); - this.table = document.createElement('table'); - this.table.classList.add("table", "table-bordered", "action-table"); - if (this.classes !== undefined) { - for (var i in this.classes) { - this.table.classList.add(this.classes[i]); - } - } - this.thead = document.createElement('thead'); - this.tbody = document.createElement('tbody'); - var trHead = document.createElement('tr'); - for (var col of this.header) { - var th = document.createElement('th'); - th.innerHTML = col; - trHead.appendChild(th); - } - this.thead.appendChild(trHead); + __create_table() { + if (this.table_title !== undefined) { + var label = document.createElement('label'); + label.innerHTML = this.table_title; + this.container.appendChild(label); + } + this.form = document.createElement('form'); + this.table = document.createElement('table'); + this.table.classList.add("table", "table-bordered", "action-table"); + if (this.classes !== undefined) { + for (var i in this.classes) { + this.table.classList.add(this.classes[i]); + } + } + this.thead = document.createElement('thead'); + this.tbody = document.createElement('tbody'); + var trHead = document.createElement('tr'); + for (var col of this.header) { + var th = document.createElement('th'); + th.innerHTML = col; + trHead.appendChild(th); + } + this.thead.appendChild(trHead); - this.__add_control_row(); + this.__add_control_row(); - for (var row of this.data) { - this.__add_row(row); - } - this.table.appendChild(this.thead); - this.table.appendChild(this.tbody); - this.form.appendChild(this.table); - this.container.appendChild(this.form); - } + for (var row of this.data) { + this.__add_row(row); + } + this.table.appendChild(this.thead); + this.table.appendChild(this.tbody); + this.form.appendChild(this.table); + this.container.appendChild(this.form); + } - __add_row(row) { - var tr = document.createElement('tr'); - tr.id = "tr_" + this.__uuidv4(); - for (var col of row) { - var td = document.createElement('td'); - td.innerHTML = col; - tr.appendChild(td); - } - this.__add_action_button(tr); - this.tbody.appendChild(tr); - return tr.id; - } + __add_row(row) { + var tr = document.createElement('tr'); + tr.id = "tr_" + this.__uuidv4(); + for (var col of row) { + var td = document.createElement('td'); + td.innerHTML = col; + tr.appendChild(td); + } + this.__add_action_button(tr); + this.tbody.appendChild(tr); + return tr.id; + } - __add_control_row() { - var tr = document.createElement('tr'); - for (var itemOption of this.control_items) { - var td = document.createElement('td'); - var item = this.__add_control_item(itemOption); - if (itemOption.colspan !== undefined) { - td.colSpan = itemOption.colspan; - } - td.appendChild(item); - tr.appendChild(td); - } - var td = document.createElement('td'); + __add_control_row() { + var tr = document.createElement('tr'); + for (var itemOption of this.control_items) { + var td = document.createElement('td'); + var item = this.__add_control_item(itemOption); + if (itemOption.colspan !== undefined) { + td.colSpan = itemOption.colspan; + } + td.appendChild(item); + tr.appendChild(td); + } + var td = document.createElement('td'); - var btn = document.createElement('button'); - var header_action_button_style = this.header_action_button.style === undefined ? {} : this.header_action_button.style; - if (header_action_button_style.type !== undefined) { - btn.classList.add("btn", "btn-"+header_action_button_style.type); - } else { - btn.classList.add("btn", "btn-primary"); - } - if (header_action_button_style.tooltip !== undefined) { - btn.title = header_action_button_style.tooltip; - } - if (header_action_button_style.icon !== undefined) { - btn.innerHTML = ''; - } else { - btn.innerHTML = ''; - } - btn.type = "button"; - btn.disabled = this.additionButtonDisabled; + var btn = document.createElement('button'); + var header_action_button_style = this.header_action_button.style === undefined ? {} : this.header_action_button.style; + if (header_action_button_style.type !== undefined) { + btn.classList.add("btn", "btn-"+header_action_button_style.type); + } else { + btn.classList.add("btn", "btn-primary"); + } + if (header_action_button_style.tooltip !== undefined) { + btn.title = header_action_button_style.tooltip; + } + if (header_action_button_style.icon !== undefined) { + btn.innerHTML = ''; + } else { + btn.innerHTML = ''; + } + btn.type = "button"; + btn.disabled = this.additionButtonDisabled; - var that = this; - btn.addEventListener("click", function(evt) { - var data = []; - for (var elem of that.form.elements) { - if (elem.classList.contains('form-group')) { - data.push(elem.value); - } - } - if (that.additionEnabled) { - that.add_row(data); - } - if (that.onAddition !== undefined) { - that.onAddition(data, that); - } - }); + var that = this; + btn.addEventListener("click", function(evt) { + var data = []; + for (var elem of that.form.elements) { + if (elem.classList.contains('form-group')) { + data.push(elem.value); + } + } + if (that.additionEnabled) { + that.add_row(data); + } + if (that.onAddition !== undefined) { + that.onAddition(data, that); + } + }); - td.appendChild(btn); + td.appendChild(btn); - tr.appendChild(td); - this.thead.appendChild(tr); - } + tr.appendChild(td); + this.thead.appendChild(tr); + } - __add_control_item(options) { - var item; - switch(options.DOMType) { - case "select": - item = this.__create_select(options.item_options); - this.selects[item.id] = item; - break; - case "input": - item = this.__create_input(options.item_options); - break; - case "empty": - item = this.__create_empty(options.item_options); - break; - default: - break; - } - return item; - } + __add_control_item(options) { + var item; + switch(options.DOMType) { + case "select": + item = this.__create_select(options.item_options); + this.selects[item.id] = item; + break; + case "input": + item = this.__create_input(options.item_options); + break; + case "empty": + item = this.__create_empty(options.item_options); + break; + default: + break; + } + return item; + } - __add_action_button(tr) { - var that = this; - var td = document.createElement('td'); - var btn = document.createElement('button'); - btn.classList.add("btn", "btn-danger"); - btn.innerHTML = ''; - btn.type = "button"; - btn.setAttribute('rowID', tr.id); - if (that.row_action_button_style.tooltip !== undefined) { - btn.title = that.row_action_button_style.tooltip; - } - if (that.row_action_button_style.style !== undefined) { - btn.style = that.row_action_button_style.style; - } - var that = this; - btn.addEventListener("click", function(evt) { - if (that.onRemove !== undefined) { - var tr = document.getElementById(this.getAttribute('rowID')); - var data = that.__get_array_from_DOM_row(tr); - that.onRemove(data, that); - } - if (that.removalEnabled) { - that.delete_row(this.getAttribute('rowID')); - } - }); - td.appendChild(btn); + __add_action_button(tr) { + var that = this; + var td = document.createElement('td'); + var btn = document.createElement('button'); + btn.classList.add("btn", "btn-danger"); + btn.innerHTML = ''; + btn.type = "button"; + btn.setAttribute('rowID', tr.id); + if (that.row_action_button_style.tooltip !== undefined) { + btn.title = that.row_action_button_style.tooltip; + } + if (that.row_action_button_style.style !== undefined) { + btn.style = that.row_action_button_style.style; + } + var that = this; + btn.addEventListener("click", function(evt) { + if (that.onRemove !== undefined) { + var tr = document.getElementById(this.getAttribute('rowID')); + var data = that.__get_array_from_DOM_row(tr); + that.onRemove(data, that); + } + if (that.removalEnabled) { + that.delete_row(this.getAttribute('rowID')); + } + }); + td.appendChild(btn); - if (that.row_action_button.others !== undefined) { - for (var i in that.row_action_button.others) { - var newBtnOptions = that.row_action_button.others[i]; + if (that.row_action_button.others !== undefined) { + for (var i in that.row_action_button.others) { + var newBtnOptions = that.row_action_button.others[i]; - var btn_style = newBtnOptions.style !== undefined ? newBtnOptions.style : {}; - var btn = document.createElement('button'); - btn.type = "button"; - if (btn_style.type !== undefined) { - btn.classList.add("btn", "btn-"+btn_style.type); - } else { - btn.classList.add("btn", "btn-primary"); - } - if (btn_style.icon !== undefined) { - btn.innerHTML = ''; - } else { - btn.innerHTML = ''; - } - if (btn_style.title !== undefined) { - btn.title = btn_style.title; - } - if (btn_style.style !== undefined) { - btn.style = btn_style.style+"margin-left: 3px"; - } else { - btn.style = "margin-left: 3px"; - } - btn.setAttribute('rowID', tr.id); - if (newBtnOptions.event !== undefined) { - btn.addEventListener("click", function(evt) { - var tr = document.getElementById(this.getAttribute('rowID')); - var data = that.__get_array_from_DOM_row(tr); - newBtnOptions.event(data, that); - }); - } - td.appendChild(btn); - } - } + var btn_style = newBtnOptions.style !== undefined ? newBtnOptions.style : {}; + var btn = document.createElement('button'); + btn.type = "button"; + if (btn_style.type !== undefined) { + btn.classList.add("btn", "btn-"+btn_style.type); + } else { + btn.classList.add("btn", "btn-primary"); + } + if (btn_style.icon !== undefined) { + btn.innerHTML = ''; + } else { + btn.innerHTML = ''; + } + if (btn_style.title !== undefined) { + btn.title = btn_style.title; + } + if (btn_style.style !== undefined) { + btn.style = btn_style.style+"margin-left: 3px"; + } else { + btn.style = "margin-left: 3px"; + } + btn.setAttribute('rowID', tr.id); + if (newBtnOptions.event !== undefined) { + btn.addEventListener("click", function(evt) { + var tr = document.getElementById(this.getAttribute('rowID')); + var data = that.__get_array_from_DOM_row(tr); + newBtnOptions.event(data, that); + }); + } + td.appendChild(btn); + } + } - tr.appendChild(td); - } + tr.appendChild(td); + } - __create_empty(options) { - var empty = document.createElement('span'); - empty.classList.add("form-group"); - empty.id = options.id !== undefined ? options.id : 'actionTable_controlSelect_'+this.__get_uniq_index(); - return empty; - } + __create_empty(options) { + var empty = document.createElement('span'); + empty.classList.add("form-group"); + empty.id = options.id !== undefined ? options.id : 'actionTable_controlSelect_'+this.__get_uniq_index(); + return empty; + } - __create_input(options) { - var input = document.createElement('input'); - input.classList.add("form-group"); - input.id = options.id !== undefined ? options.id : 'actionTable_controlSelect_'+this.__get_uniq_index(); - if (options.style !== undefined) { - input.style = options.style; - } - if (options.placeholder !== undefined) { - input.placeholder = options.placeholder; - } - if (options.disabled !== undefined) { - input.disabled = options.disabled; - } - if (options.typeahead !== undefined) { - var typeaheadOption = options.typeahead; - $('#'+input.id).typeahead(typeaheadOption); - } - return input; - } + __create_input(options) { + var input = document.createElement('input'); + input.classList.add("form-group"); + input.id = options.id !== undefined ? options.id : 'actionTable_controlSelect_'+this.__get_uniq_index(); + if (options.style !== undefined) { + input.style = options.style; + } + if (options.placeholder !== undefined) { + input.placeholder = options.placeholder; + } + if (options.disabled !== undefined) { + input.disabled = options.disabled; + } + if (options.typeahead !== undefined) { + var typeaheadOption = options.typeahead; + $('#'+input.id).typeahead(typeaheadOption); + } + return input; + } - __create_select(select_options) { - var select = document.createElement('select'); - select.classList.add("form-group"); - select.id = select_options.id !== undefined ? select_options.id : 'actionTable_controlSelect_'+this.__get_uniq_index(); - select.style.width = "100%"; - this.__add_options_to_select(select, select_options.options); - if(select_options.default !== undefined) { - select.value = select_options.default; - } - return select; - } + __create_select(select_options) { + var select = document.createElement('select'); + select.classList.add("form-group"); + select.id = select_options.id !== undefined ? select_options.id : 'actionTable_controlSelect_'+this.__get_uniq_index(); + select.style.width = "100%"; + this.__add_options_to_select(select, select_options.options); + if(select_options.default !== undefined) { + select.value = select_options.default; + } + return select; + } - __add_options_to_select(select, options) { - for(var value of options) { - var option = document.createElement('option'); - if (Array.isArray(value)) { // array of type [value, text] - option.value = value[1]; - option.innerHTML = value[1]; - } else { // only value, text=value - option.value = value; - option.innerHTML = value; - } - select.appendChild(option); - } - } + __add_options_to_select(select, options) { + for(var value of options) { + var option = document.createElement('option'); + if (Array.isArray(value)) { // array of type [value, text] + option.value = value[1]; + option.textContent = value[1]; + } else { // only value, text=value + option.value = value; + option.textContent = value; + } + select.appendChild(option); + } + } - __uuidv4() { - return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { - var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); - return v.toString(16); - }); - } + __uuidv4() { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { + var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); + } }