We have an XSS in a desktop application, what happens next? How can you escalate it to remote code execution? Let's see.
Modern desktop applications are mostly1 based on Chromium. There are three major frameworks:
cute
).There also some miscellaneous frameworks like NW.js. I have only seen a single commercial app using this framework and it was six years ago when I was still doing consulting at good ole' Cigital.
There are two kinds of browser-based desktop applications:
The JavaScript bridge is a set of APIs that allow the web content in the application to interact with the host machine. In Steam (based on CEF), you click on the install button on a web page displayed in the app and a game gets installed on your machine. The web page button calls some JavaScript and eventually it uses the JavaScript bridge to do stuff on the machine.
Rogue JavaScript (e.g., via XSS) can use it to jump the browser sandbox and do bad things to the underlying machine.
XSS Happens (lol)
"But, I am not gonna have XSS, Parsia." You will, my friend. Even if you do everything right, you might get hit by a framework bypass.
As is tradition, we're gonna review public bugs. That's how I learn.
Years ago (probably around 2015), I looked at Razer Comms. Think of it as the precursor to Discord. Razer Comms was a CEF app and I managed to get a few trivial XSS instances there.
Not knowing what to do next, the best I could do was show a prompt to phish user's passwords. Now, I wish I had explored the JavaScript bridge to see what else I could have done.
Is this the best I could do?
I never disclosed them and published a post after it was retired:
Disclosure: I work for EA and Origin is one of our products.
I have used this bug numerous times. There are a few reasons:
XSS happened because of an AngularJS sandbox bypass. This is one of those
situations when you can do everything correctly but get hit. We see a typical
alert
.
But, the last section named The Third Bug (RCE) explores
the JavaScript bridge. Origin is using the QtWebEngine to display web pages and
the Origin.client.desktopServices
API is available. The weapon of choice is
asyncOpenUrl
which allows us to pass a scheme (including file:///
to execute
files) but, no parameters.
This is a new one by Joel Noguera of SwordBytes Security. You should read it:
I am not gonna go through the blog post but, here's a summary (quoting myself again lol):
CEF App -> Protocol Handler -> Send request -> Response has XSS -> XSS calls JavaScript bridge API -> Write file with API -> Execute file with API
Let's focus on the Escaping the CEF sandbox
section. The Overwolf JavaScript
bridge provides a openUrlInDefaultBrowser(url) which is
similar to what we have seen before. We can open URL/file or execute files
without parameters.
But, there's also writeFileContents which allows writing a file to disk. The rest of the path is clear, write a bat file (or an HTA file if you feel fancy) and then execute it with the previous API.
I have purposefully not talked about Electron in this post. Electron has the
ultimate JavaScript bridge with nodeIntegration
. I have talked about it a lot.
Even, when it's disabled, RCE happens (this is a great writeup,
btw). With the Electron defaults becoming more secure, we need to start using
the techniques in this blog.
Here's a ton of examples (including two of mine):
XSS happens. After you get XSS in a modern desktop app, start poking the JavaScript bridge to jump out of the Chromium sandbox.