Skip to content

Commit

Permalink
[SECURITY] Prevent XSS in modal component
Browse files Browse the repository at this point in the history
Resolves: #84190
Releases: master, 8.7, 7.6
Security-Commit: 4e75300bebae5e06887f3234a32a0bae9635c047
Security-Bulletin: TYPO3-CORE-SA-2018-007
Change-Id: I29ca9803823825066af87b2534aaf407183c1b4e
Reviewed-on: https://review.typo3.org/59085
Reviewed-by: Oliver Hader <oliver.hader@typo3.org>
Tested-by: Oliver Hader <oliver.hader@typo3.org>
  • Loading branch information
ohader committed Dec 11, 2018
1 parent 20927ad commit 89a38ad
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 5 deletions.
12 changes: 7 additions & 5 deletions typo3/sysext/backend/Resources/Public/JavaScript/Modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@
*/
define(['jquery',
'TYPO3/CMS/Backend/Severity',
'TYPO3/CMS/Core/SecurityUtility',
'bootstrap'
], function($, Severity) {
], function($, Severity, SecurityUtility) {
'use strict';

var securityUtility = new SecurityUtility();

try {
// fetch from parent
if (parent && parent.window.TYPO3 && parent.window.TYPO3.Modal) {
Expand Down Expand Up @@ -196,10 +199,9 @@ define(['jquery',
if (typeof content === 'object') {
currentModal.find('.modal-body').append(content);
} else {
// we need html, check if we have to wrap content in <p>
if (!/^<[a-z][\s\S]*>/i.test(content)) {
content = $('<p />').text(content);
}
content = $('<p />').html(
securityUtility.encodeHtml(content)
);
currentModal.find('.modal-body').html(content);
}

Expand Down
78 changes: 78 additions & 0 deletions typo3/sysext/core/Resources/Public/JavaScript/SecurityUtility.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/

/**
* Module: TYPO3/CMS/Core/SecurityUtility
*/
define([], function() {
'use strict';

/**
* Module: TYPO3/CMS/Core/SecurityUtility
* contains method to escape input to prevent XSS and other security related things
* @exports TYPO3/CMS/Core/SecurityUtility
*/
var SecurityUtility = (function() {
/**
* @param {Document} documentRef
*/
function SecurityUtility(documentRef) {
if (documentRef === void 0) {
documentRef = document;
}
this.documentRef = documentRef;
}
/**
* Encodes HTML to use according entities. Behavior is similar to PHP's
* htmlspecialchars. Input might contain XSS, output has it encoded.
*
* @param {string} value Input value to be encoded
* @param {boolean} doubleEncode (default `true`)
* @return {string}
*/
SecurityUtility.prototype.encodeHtml = function(value, doubleEncode) {
if (doubleEncode === void 0) {
doubleEncode = true;
}
var anvil = this.createAnvil();
if (!doubleEncode) {
// decode HTML entities step-by-step
// but NEVER(!) as a whole, since that would allow XSS
value = value.replace(/&[#A-Za-z0-9]+;/g, function (html) {
anvil.innerHTML = html;
return anvil.innerText;
});
}
// apply arbitrary data a text node
// thus browser is capable of properly encoding
anvil.innerText = value;
return anvil.innerHTML;
};
/**
* @return {HTMLSpanElement}
*/
SecurityUtility.prototype.createAnvil = function() {
return this.documentRef.createElement('span');
};
/**
* @param {string} value
*/
SecurityUtility.prototype.debug = function(value) {
if (value !== this.encodeHtml(value)) {
console.warn('XSS?!', value);
}
};
return SecurityUtility;
}());
return SecurityUtility;
});

0 comments on commit 89a38ad

Please sign in to comment.