Exploiting Zoom whiteboard via the clipboard. Nice find from @spaceraccoon
https://spaceraccoon.dev/analyzing-clipboardevent-listeners-stored-xss/
Exploiting Zoom whiteboard via the clipboard. Nice find from @spaceraccoon
https://spaceraccoon.dev/analyzing-clipboardevent-listeners-stored-xss/
@gaz @spaceraccoon Nice writeup!
Looking at this with a browser's hat on, I wonder what we could do to make the `convertToText()` mechanism go away. The new `Element.setHTML()` method aims to handle element nodes being added to the DOM. It doesn't do much for attributes... I wonder if that's a pattern common-enough for there to be something here we should be generalizing?
@gaz @spaceraccoon That said, it's a somewhat straightforward wrapper in userland:
```
let temp = document.createElement('div');
temp.setHTML(data);
el.attribute = temp.innerHTML;
```
/cc @freddy
@koto @gaz @spaceraccoon @freddy My read of the last step was that they _did_ use `convertToText()` as a sanitizer for input to the `dangerouslySetInnerHTML` sink, but that their implementation was a regex that didn't handle multi-line strings. :)
Obviously removing the use of the dangerous sink would be better. But given that developers gonna develop, I wonder whether there's anything we can learn from this for the Sanitizer API.
@gaz @mikewest @spaceraccoon @mikewest @gaz @spaceraccoon I second @koto 's interpretation in that they used DOMPurify in some places, but not in others. imho, the important piece for us to learn is:
A great sanitizer can't help if you forget to use it. A document-wide policy like CSP could enforce things (see Trusted Types).
@freddy @gaz @spaceraccoon @koto I disagree, insofar as I see this as a case of _poor_ sanitization, not _missing_ sanitization. Trusted Types is a critical tool that ensures that _something_ happens to the dangerous input, but it makes no guarantees that the output is inert when it hits a sink.
In this case, they wanted to more or less "de-htmlize" a string, replacing `<br>` with `\n` and etc. Ending that method with a stringified `setHTML()` call with a `*` blocklist would have done the job.
@gaz @mikewest @spaceraccoon @freddy hm, so they assumed the regexes are strict enough and skipped sanitizing with a full-blown sanitizer afterwards? There was definitely an attempt to sanitize.
DOMPurify was available and used in this codebase, IIUC. If DOMPurify.sanitize(s) was not called, is it more likely that a 2-liner using setHTML would?