 Hi, everybody. My name is Silvia Velli, and this is my talk, only an election away from code execution. So, a little bit about myself. I'm currently working as a web application pentester in an Estonian-based company called Clarified Security, so if you're asking where Estonia is, it's a far, far away land from here. And I consider myself to be a bit of a reversing enthusiast and a proud member of the Black Hood movement, which is basically a women-only reverse engineering workshop. So, the talk that I'm presenting to you today was part of my master's thesis. It was also the project that I was working on, which got me my very first CVEs. And by coincidence, this happens to be my very first conference talk, so let's see how that's going to go. So, thank you. So, those of you who have never heard of election framework, it is a framework developed and maintained by the GitHub team, so pretty famous, and it came around in 2013. However, back then, it was the platform on which the hackable text editor, Adam, was built upon. And in 2015, it got renamed to what we know of today as election. And the framework basically allows you to build multi-platform desktop applications. But the funny part here is that you're building those desktop applications by only using web technologies. So, yeah. And since it's using web technologies, it gives you pretty much a good platform if you want to move from web applications to desktop applications. As this case, these two worlds have sort of merged together almost unnoticeably. So, what got me into this topic first place? It was a bit of good luck from friends, but I started to notice these articles and news bulletins where people were talking about, they were getting cross-site scripting vulnerabilities from desktop applications, but these were transforming into code execution. So, I mean, how bad can that actually go? And not only this, but I started noticing people were discussing about election framework and all the vulnerabilities that started to pop up. And just few days ago, I happened to come by a tweet, which in my opinion was so spot on. So, can you imagine a person who would come up with an idea? Let's reinvent the desktop applications, but in such a way that we take one of the most common web application vulnerabilities, cross-site scripting vulnerability, and let's allow this to transform into native code execution. So, yeah. But nevertheless, soon being named started to adopt the framework. So, there were already these web applications by these, yeah, you can see on the logos, but then they came out with their own desktop applications, and soon tons of open source applications followed in GitHub, or even the ones that are listed on the official site that Electron has with all their documentation. And, yeah, as you see, in 2015, Electron came around with a bit of, a bit over 100,000 downloads by the NPM stats. But now, we were already in 2017, and then the download number was already over 4 million. So, you can imagine how it's going to be like in 2018. So, you can see how fast the framework got popularized. People were experimenting with it. But at the same time, if you come to this new environment, then you start experimenting, then things are, yeah, not going exactly the right in the first try. So, when I'm talking about the Electron framework, I'm actually talking about its three core components. The core components are Node.js, the lib Chromium content module from the Chromium project, which here is basically the core code that you need to even render a page. And then the VH JavaScript engine, which Node and the Chromium share a single instance of. So, similarly to Chromium, Electron also uses multiprocess architecture. What that means is, if you launch an Electron application, then there are two types of processes that are created. There's always the main process, never more than one. And then there is one or multiple renderer processes, which are associated with that main process, where they were created from. And each of the processes is running concurrently. And the processes resources and memory are isolated. So, in this case, it also serves the purpose of a safety mechanism. So, in case there is a fatal error in one of these processes, the rest of the application will survive. So, everything is cool. And to give you an overview of how a simple Electron application looks like, we can take three files. So, first of all, the index.js, sorry, the main.js. Then the index.html and the package.json file. So, package.json file here is what contains the main script. In our case, this is main.js. However, if you don't go there and mark it specifically, it's going to fall back to index.js. Then talking about index.html, then this file is what's going to contain everything that we want to display to the user. And, yeah, another good point here is that main.js, here is the application's entry point. So, this is what's going to get executed within the main process. However, all the content we're going to display to the user is going to get executed as a renderer process. And Electron, being such a good framework, it's a bit of irony here, but being such a good framework, provides you a set of framework-specific APIs besides the built-in node models themselves. And these framework-specific APIs are either accessible to the main process, to the renderer process, or in a couple of cases, to both of them. And I'm not going to go into too much detail here, as there's so many framework-specific APIs, but for the scope of this talk, we should know that in Electron applications, main process is what is responsible for creating and managing new browser windows, as well as a set of events during the lifetime of that application while it's launched. And whenever you are creating a new browser window, this is something that is the responsibility of the main process. Then a set of web-preference options becomes available to you. So, the browser window is created by using an Electron-specific API called Browser Window, which contains the browser window class. And inside the browser window, the web-preference options allow you to give certain features to your renderer process. For example, it is possible to control the use of developer tools. So, if you have a desktop application, you can see the developer tools, you can see, for example, the HTML code you have there. So, this can prove to be very useful if you're either trying to debug your program, or in my case, if I'm trying to identify a vulnerability. And it is also possible to change the value of sandbox option. So, by default, the sandbox option there is always false. Because otherwise, you would lose the desktop-like experience what Electron is trying to provide you with. So, you need to be able to interact with your system. However, if you, for some reason, decide to go and turn the sandbox option to true, it will be equal to having a sandbox of the Chrome browser. So, you lose the ability to interact with the system, as well as, for example, if the developer has made the decision, I'm having a static page, I don't need it. So, that's okay. However, if you, for example, need to traverse the file system, then that's a big no. You just can't do it. Otherwise, your application won't work. And then, as soon as you decide to enable the sandbox, this means you're going to automatically disable the Node.js engine. But as a separate option here, Node integration, which was what I was focusing on during this project, I'm going to demonstrate you how this option actually works. So, if I'm having a simple index.html file, so remember we had three files, right? And in index.html file, I have a script. I'm attempting to require the OS module, so my Node.js engine is turned on. And I'm requiring the module in order to ask further questions. What is the platform? What is the home directory of the machine on which my application is running up on? I want to display that information. So, if you take the script and you place it into a context where Node integration has been set to true, you get exactly what you asked for. However, if you place the same script into the conditions where your renderer process has Node integration set to false, then instead we are shown the reference error. You can't require anything anymore. So, maybe this was the case where developer was right. He wanted it that way. However, let's take the same script once more and place it in a super nice context. So, we are in the presence of an application which has a cross-site scripting vulnerability. And therefore, the attacker here is able to inject code. However, let's put this cross-site scripting vulnerability also to the context where Node integration is enabled. So, therefore, here, this transforms into code execution. So, that's what's been going on through the news for the past two weeks a lot. And, yeah, funnily enough, this is not all. So, if you see how the processes in election framework are created, then you will notice there's a lot of freedom. Because, yeah, for example, if you look at the process from task manager, you will see that renderer processes by default are created with Node integration always enabled. So, this is something that the framework is doing for you. But at the same time, when you don't need the Node, then you're in trouble. So, that made me have two assumptions here. I was assuming that in most cases, as web preference options are only optional, the developers won't go the extra mile and go and set it to false if they don't need it. And my second assumption here was that since we are having now web technologies in a desktop environment, so now these web developers coming to an environment where they have maybe never been. So, maybe they start feeling a bit more safe. Because, I mean, how can a cross-site scripting vulnerability actually exist on a desktop? So, yeah, based on those two assumptions, I got myself a goal. So, I wanted to know how often can I actually find a situation where the cross-site scripting vulnerability was my perfect match. So, with Node, right? And in order to do that, I went to GitHub, open source projects. I picked out 30 applications. I gathered some initial information on those applications because that was my first time using election. And I wanted to know how many browser window instances are actually created, what were the web preference options and their values, as well as if I can identify a cross-site scripting vulnerability from there. I mean, cross-site scripting vulnerability has been around since 90s. So, what are the odds? I mean, I wasn't born that time yet. So, yeah. So, what I gathered here was different information about the framework specific APIs which they required. What was the remote content that they wanted to introduce in their applications and then finally, options which was most interesting part. And what I saw here was that these 30 applications only required 16 out of the 56 framework specific APIs. So, that's not even a half. And if your node is enabled, you're going to have access to all of those. So, think about this as an attacker here. And the most valuable functionality here laid within the main process APIs. And quite often you can see from the renderer process, the remote module was used. So, this is the module that you can use to evoke functionality that is only available to the main process. So, you let main process do something for you, you get the results back and you're happy. When it came to remote content, these four ways what I tried to gather information on came from the official documentation of election. However, the suggested ways I found out weren't actually used that often. And the developers preferred to open any kind of remote content within the user's default browsers. So, maybe they felt a little bit more safe there. And in 10 applications, the content that they included was all served over HTTP. So, when it came to the web preference options, I actually here focused basically only on the node integration. And if you remember my assumptions, my assumptions were that these options would most likely be untouched. So, the 30 applications ended up creating 52 browser window instances. And in 41 cases, my assumption was correct. Nobody touched it. And in five cases, the developers went and changed, sorry, and set the value to true again just to be sure that I have these nodes there. Even though that was the default value. And then in six cases, the developers, I assumed they made the correct decision. We don't need it. Turn it off. So, based on these numbers, I actually had now 46, was it 46? Yeah. 46 chances to go and hunt for cross-site scripting vulnerabilities. So, what are the odds that I'm going to find one? At least one. So, instead, I ended up with 10. And the funny part here is that if you look a bit more closely, then the most popular election-based applications, obviously, are either markdown editors or node keeping applications. So, I guess we have a lot of nodes to keep. And basically, if you, well, I'm going to give you a golden rule here. If you're going to go to the election applications official page, you're going to see the applications that are advertised there. Pick one, try this, and you're going to have a code execution. So, how did these code executions actually look like? So, the first application, the Liano desktop application. That was a good case. Because Liano also has a web application. And if you have the desktop version on your machine, and in this case, this application was node sharing application. So, you have a bunch of friends using the same notebook. It's all about cooperation. So, you have a super nice friend who's going to create you a new node. Then this node is not vulnerable within the web application. We have really nice browsers these days. And as soon as you, as a victim, decide to synchronize the data to be displayed on your desktop application, you're going to have a bad time. So, how the attack vector here looks like? It's a nice picture. So, you have a nice friend. Your nice friend creates you a new node with an awesome title. Let me invite you to my birthday party. But behind that birthday party, there's a nice code execution. So, as soon as you synchronize the data, you will have everything from your machine. Then the script that I introduced here to the developers, what made them freak out was me creating a child process, which is actually so nice to help you with with their framework-specific APIs. And I used this to spawn a shell. And, yeah, voila! So, yeah, that was the end result. So, by the time you're displayed this nice alert, which I used to assure developers that the script actually was executed, I already had your ETC password file. So, then came the fruits of the hard labor I did here. So, I told the developers you have this nice vulnerability there, but I didn't get any answer. And, finally, when I did, the only answer was thank you, even though I hadn't even sent them a report yet. So, I guess they're not too eager to fix them. And, yeah, so, getting to the second example. I guess we're in a role here with the markdown editors. So, that was the case of Shiba. In Shiba's case, the attack factor was a little bit different, because you, as an attacker, would have to convince your victim to open a crafted MD file. And, in this case, I presented them a script similar to the one that I showed you in the last example. But, I'm going to show you how it would look like as a video, if I'm able to get it there. Tell me if you can see it. Can you? All right. And it's gone. So, basically, what happened here was me presenting two views of an attacker and a victim. If I'm opening a netcat on 1337, waiting for my connection back. So, the only thing victim needed to do here was to open application, get my birthday invite as a markdown file for some weird reason, and I'm having a reverse shell. So, I mean, if this is not the easiest reverse shell you've ever seen in a desktop application that I don't know what is. So, yeah, I can see it here. So, there's a bit tricky. Travel. Yeah, I'm going to travel. You sure? I don't think this will move, though. Bless you. Okay, this is weird. Yeah, this is weird. Okay. So, yeah, success. Okay. So, moving along with a editor. So, that was another case of a code execution, as you can imagine. And why I'm presenting this case here was the fun fact that it had a super nice project owner. So, I presented this vulnerability to the developer, and I got no response as usual, but a month later, I got this nice message in my inbox saying that the guy had actually given his project to another guy. So, now there was two projects with code execution in GitHub, including all the previous versions that were already vulnerable. So, then the new guy ended up getting the project. He had no idea the code execution was there. And once I told him, then there was this ticket change saying that help wanted. So, this new guy was pretty much in big trouble. And, yeah, so, the deal with desktop applications is once you download it, it's there. So, the chances you going to upgrade one, like with web application, you don't even notice. So, the vulnerable versions just remain to be there, even if one of the versions later gets fixed. So, and the last case, which came actually from last week out of my free time for fun. And this time, it was a markdown editor, which happened to be synchronizing the data from everywhere. All the cloud services ever know, Dropbox, OneNote, your name, it was there. So, that gives a lot of attack vectors to have that information later on your desktop. So, yeah, I mean, I don't know how nice that feels, but I don't think I'm going to use a markdown editor pretty soon, built an election. So, and, yeah, that's what I presented here, because, I mean, developers need to have some fun, too. And, but this was actually my best experience, because I got a response back in 36 minutes. By the next day, it was fixed and everybody were happy. So, that was a really good ending to the story. And the lessons learned or take away from myself or for you is, well, basically, if you go to this page that I suggested you to go to, you're going to have a lot of fun, but don't use stuff from there. And basically, if you give the person a chance not to do something, they're not going to do it. Like, never. And, yeah, it's a really good playing field. If you want to have a lot of golden findings, you're going to find them. I'll promise you. And some ideas, actually, that I was thinking about, maybe somebody will come up with better ideas. I'm not a developer. So, if you happen to have this match of cross-scripting vulnerability with node integration enabled. So, then you would instantly be able to access all the modules that the framework or node provides you. But what if you would be able to control what kind of modules you can use during the lifetime of the application? Let's see, from a configuration file. So, that, for me as an attacker, for example, that would limit the functionality that I'm able to use. So, maybe that could be useful in this case. And then the second thing. It would need an extra movement from the developers, but I would go the extra mile and set the node integration to false for obvious reasons. So, in the case you have a static page or you don't need to interact with the operating system, then it's going to be turned off. You don't really need to go and worry about it. But if something is not working, you can go and try. Okay. I'll switch it on. I'll see if it works. So, yeah. These are the two things that I would suggest here. And this is my way out. So, thank you.