Continuing from his previous post, Bug Bounty Hunter Renwa writes about the second vulnerability he submitted to Opera’s Private Bug Bounty Programme: a Remote Code Execution in Opera’s My Flow Feature. What follows is his write-up and experience. The described vulnerability of course has been fixed immediately after reporting.

One of the cooler features of the Opera Browser is My Flow, which is basically a shared space between your computer and your phone, allowing you to share links, images, and videos with yourself. To connect, you just scan a QR code, and then you can send things between devices.

Using the developer tools in Opera, I found that the My Flow interface is loaded from the domain web.flow.opera.com, which is just a normal HTML page, and which allows me to view its code and components.

Looking at the page’s source code, I found that the page communicated with a browser extension, but from my browser’s extension list in opera://extensions/, nothing appeared. After some research, I found that it is actually a hidden browser extension, which could be displayed by opening Opera using a special flag, –show-component-extension-options. After opening the browser with that flag, I found the extension called Opera Touch Background, and was able to view its source code.

Going back to the web.flow.opera.com page, I began looking for XSS vulnerabilities. What caught my eye was this code:

const html = e.dataTransfer.getData('text/html');
const src = html.match(//);
if (src && src[1]) {
   const parser = document.createElement("span");
   parser.innerHTML = src[1];
}

This functionality is for drag-and-drop; when a user drops an image onto the page, the code creates an element with its innerHTML element set as the location of the image. However, there are two problems with this:

  1. In browsers, it is possible to set the dataTransfer to any arbitrary value.
  2. In browsers, if you create a new element and set its innerHTML to an <img> tag, it will still be loaded in the background.

This means that the following will cause an alert box, despite no image being loaded on the screen:

const parser = document.createElement("span");
parser.innerHTML = '<img src=x onerror=alert(1)>';

With all of this in mind, I created a small proof-of-concept XSS. To show how easy it was to cause the XSS, I created a webpage which, once you began dragging an image, would redirect to the web.flow.opera.com page after a couple seconds. This meant that a user would only need to begin dragging an image, and then simply let go of the mouse, for the XSS to happen.

However, I wanted to show a greater impact, so I began looking at what the Opera Touch Background extension actually did. As it turns out, it has higher privileges and access to native functions, such as opr.operaTouchPrivate, which is a collection of functions developed for use with the My Flow application. Looking at the available functions, two cases caught my eye: SEND_FILE and OPEN_FILE.

The SEND_FILE function retrieves information about a file provided by the user and uploads it to My Flow; it also saves the file to the user’s computer in Downloads/MyFlow. The OPEN_FILE is used for image files for My Flow, but while testing I noticed that you can open any type of file, not just images.

With these two functionalities, we can now have an arbitrary file write, and open, on the targeted computer. To create a real scenario I created a proof-of-concept which would first create a file exploit.bat containing calc, and then secondly, open the file — which would cause it to be executed, opening the Windows calculator:

operaTouchBackground.port.postMessage({
   type: "SEND_FILE",
   name: 'exploit.bat',
   content: 'calc',
   file_type: 'image/png'
});

operaTouchBackground.port.postMessage({
   type: 'OPEN_FILE',
   localFileName: 'exploit.bat'
});

Finally, with a convincing user interface for the single click (dragging) needed to activate the exploit, I demonstrated how the simple XSS could be turned into remote code execution for users of the My Flow system.

The vulnerability was fixed within a few days, and a bounty was awarded around three weeks later.

Thanks for reading!
Renwa

Bounty: $8,000 USD.

Related Posts

Back to top

User comments