Security flaw introduced through the serialization of foreign content

Mutation XSS bypass tackled in DOMpurify

A successful sanitization bypass has been achieved for DOMPurify through the abuse of how the software serializes foreign content.

DOMPurify is a cross-site scripting (XSS) sanitizer for HTML, the MathML markup language, and SVG vector graphics format.

Available on GitHub, the open source JavaScript software scrubs code to sanitize and remove any dangerous elements that could be exploited to trigger XSS attacks.

However, penetration tester and bug bounty hunter Michał Bentkowski has been able to find a way to bypass sanitizing checks.

Mutation XSS (mXSS) attacks first appeared on the scene in 2013. As described by Mario Heiderich, this class of XSS exploit abuses browser default features and parsing differences.

According to Bentkowski’s advisory and technical write-up of the issue, published September 21, DOMPurify parses, serializes, and then again parses untrusted code, using commands such as:

div.innerHTML = DOMPurify.sanitize(htmlMarkup)

The code is parsed and passed to the DOM tree, the tree is sanitized, then the DOM tree is serialized back into the HTML markup. The parsed DOM tree is then appended into the document’s DOM tree.

Intuition upended

“The intuition may be that serializing a DOM tree and parsing it again should always return the initial DOM tree,” the researcher said. “But this is not true at all.”

The serialize-parse roundtrip is not “guaranteed to return the original DOM tree,” Bentkowski noted, and as such, can become a root cause of an mXSS exploit.

When foreign content is introduced, such as MathML or SVG namespaces, a different kind of parsing is utilized, in which child entities are allowed and HTML entities are decoded.

Read more of the latest vulnerability news

In the MathML namespace, two special elements – mglyph and malignmark – allow the creation of a markup that is “in HTML namespace, but on reparsing it is in MathML namespace, [meaning that] the subsequent style tag [is] parsed differently and leading to XSS,” the researcher explained.

A fix for the mXSS flaw was released on September 18. DOMPurify Version 2.0.16 contains a patch for the vulnerability, alongside a fix for a security policy error impacting user agents on older builds of Google Chrome on Android devices.

Bentkowski told The Daily Swig that the disclosure earned him a $250 reward through Fastmail. While Fastmail products were not affected, the company uses DOMPurify and has added the library to its bug bounty scope.

Previously, Fastmail awarded the researcher $750 for a CSS sanitization bypass.

‘Matter of time’

Mere days after the patch was issued, another bypass and payload were found with a similar root cause. Bentkowski said that a pattern in the software’s code – div.innerHTML = DOMPurify.sanitize(html) – is “prone to mutation XSS-es by design”.

“It’s just a matter of time to find [other] instances,” the researcher added.

Bentkowski’s achievement has since inspired another security researcher to start digging into DOMpurify.

Intrigued that his fellow researcher had “used style with math based tags to confuse the HTML parser and bypass DOMPurify”, PortSwigger’s Gareth Heyes managed to bypass the patched version of DOMPurify and trigger mXSS in both Chrome and Firefox.

Last year, Bentkowski also described how it was possible to abuse the <svg> element in DOMPurify to trigger mXSS variants in Chrome and Safari.

Then in June, the penetration tester examined Sanitize, HTML, and CSS sanitization software for Ruby. An improper sanitization vulnerability, tracked as CVE-2020-4054, was discovered that could lead to XSS attacks.

RELATED Configuration loophole triggers XSS in Sanitize Ruby Gem