As many of you reading this probably already know, in mid April, a friend and I (@Daley) located a Remote Code Execution vulnerability in EA's Origin client (CVE-2019-11354). Today I'm going to go in depth on how we discovered this vulnerability, along with a couple others we needed to chain along the way ;pp
A lot of what was discovered was enabled by QtWebEngine debugging. By passing a specific flag to the origin process, we can hook Chrome devtools to the process and inspect the web view.
In order to set up remote debugging, you have to enable port-forwarding in the chrome devtools. To do this you need to start chrome and open the devtools. From there, open the Remote Devices view, enable port forwarding, and fill in the settings as needed.
Now we can start the origin process.
If you navigate to localhost:31337 in chrome, you'll be met with the devtools, and from there, you can do all the poking around you need.
URI exploitation isn't new by any means. For a long time it has provided reliable ways of delivering payloads and executing commands on remote computers. The idea of being able to execute remote commands by simply having your target visit a web-page is obviously more than ideal to any threat actor.
In this scenario, the whole idea behind registering a custom URI handler is for ease-of-access. For example, Origin's handler is mainly there to be able to launch or purchase games from your web-browser. As soon as you click one of those links, your Origin client will launch with the parameters supplied by the crafted URI.
The Origin URI provides us with a few options we can use. To launch a game, we can use the following URI. This option gives us a few parameters. That's where we'll find our first bug.
The first bug relies on the fact that when Origin recieves an invalid game ID, it gives you the option to manually add it to your game library. In the dialog that pops up, it also echoes out the title of the game you'd like to add. If the game isn't recognized by Origin, how is it supposed to fetch a title, you may be asking. That's where the "title" parameter comes in handy.
We can quite literally specify any title we want by simply using the following link:
This initially prompted me to try injecting HTML to see if maybe there was a possibility for XSS. You can tell that the HTML is being interpreted when you use the following link:
Angular is notorious for sandboxing, which means that we're going to have to do some funky scripting in order to execute what we want. Thankfully some researchers have already compiled a gist of Angular sandbox-escapes, which is what we used.
By using the following payload in the title param, we were able to pop an alert box (l33th4x!!!!11)
Now, this part of the exploit is relatively trivial. QDesktopServices itself isn't necessarily vulnerable here, however the way that Origin has implemented it, on top of the other vulnerabilties, it ended up with a pretty nasty result.
According to the Qt documentation, "The QDesktopServices class provides methods for accessing common desktop services. Many desktop environments provide services that can be used by applications to perform common tasks, such as opening a web page, in a way that is both consistent and takes into account the user's application preferences."
By accessing Origin.client.desktopServices in the DOM, we can find the following functions:
: function asyncOpenUrl() : function asyncOpenUrlWithEADPSSO() : function deminiaturize() : function flashIcon() : function formatBytes() : function getVolumeDiskSpace() : function isMiniaturized() : function miniaturize() : function moveWindowToForeground() : function setNextWindowUUID() : function showWindow()
Some of these functions are pretty cool. If you call
flashIcon(), you'll see the Origin icon flashing (big surprise, right). Most of the functions are pretty self explanatory actually, so I won't bother going into them.
What we had luck with was
asyncOpenUrl(). This function basically calls QDesktopServices
openUrl() function, which in turn opens a web browser, or whatever application is registered with the provided URI. According to the documentation, you can also load local resources. Sounds promising, right ;)?
As I mentioned earlier, Origin has a CSP in place which makes exfiltration somewhat difficult. If we use the
ldap:// URI handler in conjunction with
asyncOpenUrl(), we can send an LDAP request along with the data we want to exfiltrate.
From the server, start tcpdump and set the necessary filters and you should see the data being transmitted in plaintext.
Origin.user object contains a bunch of other information as well.
: function accessToken() : function country() : function dob() : function email() : function emailStatus() : function globalEmailSignup() : function isAccessTokenExpired() : function originId() : function personaId() : function registrationDate() : function sessionGUID() : function showPersona() : function tfaSignup() : function underAge() : function userGUID() : function userPid() : userStatus()
Electronic Art's rolled out a patch, however there are bypasses available as some on Twitter have decided to share. This highlights the issue once again and should be addressed by sanitizing all types of input, as the initial patch failed to do so.