Stored Cross-Site Scripting in Kendo UI Editor (CVE-2018-14037)

Project Description

A cross-site scripting (XSS) vulnerability in Progress Kendo UI Editor v2018.1.221 allows remote attackers to inject arbitrary JavaScript into the DOM of the WYSIWYG editor. If the victim accesses the editor, the payload gets executed. Furthermore, if the payload is reflected at any other resource that does rely on the sanitisation of the editor itself, the JavaScript payload will be executed in the context of the application which allows attackers in the worst case to take over user sessions.


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 https://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]*(&nbsp;|\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

Vendor contact timeline

2018-05-02: Contacting vendor through email for security contact.
2018-05-02: Contact person requests to obtain advisory via unencrypted mail.
2018-05-08: Advisory delivered through unencrypted email to vendor.
2018-05-29: Contacting vendor for current status and informing them about the publishing date.
2018-07-02: Reminded the vendor that the advisory will be published soon.
2018-07-02: Multiple emails exchanged, vendor demands that customers need to issue a support ticket on this case.
2018-07-03: Telling them that it is a security issue they already know two months without seemingly acting upon it.
Vendor: product managers have been informed and will contact us; no further info
2018-07-11: Asking vendor again for a status update & patch information.
2018-07-11: Vendor: “Thank you for following up. I have sent this to the product team to
take into consideration. They will be following up with you as they may need.
We appreciate you following up regarding this request.”
2018-07-12: Detailed answer from vendor regarding workaround.
2018-07-13: Requested CVE number.
2018-09-26: Public release of security advisory.

Solution

There is no fix available from the vendor. Check the vendor’s website for potential future updates.

 

Workaround

The following workaround was provided by the vendor which has to be extended in order to mitigate all of the above mentioned payloads.

First, one thing to keep in mind with the Kendo UI Editor is that since it is
a HTML editor that many users implement in order take advantage of HTML content
(compared to straight text). This means that while we often sanitize many
things (script tags, DOM event attributes, etc.) in order to prevent
cross-site scripting […] there are certain cases that we cannot automatically
sanitize because of use cases that customers of ours have – this being one of
them.

Because the value that is set to the Editor is done through the jQuery method
`$(“#value”).val()` it is possible to sanitize or encode values before being
set to the editor.

This is can be done through implementing some custom sanitations through the
`serialization.custom <https://docs.telerik.com/kendo-ui/api/javascript/ui/editor/configuration/serialization.custom>`,
and `deserialization.custom<https://docs.telerik.com/kendo-ui/api/javascript/ui/editor/configuration/deserialization>`,
options available in the Editor today.

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Untitled</title>

  <link rel="stylesheet" href="https://kendo.cdn.telerik.com/2018.2.620/styles/kendo.common.min.css">
  <link rel="stylesheet" href="https://kendo.cdn.telerik.com/2018.2.620/styles/kendo.rtl.min.css">
  <link rel="stylesheet" href="https://kendo.cdn.telerik.com/2018.2.620/styles/kendo.default.min.css">
  <link rel="stylesheet" href="https://kendo.cdn.telerik.com/2018.2.620/styles/kendo.mobile.all.min.css">

  <script src="https://code.jquery.com/jquery-1.12.3.min.js"></script>
  <script src="https://kendo.cdn.telerik.com/2018.2.620/js/angular.min.js"></script>
  <script src="https://kendo.cdn.telerik.com/2018.2.620/js/jszip.min.js"></script>
  <script src="https://kendo.cdn.telerik.com/2018.2.620/js/kendo.all.min.js"></script></head>
<body>
  <textarea id="editor"></textarea>
  <script>
    function sanitizeHtml(html) {
      var temp = $("<div></div>").html(html);
      temp.find("object").remove();
      return temp.html() || "\ufeff";
    }

    $("#editor").kendoEditor({
      tools: [
        "viewHtml"
      ],
      deserialization: {
        custom: function(html) {
          return sanitizeHtml(html);
        }
      },
      serialization: {
        custom: function(html) {
          return sanitizeHtml(html);
        }
      }
    });

    var editor = $("#editor").getKendoEditor();

    editor.value('<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgic2VjdGVzdCIpPC9zY3JpcHQ+"></object>');
    console.log(editor.value());
  </script>
</body>
</html>

 

Advisory URL

https://www.sec-consult.com/en/vulnerability-lab/advisories/index.html

 

 

EOF M. Tomaselli / @2018

Project Details

  • TitleStored Cross-Site Scripting
  • ProductProgress Kendo UI Editor
  • Vulnerable versionv2018.1.221
  • Fixed versionnone, see workaround
  • CVE numberCVE-2018-14037
  • Impactmedium
  • Homepagehttps://www.progress.com/kendo-ui
  • Found2018-04-23
  • ByM. Tomaselli (Office Munich) | SEC Consult Vulnerability Lab

Cookie Preference

Please select an option. You can find more information about the consequences of your choice at Help.

Select an option to continue

Your selection was saved!

Help

Help

To continue, you must make a cookie selection. Below is an explanation of the different options and their meaning.

  • Accept all cookies:
    All cookies such as tracking and analytics cookies.
  • Accept first-party cookies only:
    Only cookies from this website.
  • Reject all tracking cookies:
    No cookies except for those necessary for technical reasons are set.

You can change your cookie setting here anytime: Privacy Statement. Legal Notice

Back