Uploaded image for project: 'ZK'
  1. ZK
  2. ZK-5766

DomPurify fails with partial html content

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: Blocker Blocker
    • 10.1.0
    • 10.0.0, 10.0.1, 10.0.1.1
    • None
    • Security Level: Jean
    • None

      2024-10-11 - Reopened additonal cases of domPurify with partial content (see comment)

      2024-10-09 - Reopened: additonal cases of domPurify failing with partial content:

      https://zkfiddle.org/sample/342cc7c/2-domSanitze-errors-due-to-partial-html

      Open fiddle, search of the string:
      onClick

      current result:

      All of the samples above allow a onClick="..." string to escape from a DOM attribute, and register another attribute, such as a JS listener or others, and can be used as an XSS vector.

      Expected result

      Attributes are not escapable

      Debug information

      The core of the issue is that the DomPurify library only works with full HTML elements
      A full element is either a full node, or an implicite text node.
      A series of attributes without an opening tag causes the DomPurify library to incorectly "fix" the quotes / doublequotes, and as a result causes potential XSS scenarios

      Dom purify is used in more locations than the ones reported in the current sample, and may still cause issues.
      Even if this sample string doesn't trigger the issue, since DomPurify fails to correctly escape the attribute content in the scenario above, it is reasonable to expect that a well-crafted malicious string could be created for other cases with the same results.

      2024-10-08 - Reopened: updated fiddle with reproducing case

      https://zkfiddle.org/sample/1r8ig9m/2-dompurify-partial-html-updated

      current result:

      Using \" inside of a style value transform the " into ' character, instead of encoding it to "
      If the string is delimited by single quotes, this allow the value to end the current single-quote delimited string and start another CSS rule.

      Expected result

      Style value cannot use \" to break out of a rule and create new unintended rules

      Steps to Reproduce

      Run fiddle
      https://zkfiddle.org/sample/1r8ig9m/1-dompurify-partial-html

      Current Result

      the attribute cleanup fails for 2nd row, causing tooltipText to spill into DOM content

      Expected Result

      attribute content doesn't spill in dom content

      Debug Information

      Caused by DomPurify.sanitize incorrectly adding string ending doublequote inside of an existing attribute.
      This happens on partial html content passed to DomPurify sanitize.
      Doesn't happen on fully formed dom element content

      Run in JS console as test samples:

      DOMPurify.sanitize("<div id= title='<a href>'></div>")
      > `<div href="" id="title='<a">'></div>`
      href word inside of title, removed when inside of fully formed div outer element

      DOMPurify.sanitize("<div id= title='<a foo>'></div>")
      > `<div id="title='<a">'></div>`
      foo word inside of title, removed when inside of fully formed div outer element

      DOMPurify.sanitize("id= title='<a href>'")
      > `id= title='<a href="">'</a>`
      attribute content broken, href receives doublequotes, breaks attribute to dom content

      DOMPurify.sanitize("id= title='<a foo>'")
      > "id= title='<a>'</a>"
      attribute content broken, but doesn't escape to dom content

      Workaround

      <script><![CDATA[
      zk.afterLoad('zk', function() {
          var xzUtl = {};
          zk.override(zUtl, xzUtl, {
             encodeXMLAttribute : function() {
                var result = xzUtl.encodeXMLAttribute.apply(this, arguments);
                return result.replaceAll('<', '&lt;');
             }
          });//zk.override
      });//zk.afterLoad
      ]]></script>
      

            jumperchen jumperchen
            MDuchemin MDuchemin
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: