Photo by Markus Spiske on Unsplash

Earlier this month, a colleague noticed some formatting issues going on in Azure Data Studio (formerly SQL Operations Studio). For background, Azure Data Studio is basically SQL Server Management Studio’s little sibling that’s meant to be a cross-platform application for running SQL queries and performing basic management tasks. It’s built with Electron and based on the same guts as the popular Visual Studio Code editor.

Normally, a formatting bug in a desktop app isn’t something to bat an eye over, but what was happening was that HTML in the database was somehow leaking outside of what should have been a text field and being rendered onto the page as formatted HTML.

HTML should be in its column as text, but ended up actually getting rendered to the page

Since an Electron app like Azure Data Studio is basically a web browser masquerading as a desktop app, this quickly raised concern about Cross Site Scripting (XSS). XSS happens when you can inject arbitrary HTML or JavaScript onto a page, either from server-generated content or from setting a raw string as innerHTML without proper escaping. Injected JavaScript on a login page or checkout page can easily steal sensitive information or take over an account. In general, although this can compromise a site, it will not by itself compromise the computer viewing the page or the server displaying it.

A quick inspection with the built-in chrome developer tools quickly revealed that the HTML was ending up on the page by having the raw value of a column set to the title attribute of an element in the data table. XSS can happen when an unescaped value is written as raw HTML like in the example below:

element.innerHTML = `<span title="${value}">...</span>`;

By setting the value to "><h1>Hello World</h1><span title=" , this would cause the HTML output to the page to look like this:

<span title=""><h1>Hello World</h1><span title="">...</span>

With HTML on the page, a few well known hacks allowed us execute whatever JavaScript we wanted. This meant that an attacker could insert a crafted value into the database that would execute as soon as a developer or database admin viewed the value in Azure Data Studio. After some quick testing, we had a 1-liner keystroke logger that would log all keystrokes to the console, including password entry in the SQL connection tab. The logger would persist as long as the app was open after the user viewed the dangerous content.

This seemed concerning enough that we gave a heads up to the Microsoft Security Response Center. Around the same time, a github issue about the formatting issues was also created and Microsoft employees noted the potential for XSS.

However, this raised the question of how much damage you could do with an XSS bug in an Electron app like Azure Data Studio or Visual Studio Code. I had never done more than spin up a quick test project with Electron, so after some digging, I learned that you could set an Electron window to run as an isolated browser window or with tight integration with the node.js back-end. Tight integration with node is convenient but it also means that any XSS bug can escalate into a code execution bug. As it turns out, this tight integration is used in Azure Data Studio.

With node integration, what started out as an HTML formatting bug turned into shell access.

By executing JavaScript which called into Electron’s node.js API, we were able to gain shell access. In the above example, we exploited this to open the windows calculator app to demonstrate.