As you may recall, back in June, Checkmarx disclosed multiple cross-site scripting (XSS) vulnerabilities impacting Drupal Core, listed as CVE-2020-13663, followed by a more technical breakdown of the findings in late November. Today, we’re releasing details surrounding additional, new vulnerabilities (CVE-2020-13669) uncovered in Drupal Core as part of our continued research of the open source CMS platform. All research was conducted and reported to Drupal by Dor Tumarkin of Checkmarx.
CVE-2020-13669 – Overview
Drupal Security Risk: Moderately Critical – https://www.drupal.org/sa-core-2020-010
Vulnerable versions:
- Drupal 8.8 – before 8.8.10
- Drupal 8.9 – before 8.9.6
- Drupal 9 – before 9.0.6
Impact Summary
- Inject malicious code in webpages via Cross-Site Scripting to:
- Hijack user accounts
- Inject malicious web-content, such as malicious login or payment forms
- Defacing a page to hide its contents
- Redirect users to a website of an attacker’s choice, allowing them to abuse users’ trust in the victim website
CVE-2020-13669 – FigCaption Widget – Self-XSS, Stored DOM Manipulation, and XSS Potential
Vulnerability Proof of Concept (PoC)
The Figure Caption Widget (“FigCaption”) allows even basic content contributors with Basic HTML content privileges to insert a caption into their content. It is bundled with Drupal Core’s default CKEditor.
The raw HTML of such a caption would be of the following form:
Once submitted or rendered, this HTML is morphed into an entire HTML tree that presents the image inside CKEditor. However, the “data-caption” attribute may itself contain HTML, which is then rendered, and suffers from multiple issues as follows:
- A lack of coherence/consistency between HTML attribute whitelists for the general CKEditor and internal FigCaption HTML, which allows the HTML inside FigCaption to contain arbitrary attributes, allowing:
- Injecting arbitrary attributes and classes into <a> HTML tags, such that classes with CSS that covers the entire app, defacing pages permanently with a redirection to a site of an attacker’s choosing (it should be noted that “on*” event attributes, such as “onclick”, are still properly sanitized)
- Bypassing certain sanitizing behavior which could lead to XSS, given more widgets in the ecosystem, such as inserting the “javascript:” scheme into attributes that generally sanitize this scheme
- A lack of sanitization when rendering in preview mode, allowing injecting <script> tags, which leads to self-XSS
Vulnerabilities Breakdown and Potential Implications
The issue affects the DOM in multiple ways, both stored and reflected from DOM. All issues here pertain to picture captions, which is a plugin added on top of CKEditor by the Drupal team.
Self-XSS PoC
Self-XSS occurs when users copy values into a CKEditor instance. This requires a much more involved user in an attack scenario—the user needs to copy and paste content into the page.
Copying the following payload and switching to an HTML view (in vanilla Drupal Core, by clicking the “Source” button) would result in XSS:
Page Defacement with Redirection – Stored DOM Manipulation PoC
The above self-XSS is sanitized by the server when submitted, as the caption itself has a separate server-side component for sanitization. However, this creates an inconsistency—two components provide dissimilar sanitization. The major issue is that sanitization outside of the caption for “Basic HTML” mode only allows the following tags and attributes:
While the server-side sanitizer allows only the same tags, it does not offer any sanitization for attributes beyond normal XSS sanitization (on* JS events, removing “javascript:” prefixes from attribute values, some style attributes). This allows injecting far more than just the basic HTML tags—classes can now be used to get styles, data-* attributes can be used to power certain widget functionality, and more.
For example, consider the following defacement which injects a clickable redirection button:
This allows injecting buttons into HTML UIs, which can redirect to other websites. This can be made even worse by adding the “joyride-modal-bg” class to cover the whole page:
Adding the “joyride-modal-bg” class to an “a” tag will turn the entire page into a gray block on top of all the content, as per “joyride-modal-bg”’s CSS properties. By having an “a” element cover the whole page, clicking anywhere on that element would redirect to an external website of an attacker’s choice as declared in “src”. This would allow attackers to deface the website or conduct phishing attacks by impersonating the website of origin, even from the lowly Basic HTML content adding permission.
The Broken Widget – Potential Stored XSS PoC
A potential exploit also exists by creating a partial widget. However, it’s not based on what the widget is when it is edited in CKEditor, but it’s based on attempting to inject the HTML product of a widget back into CKEditor. The product of a widget is the HTML generated by it, rather than the HTML fed to it:
As the previous exploits show, by combining the ability to add some benign HTML tag such as <em>, but with widget “data-*” and class attributes, an attacker is able to construct partial or broken widgets, which trigger when the page renders. Since widgets rewrite parts of the DOM, and trigger certain JS methods, this may allow a downstream DOM XSS.
For example, the following PoC, based on widget attributes, would trigger a broken widget from within the data-caption when viewed as Drupal content:
However, when browsing back to the edit view of this Drupal node, some of the broken widget’s functionality will trigger. The broken widget will read the value “src” in data-cke-widget-data’s JSON, and use it to populate the HTML attribute “src” inside the widget upon rendering the above payload in editor view, after it has been stored. This allows storing a payload that replaces the “src” attribute in the “img” tag with “javascript:alert(“XSS”)”:
This demonstrates that widget flow can be triggered from broken widgets to populate attributes, bypassing URL scheme sanitizers by inserting dangerous values into attributes after the page has already rendered.
The payload <img src=javascript:[code] > only functions for older browsers; Chrome complains about the URL scheme, while Firefox, Edge, and the latest IE ignore it outright. However, note that if an appropriate widget was in the scope where it was possible to overwrite <a href> or <iframe src> in this way, it would be possible to store a DOM XSS payload here. Given additional widgets in a slightly less barebones ecosystem than standalone Drupal Core, a stored XSS is a very likely possibility using this vector.
Overall, an issue clearly exists in containment. It is possible to escape a restrictive Basic HTML sandbox to a looser one which allows injecting classes, ids and arbitrary data attributes, and store dangerous HTML in the most basic Drupal ecosystem.
Summary of Disclosure and Events
Unlike the previous issue disclosed (CVE-2020-13663), CVE-2020-13669 is actually two distinct vulnerable elements. The FigCaption widget, and Drupal widgets in general, are both client-side and server-side mechanisms, which requires both to behave identically on both client and server. Finally, the fixes for both of these mechanisms, while completely disparate, involved the same basic approach—applying the restrictive whitelists of Basic HTML mode to the whitelist within the image caption, so that attackers cannot access more HTML functionality and thus breach the HTML sandbox.
Recommendation Summary
The fixes for these issues have been released, and it is highly recommended for all organizations to update their Drupal Core to the latest available version.
Timeline of Disclosure
18-Jun-20 – Drupal Self-XSS reported, followed by HTML defacement injection, and XSS prevention bypass via broken widgets
16-Sep-20 – Drupal Core new sub-versions release across all major versions, mitigating CVE-2020-13669
Final Words
Drupal Core is a complicated piece of software with many content and system management features and a vast plugin ecosystem. It is no surprise that this complexity yields such vulnerabilities—particularly common web-vulnerabilities such as XSS.
To counterbalance this complexity, the Drupal Security Team takes a strong stance and ownership on securing open-source software. They are responsive, receptive, and thorough, which allows for both a quick and high-quality response to security issues being reported.
Disclosures like this are part of the Checkmarx Security Research Team’s efforts to drive changes in software security practices. Checkmarx is committed to analyzing open source packages to help development teams build and deploy more secure software. Checkmarx’s database of open source libraries and vulnerabilities is cultivated by the Checkmarx Security Research Team, empowering CxSCA with risk details, remediation guidance, and exclusive vulnerabilities that go beyond the NVD.