Lucene search

K
hackeroneDanieljppH1:1401268
HistoryNov 16, 2021 - 7:39 a.m.

Rocket.Chat: Persistent CSS injection with ’marked’ markdown parser in Rocket.Chat

2021-11-1607:39:30
danieljpp
hackerone.com
16
rocket.chat
css injection
marked parser
persistent attack
style manipulation
functionality block
content hijack
vulnerability
mitigation
impact
fix

EPSS

0.001

Percentile

24.8%

Summary: Rocket.Chat offers two different markdown parsers out of the box: the ’orginal’ one and the ’marked’ one. Both markdown parsers offer a different set of features with different re- strictions. Due to more loose restrictions in the ’marked’ parser, a persistent CSS injection in the web interface of Rocket.Chat is possible.

Description: Due to style injection in the complete chat window, an adversary is able to manipulate not only the style of it, but will also be able to block functionality as well as hijacking the content of targeted users. Hence the payloads are stored in messages, it is a persistent attack vector, which will trigger as soon as the message gets viewed.

Releases Affected:

  • 4.1.0 with ‘marked’ parser

Steps To Reproduce (from initial installation to vulnerability):

(Add details for how we can reproduce the issue)

  1. Setup a new installation of Rocket.Chat
  2. Enable the ‘marked’ parser in the admin settings under ‘Message’ > ‘Markdown’ > ‘Markdown Parser’
  3. Create a second user account with username usertest and a channel containing both accounts
    4 . Send some messages between both accounts
  4. Send
<div>foobar</div>

This should block the top right channel settings with a red box.
6. Send

foo
&lt;style &gt;
[data-username="usertest"] div div p{
    background: rgba(255, 0, 0, 0.2);
    font-size: 0;
}
[data-username="usertest"] div div p::after{ font-size: initial;
    content: "hacked";
}
&lt;/style&gt;

as admin user and observe, that the messages of ‘usertest’ are overwritten with the content ‘hacked’. (It can be done vice versa when replacing ‘usertest’ in the payload with the admins username).

Supporting Material/References:

Root Cause

The implementation of the ’marked’ render removes html encoding of the message right before rendering it in app/markdown/lib/parser/marked/marked.js line 98.

	message.html = _marked(unescapeHTML(message.html), {
		gfm,
		tables,
		breaks,
		pedantic,
		smartLists,
		smartypants,
		renderer,
		highlight,
	});

	const window = getGlobalWindow();
	const DomPurify = createDOMPurify(window);
	message.html = DomPurify.sanitize(message.html, { ADD_ATTR: ['target'] });

Due to the unscape, the user will be able to inject custom HTML elements. Since DomPurify.sanitize will only sanitize XSS relevant elements and properties, the malicious HTML with the CSS injection will be set into the user’s message.

Suggested mitigation

To avoid the style injection, but still allow the usage of custom tags, DomPurify.sanitize could be configured to also remove style elements and attributes. Another way to mitigate the issue would be to not unescape the html before rendering it with ’marked’ to therefore prohibit the user to use custom HTML in their messages.

Impact

An attacker can block the user from certain functionalities as well as render the chat window unusable (e.g. with a rotation of the complete html body) after the user enters a channel. Another impact of the issue is the authenticity and integrity of messages. Since an adversary will be able to manipulate or hide arbitrary user messages, the authenticity and integrity is not given anymore. These attack vectors are stored in messages, which will make them available for every new user entering the channel.

Fix

Fixed in 5.0>

EPSS

0.001

Percentile

24.8%

Related for H1:1401268