1 00:00:00,120 --> 00:00:02,349 - This is gonna be Electrovolt, 2 00:00:02,349 --> 00:00:03,840 pwning popular desktop apps 3 00:00:03,840 --> 00:00:06,870 while uncovering new attack services on Electron. 4 00:00:06,870 --> 00:00:08,493 So, let's put it together. 5 00:00:09,438 --> 00:00:12,521 (audience applause) 6 00:00:16,140 --> 00:00:17,490 - Good afternoon, everyone. 7 00:00:17,490 --> 00:00:20,340 And thanks for coming to our talk. 8 00:00:20,340 --> 00:00:22,170 Let me ask you this. 9 00:00:22,170 --> 00:00:25,500 Have you ever wondered how secure it is 10 00:00:25,500 --> 00:00:28,680 to open a message within the desktop app 11 00:00:28,680 --> 00:00:31,263 you use to chat with your colleagues at work? 12 00:00:32,100 --> 00:00:35,370 Have you ever wondered how secure it is 13 00:00:35,370 --> 00:00:38,460 to open a source code which you just downloaded 14 00:00:38,460 --> 00:00:41,913 from the internet within your favorite source called editor? 15 00:00:42,930 --> 00:00:45,360 What do this Electron based desktop applications 16 00:00:45,360 --> 00:00:50,190 have in common, and how fundamentally secure are they? 17 00:00:50,190 --> 00:00:54,870 Before the year, we sat out to find an exact answer 18 00:00:54,870 --> 00:00:58,530 to discover what lurks beneath Electron applications. 19 00:00:58,530 --> 00:01:01,890 And throughout the course of one year of our research, 20 00:01:01,890 --> 00:01:04,620 we were able to find flaws in more 21 00:01:04,620 --> 00:01:09,620 than a dozen iconic applications used by millions of people 22 00:01:09,630 --> 00:01:13,440 and uncovered new attack surface within Electron. 23 00:01:13,440 --> 00:01:18,228 Hereby, I welcome everyone today to Electrovolt, 24 00:01:18,228 --> 00:01:20,610 where I will take you on a journey 25 00:01:20,610 --> 00:01:23,490 to pwn popular desktop applications 26 00:01:23,490 --> 00:01:26,790 while uncovering new attack surface on Electron. 27 00:01:26,790 --> 00:01:29,820 So for the agenda off of our talk, first of all, 28 00:01:29,820 --> 00:01:32,220 I will start with what is Electron 29 00:01:32,220 --> 00:01:34,290 and the basics of Electron. 30 00:01:34,290 --> 00:01:37,200 Then I will explain different security settings, 31 00:01:37,200 --> 00:01:39,150 which Electron provides. 32 00:01:39,150 --> 00:01:41,850 Then we will hack real world applications, 33 00:01:41,850 --> 00:01:43,800 starting from the least restrictive 34 00:01:43,800 --> 00:01:46,680 to the most restrictive settings. 35 00:01:46,680 --> 00:01:50,250 And then, I will disclose a novel flaw 36 00:01:50,250 --> 00:01:53,280 which we discovered within Electron JS framework. 37 00:01:53,280 --> 00:01:56,610 And at the end, I will end it with mitigations. 38 00:01:56,610 --> 00:01:58,323 So, let's get started. 39 00:01:59,850 --> 00:02:01,260 So who are we? 40 00:02:01,260 --> 00:02:04,770 I'm Aaditya Purani, AKA knapsstack. 41 00:02:04,770 --> 00:02:06,780 I'm a senior security engineer 42 00:02:06,780 --> 00:02:09,240 at a leading automotive company. 43 00:02:09,240 --> 00:02:12,780 My main areas of expertise are application security 44 00:02:12,780 --> 00:02:14,160 and blockchain. 45 00:02:14,160 --> 00:02:18,210 And on the weekend I play CTFs with perfect blue. 46 00:02:18,210 --> 00:02:23,210 Joining me today is my colleague, Max, AKA thegrandpew. 47 00:02:23,640 --> 00:02:27,060 Max is a security researcher at Assetnote, 48 00:02:27,060 --> 00:02:30,600 and he has expertise in application security and blockchain, 49 00:02:30,600 --> 00:02:34,170 and Max plays CTFs with Water Paddler. 50 00:02:34,170 --> 00:02:36,090 We have two other research member 51 00:02:36,090 --> 00:02:39,210 who are not able to join with us today on the stage, 52 00:02:39,210 --> 00:02:42,090 but I would like to introduce them as well. 53 00:02:42,090 --> 00:02:45,150 So we have Mohan AKA S1r1u5, 54 00:02:45,150 --> 00:02:49,170 who is a security auditor at Cure53. 55 00:02:49,170 --> 00:02:52,470 And we have William Bowling, AKA vakzz, 56 00:02:52,470 --> 00:02:56,280 who is a senior software developer at Biteable. 57 00:02:56,280 --> 00:02:58,140 So let's get started. 58 00:02:58,140 --> 00:03:00,210 So what is Electron? 59 00:03:00,210 --> 00:03:02,130 If you can build a website, 60 00:03:02,130 --> 00:03:04,680 then you can build a desktop application. 61 00:03:04,680 --> 00:03:07,920 That's the main concept behind Electron. 62 00:03:07,920 --> 00:03:11,490 Electron is a popular open source framework 63 00:03:11,490 --> 00:03:14,490 used by multiple iconic applications, 64 00:03:14,490 --> 00:03:19,490 such as Microsoft Teams, Discord, Slack, and others. 65 00:03:20,160 --> 00:03:24,600 Electron is built on top of Chromium and Node JS, 66 00:03:24,600 --> 00:03:29,600 which means that by just using HTML, JavaScript and CSS, 67 00:03:30,630 --> 00:03:33,930 you can ship an entirely cross platform, 68 00:03:33,930 --> 00:03:35,583 native desktop application. 69 00:03:36,540 --> 00:03:39,660 So before diving into the bugs, it is really important 70 00:03:39,660 --> 00:03:43,050 to understand the architecture of Electron. 71 00:03:43,050 --> 00:03:46,800 So for Electron, there are two types of processes. 72 00:03:46,800 --> 00:03:49,110 The first one is the main process 73 00:03:49,110 --> 00:03:52,710 and the second one is a renderer process. 74 00:03:52,710 --> 00:03:55,260 So main process is the starting point 75 00:03:55,260 --> 00:03:57,870 of all the Electron application. 76 00:03:57,870 --> 00:04:01,740 Main process can create multiple renderer process 77 00:04:01,740 --> 00:04:04,683 using a class known as browser window. 78 00:04:05,550 --> 00:04:08,250 On the other hand, we have renderer process, 79 00:04:08,250 --> 00:04:11,940 which is used to render webpages using Chromium. 80 00:04:11,940 --> 00:04:14,160 And as Chromium is used, 81 00:04:14,160 --> 00:04:18,030 a lot of Chromium related features are involved as well, 82 00:04:18,030 --> 00:04:23,030 such as Chrome multiple process, site isolation, and others. 83 00:04:23,370 --> 00:04:24,510 It is important to note 84 00:04:24,510 --> 00:04:27,060 that there can be only one main process, 85 00:04:27,060 --> 00:04:31,140 but there can be multiple renderer process. 86 00:04:31,140 --> 00:04:34,050 The way the main process and renderer process communicates 87 00:04:34,050 --> 00:04:36,750 with each other is through IPC 88 00:04:36,750 --> 00:04:39,660 or inter process communication module. 89 00:04:39,660 --> 00:04:42,500 As you can see in the diagram on the left side, 90 00:04:42,500 --> 00:04:44,850 we have a Node shared library. 91 00:04:44,850 --> 00:04:46,950 These are the Node primitives, 92 00:04:46,950 --> 00:04:49,590 which are provided to both the main process 93 00:04:49,590 --> 00:04:51,180 and the renderer process. 94 00:04:51,180 --> 00:04:54,780 And as it is not secure to provide Node primitives 95 00:04:54,780 --> 00:04:56,400 to the renderer process, 96 00:04:56,400 --> 00:05:00,210 we have something known as browser window web preferences 97 00:05:00,210 --> 00:05:03,060 or security settings to limit the exposure 98 00:05:03,060 --> 00:05:04,920 of Node primitives. 99 00:05:04,920 --> 00:05:08,220 So let's look how this all will look in a code. 100 00:05:08,220 --> 00:05:10,260 So here we have a main process. 101 00:05:10,260 --> 00:05:12,930 And first of all, we create a browser window 102 00:05:12,930 --> 00:05:14,850 with a multiple web preferences, 103 00:05:14,850 --> 00:05:16,740 which are security settings 104 00:05:16,740 --> 00:05:19,620 with either true or false Boolean value. 105 00:05:19,620 --> 00:05:23,100 Then we load a URL which is google.com. 106 00:05:23,100 --> 00:05:28,100 And then we define an IPC event listener known as open URL, 107 00:05:28,380 --> 00:05:31,710 which will listen for this open URL channel 108 00:05:31,710 --> 00:05:35,550 and invoke shell.openExternal with the argument. 109 00:05:35,550 --> 00:05:38,100 On the other side for the renderer process, 110 00:05:38,100 --> 00:05:40,530 it is divided into two parts. 111 00:05:40,530 --> 00:05:43,260 The first one is preload.js. 112 00:05:43,260 --> 00:05:46,020 And preload scripts contain code 113 00:05:46,020 --> 00:05:49,140 that is loaded prior to the web page. 114 00:05:49,140 --> 00:05:52,770 So this script run within the render context, 115 00:05:52,770 --> 00:05:57,630 but are granted more privileges by having access to Electron 116 00:05:57,630 --> 00:05:59,700 and Node JS APIs. 117 00:05:59,700 --> 00:06:03,454 So it can import a Node JS library here. 118 00:06:03,454 --> 00:06:05,940 ContextBridge which you see here, 119 00:06:05,940 --> 00:06:09,930 is a way to safely expose an API to the webpage, 120 00:06:09,930 --> 00:06:13,440 which can be later accessed using window object. 121 00:06:13,440 --> 00:06:15,330 So let's see how the web page would look like. 122 00:06:15,330 --> 00:06:17,820 So here we have a webpage for google.com, 123 00:06:17,820 --> 00:06:20,640 which was just loaded by the main earlier. 124 00:06:20,640 --> 00:06:22,440 And it's a Hello World webpage 125 00:06:22,440 --> 00:06:25,980 where it uses window.electron.open URL, 126 00:06:25,980 --> 00:06:28,860 and passes an argument to invoke that channel 127 00:06:28,860 --> 00:06:30,033 on the main process. 128 00:06:30,960 --> 00:06:34,080 So as we noticed in the main process, 129 00:06:34,080 --> 00:06:36,840 we can set multiple security settings 130 00:06:36,840 --> 00:06:40,770 to describe what type of render process we want. 131 00:06:40,770 --> 00:06:43,620 So, if the security setting is, for example, 132 00:06:43,620 --> 00:06:45,810 Node integration is true, 133 00:06:45,810 --> 00:06:48,780 and Sandbox and context isolation is false, 134 00:06:48,780 --> 00:06:51,750 then it is the most insecure you can get. 135 00:06:51,750 --> 00:06:55,290 In this case, XSS is equal to RC. 136 00:06:55,290 --> 00:06:57,783 So it's not a good idea to use this setting. 137 00:06:58,620 --> 00:07:01,140 Electron developers also thought about the same 138 00:07:01,140 --> 00:07:03,270 and they came up with a solution. 139 00:07:03,270 --> 00:07:05,910 And the solution was to introduce a new feature 140 00:07:05,910 --> 00:07:08,400 known as context isolation. 141 00:07:08,400 --> 00:07:10,170 So as you can see in this diagram, 142 00:07:10,170 --> 00:07:13,020 there is a slight change compared to the previous one. 143 00:07:13,020 --> 00:07:15,690 Now we have two different context. 144 00:07:15,690 --> 00:07:17,880 The first one is the application context. 145 00:07:17,880 --> 00:07:20,790 And the second one is an isolated context. 146 00:07:20,790 --> 00:07:23,370 So, application context is the space 147 00:07:23,370 --> 00:07:26,310 where your webpage JavaScript would run. 148 00:07:26,310 --> 00:07:29,790 Whereas the isolated context is where your preload 149 00:07:29,790 --> 00:07:33,450 and Electron's internal JavaScript code would run. 150 00:07:33,450 --> 00:07:37,530 So now we have a good segregation between that layers. 151 00:07:37,530 --> 00:07:39,420 So in this situation, 152 00:07:39,420 --> 00:07:43,290 the Node primitives are only exposed to the isolated context 153 00:07:43,290 --> 00:07:46,680 and are not reachable by the webpage. 154 00:07:46,680 --> 00:07:49,650 And this is a similar concept used by Chromium browser 155 00:07:49,650 --> 00:07:53,130 as well, where it is known as isolated world, 156 00:07:53,130 --> 00:07:56,400 where the extension, which you install in your browser, 157 00:07:56,400 --> 00:08:00,990 it's content JavaScript runs on a different side compared 158 00:08:00,990 --> 00:08:02,760 to the web application JavaScript. 159 00:08:02,760 --> 00:08:04,353 So there is an isolation there. 160 00:08:05,400 --> 00:08:07,170 So throughout our talk, 161 00:08:07,170 --> 00:08:10,500 the attack surface would be the renderer process. 162 00:08:10,500 --> 00:08:12,240 And we will start by abusing 163 00:08:12,240 --> 00:08:14,640 the least restrictive configuration 164 00:08:14,640 --> 00:08:17,373 and then move on to the complex exploits. 165 00:08:18,210 --> 00:08:20,550 So to keep the slides clean, 166 00:08:20,550 --> 00:08:23,640 let us keep following terminologies in mind. 167 00:08:23,640 --> 00:08:26,400 So I talked about Node integration, context isolation, 168 00:08:26,400 --> 00:08:28,890 and Sandbox, but don't worry right now 169 00:08:28,890 --> 00:08:30,570 about Node integration in workers 170 00:08:30,570 --> 00:08:32,550 and Node integration in subframes. 171 00:08:32,550 --> 00:08:35,160 I'll talk about it in the coming slides. 172 00:08:35,160 --> 00:08:38,130 So first situation, everything is red. 173 00:08:38,130 --> 00:08:39,840 Node integration is true. 174 00:08:39,840 --> 00:08:41,850 Context isolation is false. 175 00:08:41,850 --> 00:08:43,950 And Sandbox is false. 176 00:08:43,950 --> 00:08:47,460 In this case, it is very easy to get a shell 177 00:08:47,460 --> 00:08:50,580 as Node is directly exposed to the renderer. 178 00:08:50,580 --> 00:08:54,180 So a webpage can just do require shell process 179 00:08:54,180 --> 00:08:56,640 and exec their own shell command. 180 00:08:56,640 --> 00:08:59,250 So the only thing you need to do as an attacker 181 00:08:59,250 --> 00:09:01,530 is to find a way to embed your JavaScript 182 00:09:01,530 --> 00:09:02,583 within the webpage. 183 00:09:03,420 --> 00:09:07,590 So again, we return to our schematics and the circle, 184 00:09:07,590 --> 00:09:09,120 which is mentioned in the red, 185 00:09:09,120 --> 00:09:12,720 is the area which we are targeting at this point. 186 00:09:12,720 --> 00:09:16,770 So, let's take a look at a real world case study, 187 00:09:16,770 --> 00:09:19,680 where we were able to abuse this specific configuration 188 00:09:19,680 --> 00:09:21,570 to get RCE. 189 00:09:21,570 --> 00:09:24,810 So we will look at VS Code remote code execution, 190 00:09:24,810 --> 00:09:27,210 which bypasses the restricted mode. 191 00:09:27,210 --> 00:09:31,290 So VS Code is a very commonly used source code editor. 192 00:09:31,290 --> 00:09:34,679 And when you open a project within VS Code, 193 00:09:34,679 --> 00:09:37,260 it willl prompt you that, you wanna load this project 194 00:09:37,260 --> 00:09:41,130 in a restricted mode, or you wanna open it in unsafe mode? 195 00:09:41,130 --> 00:09:44,700 So this particular RCE which I'm about to demonstrate, 196 00:09:44,700 --> 00:09:48,810 will work on restricted mode of a VS Code. 197 00:09:48,810 --> 00:09:52,860 So the bug here is we were able to find an XSS 198 00:09:52,860 --> 00:09:57,270 in Markdown, which was subjected to very strict CSP 199 00:09:57,270 --> 00:09:58,530 and Electron policy. 200 00:09:58,530 --> 00:10:02,160 And we were able to chain it with multiple bugs 201 00:10:02,160 --> 00:10:05,760 to get an RCE on an insecure window. 202 00:10:05,760 --> 00:10:08,010 So let's see how this works. 203 00:10:08,010 --> 00:10:13,010 So, this diagram is the entire exploit chain for VS Code. 204 00:10:13,890 --> 00:10:17,130 And here you can see three squares, 205 00:10:17,130 --> 00:10:19,050 which I marked with different color. 206 00:10:19,050 --> 00:10:22,200 So there is one with green, orange and red. 207 00:10:22,200 --> 00:10:24,660 So the square which is marked in green, 208 00:10:24,660 --> 00:10:28,110 is running with the most tight Electron configuration, 209 00:10:28,110 --> 00:10:29,520 which is the most secure. 210 00:10:29,520 --> 00:10:34,200 And our goal is to somehow go from that green to red. 211 00:10:34,200 --> 00:10:36,180 The red one is the one which is running 212 00:10:36,180 --> 00:10:37,710 with Node integration: true, 213 00:10:37,710 --> 00:10:39,660 which is the most insecure configuration, 214 00:10:39,660 --> 00:10:41,640 which I talked about earlier. 215 00:10:41,640 --> 00:10:43,200 So how do we do that? 216 00:10:43,200 --> 00:10:45,870 So if you know on VS Code when you open a project, 217 00:10:45,870 --> 00:10:49,980 and when you load a Markdown, it is not rendered by default. 218 00:10:49,980 --> 00:10:52,920 So first of all, you need to create a malicious project 219 00:10:52,920 --> 00:10:55,950 and create a folder known as .VS Code. 220 00:10:55,950 --> 00:10:59,340 Within this folder, you can create a JSON file, 221 00:10:59,340 --> 00:11:01,290 which is settings.json, 222 00:11:01,290 --> 00:11:04,380 and you can enable Markdown previewer. 223 00:11:04,380 --> 00:11:06,450 So as soon as this project will load, 224 00:11:06,450 --> 00:11:08,970 it will not just put a code block, 225 00:11:08,970 --> 00:11:11,460 but it will render the Markdown. 226 00:11:11,460 --> 00:11:13,470 So once a Markdown is rendered, 227 00:11:13,470 --> 00:11:17,010 you can put your own JavaScript to get accesses, 228 00:11:17,010 --> 00:11:20,430 but in the first window, the Markdown preview window, 229 00:11:20,430 --> 00:11:23,490 it is subject to a very strict CSP policy 230 00:11:23,490 --> 00:11:26,430 where on the script tags, it is subject to nonce. 231 00:11:26,430 --> 00:11:29,250 So unless there is a way to leak a nonce, 232 00:11:29,250 --> 00:11:31,530 we cannot embed a script tag. 233 00:11:31,530 --> 00:11:35,576 So what we did here is, we performed a meta redirect, 234 00:11:35,576 --> 00:11:38,190 which is a way to redirect to an external site 235 00:11:38,190 --> 00:11:39,600 within the Markdown. 236 00:11:39,600 --> 00:11:42,000 And once it redirects to our own site, 237 00:11:42,000 --> 00:11:44,490 it is not subject to that CSP policy. 238 00:11:44,490 --> 00:11:47,220 So we can run arbitrary JavaScript. 239 00:11:47,220 --> 00:11:50,400 We also use an attack known as excess leak 240 00:11:50,400 --> 00:11:52,890 in order to leak the origin of where 241 00:11:52,890 --> 00:11:55,650 this excess execution was happening. 242 00:11:55,650 --> 00:12:00,630 And this leak provide us access to extension ID of VS Code. 243 00:12:00,630 --> 00:12:02,280 So if you have used VS Code, 244 00:12:02,280 --> 00:12:05,430 there are multiple extensions you can install. 245 00:12:05,430 --> 00:12:08,880 And this extensions come with their own unique identifier, 246 00:12:08,880 --> 00:12:11,580 which is a guid-string, which is not guessable. 247 00:12:11,580 --> 00:12:12,840 So we need to leak it. 248 00:12:12,840 --> 00:12:15,390 So we leak that in the step number one. 249 00:12:15,390 --> 00:12:19,950 And step number two, as we land on attacker.com website, 250 00:12:19,950 --> 00:12:24,390 we can get an XSS on the second protocol frame, 251 00:12:24,390 --> 00:12:26,520 which is VS Code web view. 252 00:12:26,520 --> 00:12:28,620 So that is an XSS vulnerability 253 00:12:28,620 --> 00:12:32,340 within the extension VS Code web view protocol frame. 254 00:12:32,340 --> 00:12:37,340 And we use this XSS to make another post message 255 00:12:37,350 --> 00:12:41,160 to the top layer protocol frame, which is VS Code file. 256 00:12:41,160 --> 00:12:44,460 So we send a post message known as channel: do read. 257 00:12:44,460 --> 00:12:46,470 And what this will give us the response is, 258 00:12:46,470 --> 00:12:48,930 it will give you the user directory 259 00:12:48,930 --> 00:12:50,670 where this project is running for. 260 00:12:50,670 --> 00:12:53,340 And this is important for the reliability of the exploit, 261 00:12:53,340 --> 00:12:56,640 because you need to know where the user has downloaded it 262 00:12:56,640 --> 00:13:00,330 on their file system to perform further exploitation. 263 00:13:00,330 --> 00:13:03,540 So once you leak this user directory, what you can do is, 264 00:13:03,540 --> 00:13:08,010 you can perform a redirection to VS Code file protocol, 265 00:13:08,010 --> 00:13:10,620 which works similar to file protocol. 266 00:13:10,620 --> 00:13:14,490 Like if you have used file ITC password to read a file. 267 00:13:14,490 --> 00:13:17,910 But the catch here is this protocol can be invoked 268 00:13:17,910 --> 00:13:21,840 from any origin unlike the traditional file protocol. 269 00:13:21,840 --> 00:13:23,140 So what we do is, 270 00:13:23,140 --> 00:13:28,020 we do an attack which is VS Code-file:// 271 00:13:28,020 --> 00:13:31,650 and then we perform part reversal with ../ 272 00:13:31,650 --> 00:13:33,420 and append this directory 273 00:13:33,420 --> 00:13:36,660 which we have already leaked earlier in the previous step. 274 00:13:36,660 --> 00:13:39,810 And then we render an HTML page, 275 00:13:39,810 --> 00:13:42,900 which does stop.require shell process, 276 00:13:42,900 --> 00:13:44,520 and get access to the Node module, 277 00:13:44,520 --> 00:13:46,530 because that is a window which is running 278 00:13:46,530 --> 00:13:48,330 with Node integration: true. 279 00:13:48,330 --> 00:13:51,270 So let's see how this exploit would look like in real world. 280 00:13:51,270 --> 00:13:53,670 So the victim has opened VS Code here, 281 00:13:53,670 --> 00:13:56,673 and now they will try to open our Markdown. 282 00:14:02,910 --> 00:14:05,850 And as you can see, our calc is popped, 283 00:14:05,850 --> 00:14:10,850 and that is our demo for the VS Code remote code execution. 284 00:14:11,060 --> 00:14:14,143 (audience clapping) 285 00:14:17,820 --> 00:14:20,910 So we received a bounty for $6,000 286 00:14:20,910 --> 00:14:24,510 from Microsoft for this remote code execution bug. 287 00:14:24,510 --> 00:14:27,660 And the main takeaway is that if you're a developer 288 00:14:27,660 --> 00:14:30,960 for an Electron app, it is important to consider 289 00:14:30,960 --> 00:14:33,930 all your Windows as a part of the threat model 290 00:14:33,930 --> 00:14:37,080 and apply the most restrictive settings on all of them, 291 00:14:37,080 --> 00:14:40,860 rather than just one of them or two of them. 292 00:14:40,860 --> 00:14:42,720 So, let's switch gears a bit 293 00:14:42,720 --> 00:14:45,690 and increase the restrictiveness a bit more. 294 00:14:45,690 --> 00:14:49,350 So here, we have context isolation is true. 295 00:14:49,350 --> 00:14:51,600 And as context isolation is enabled, 296 00:14:51,600 --> 00:14:54,570 Node is not directly available to the renderer. 297 00:14:54,570 --> 00:14:57,030 So we cannot use an exploit like the previous case 298 00:14:57,030 --> 00:14:59,820 where we just require a Node library. 299 00:14:59,820 --> 00:15:02,580 So there are two ways to exploit this situation. 300 00:15:02,580 --> 00:15:05,910 So as you noticed here, Sandbox is false. 301 00:15:05,910 --> 00:15:09,510 So we can use a Chrome V8 renderer exploit. 302 00:15:09,510 --> 00:15:12,930 So you can go to CR bug, find a crash proof of concept 303 00:15:12,930 --> 00:15:17,070 or a full blown Chrome end it and run it. 304 00:15:17,070 --> 00:15:20,790 Or you can find a way to disable context isolation somehow. 305 00:15:20,790 --> 00:15:24,180 And that I will show you how we did in the coming slides. 306 00:15:24,180 --> 00:15:25,740 So within our diagram, 307 00:15:25,740 --> 00:15:28,230 now we have two different separate context. 308 00:15:28,230 --> 00:15:30,510 XSS is on the application side, 309 00:15:30,510 --> 00:15:33,150 and the Node and Electron API resides 310 00:15:33,150 --> 00:15:34,590 on the isolated context. 311 00:15:34,590 --> 00:15:37,263 So there is enough segregation at this point. 312 00:15:38,310 --> 00:15:42,270 So case study two, we will talk about Discord RCE. 313 00:15:42,270 --> 00:15:46,560 So Discord was using Electron version 12.14.1, 314 00:15:46,560 --> 00:15:48,630 which was an older version when we tested 315 00:15:48,630 --> 00:15:50,490 on the latest test Discord version. 316 00:15:50,490 --> 00:15:53,100 But it also means that it is indirectly using 317 00:15:53,100 --> 00:15:56,910 an older version of Chrome, which is Chrome 83. 318 00:15:56,910 --> 00:16:00,630 We found XSS in one of the video embedded in Discord. 319 00:16:00,630 --> 00:16:02,160 So if you have used Discord, 320 00:16:02,160 --> 00:16:06,030 when you chat with someone and you send them a YouTube link, 321 00:16:06,030 --> 00:16:09,060 it will expand and someone can click on that link 322 00:16:09,060 --> 00:16:12,450 and just watch it within Discord the YouTube video, 323 00:16:12,450 --> 00:16:14,610 rather than going to the YouTube website. 324 00:16:14,610 --> 00:16:17,700 So we were looking embeds to figure out 325 00:16:17,700 --> 00:16:19,860 what sort of vulnerable embeds we can find. 326 00:16:19,860 --> 00:16:22,890 And we were able to get XSS in Vimio, 327 00:16:22,890 --> 00:16:26,850 which is another famous video sharing service. 328 00:16:26,850 --> 00:16:31,290 And we exploited this XSS and perform other attack. 329 00:16:31,290 --> 00:16:35,280 But the problem here is that Iframes are embed 330 00:16:35,280 --> 00:16:38,160 in Electron as Sandbox by default. 331 00:16:38,160 --> 00:16:40,620 So we cannot just simply run a V8 exploit 332 00:16:40,620 --> 00:16:42,720 and perform our exploitation. 333 00:16:42,720 --> 00:16:43,800 So what we did is, 334 00:16:43,800 --> 00:16:46,740 we dig deeper into the Discord source code, 335 00:16:46,740 --> 00:16:50,070 and we abused Electron misconfiguration 336 00:16:50,070 --> 00:16:53,670 to open new window using window.open. 337 00:16:53,670 --> 00:16:58,290 And this new window was loaded with Sandbox disabled. 338 00:16:58,290 --> 00:17:01,770 And now, we can easily navigate to the attacker site 339 00:17:01,770 --> 00:17:03,870 and run our Chrome V8 exploit. 340 00:17:03,870 --> 00:17:06,120 So let's see Discord RCE. 341 00:17:06,120 --> 00:17:10,593 So the malicious actor is gonna send a URL to the victim, 342 00:17:11,460 --> 00:17:14,343 and victim will try to interact with the URL. 343 00:17:22,020 --> 00:17:23,850 And as you can see, a new window has opened. 344 00:17:23,850 --> 00:17:25,590 This is without Sandbox. 345 00:17:25,590 --> 00:17:29,220 And we have this Sandbox payload here, 346 00:17:29,220 --> 00:17:30,723 which is gonna pop a calc. 347 00:17:37,049 --> 00:17:40,132 (audience clapping) 348 00:17:44,100 --> 00:17:46,800 So we were awarded around $5,000 bounty 349 00:17:46,800 --> 00:17:48,540 for this bug in Discord. 350 00:17:48,540 --> 00:17:50,520 And Discord fixed it by upgrading 351 00:17:50,520 --> 00:17:52,500 to the latest Electron version, 352 00:17:52,500 --> 00:17:55,980 and also fixed this new window opener bug. 353 00:17:55,980 --> 00:17:57,750 So next time when it opens a window, 354 00:17:57,750 --> 00:18:00,930 it will be open with a Sandbox enable. 355 00:18:00,930 --> 00:18:03,300 And most of you might be knowing about this issue 356 00:18:03,300 --> 00:18:06,510 of running a renderer exploit to exploit Electron apps. 357 00:18:06,510 --> 00:18:09,510 But what I'm showing you is that it is really common 358 00:18:09,510 --> 00:18:13,920 to have this in real world Electron applications. 359 00:18:13,920 --> 00:18:18,920 So for our next case, we have Node integration to false. 360 00:18:19,050 --> 00:18:21,390 Sandbox is true in this case. 361 00:18:21,390 --> 00:18:24,690 But this time, the context isolation is false. 362 00:18:24,690 --> 00:18:26,550 So as Sandbox is true, 363 00:18:26,550 --> 00:18:29,160 Sandbox is enabled on the renderer process. 364 00:18:29,160 --> 00:18:31,890 So we get the protection of Chrome Sandbox, 365 00:18:31,890 --> 00:18:34,110 which uses seccomp on Linux, 366 00:18:34,110 --> 00:18:37,440 or win132K lockdown on Windows. 367 00:18:37,440 --> 00:18:39,960 So no Node modules are exposing the renderer 368 00:18:39,960 --> 00:18:42,930 because Node integration is set to false. 369 00:18:42,930 --> 00:18:47,070 But now as context isolation is disabled, 370 00:18:47,070 --> 00:18:50,250 there is no isolation between the website you load 371 00:18:50,250 --> 00:18:53,280 and Electron's internal or preload code. 372 00:18:53,280 --> 00:18:55,560 And let's see what I mean by that. 373 00:18:55,560 --> 00:18:57,480 So in the diagram here, 374 00:18:57,480 --> 00:18:59,910 previously we had two separate context, 375 00:18:59,910 --> 00:19:02,820 but now the Electron's internal code, 376 00:19:02,820 --> 00:19:07,820 preload, and application all run within one single context. 377 00:19:08,100 --> 00:19:12,000 So what can we do here because Electron's internal code 378 00:19:12,000 --> 00:19:14,250 is running JavaScript as well? 379 00:19:14,250 --> 00:19:17,040 So can we do something like prototype pollution 380 00:19:17,040 --> 00:19:19,920 and override certain JavaScript function? 381 00:19:19,920 --> 00:19:21,030 Let's see. 382 00:19:21,030 --> 00:19:23,010 So how to get a shell. 383 00:19:23,010 --> 00:19:26,550 So if Electron version less than 10 is used, 384 00:19:26,550 --> 00:19:28,800 then you can use a prototype pollution gadget 385 00:19:28,800 --> 00:19:31,023 to leak remote or IPC model. 386 00:19:31,920 --> 00:19:34,740 So according to Electron documentation, 387 00:19:34,740 --> 00:19:38,460 remote module is used to bridge JavaScript objects 388 00:19:38,460 --> 00:19:41,340 from the main process to the renderer process. 389 00:19:41,340 --> 00:19:45,540 So, when you leak a remote module even in a Sandbox window, 390 00:19:45,540 --> 00:19:47,763 you will get access to Node primitives. 391 00:19:48,750 --> 00:19:51,150 From Electron version 10 to 14, 392 00:19:51,150 --> 00:19:53,520 Electron developers thought that remote module 393 00:19:53,520 --> 00:19:55,470 is a very dangerous feature. 394 00:19:55,470 --> 00:19:59,250 So they switched its default value to false, 395 00:19:59,250 --> 00:20:03,030 but developer can still go out of their way and enable it. 396 00:20:03,030 --> 00:20:04,380 So you can do the same. 397 00:20:04,380 --> 00:20:07,530 You can use prototype pollution to leak remote or IPC. 398 00:20:07,530 --> 00:20:10,860 And most of the time remote module is disabled 399 00:20:10,860 --> 00:20:14,040 because developer do not do that in this common apps. 400 00:20:14,040 --> 00:20:17,340 So you need to find some sort of IPC misconfiguration 401 00:20:17,340 --> 00:20:18,663 to leverage it to RCE. 402 00:20:19,590 --> 00:20:21,360 Let's look at the third case. 403 00:20:21,360 --> 00:20:23,850 So Electron version greater than 14, 404 00:20:23,850 --> 00:20:26,910 which are the newly Electron versions, 405 00:20:26,910 --> 00:20:29,880 in this case, remote is completely deprecated. 406 00:20:29,880 --> 00:20:32,130 So there is no feature called remote, 407 00:20:32,130 --> 00:20:35,430 but developers can still do an NPM install, 408 00:20:35,430 --> 00:20:38,100 Electron/remote to install it, 409 00:20:38,100 --> 00:20:41,010 but it is really uncommon to see that. 410 00:20:41,010 --> 00:20:44,130 So what we do here is we leak IPC module. 411 00:20:44,130 --> 00:20:47,460 And our goal is to find an IPC misconfiguration 412 00:20:47,460 --> 00:20:49,620 within developer defined IPC channel, 413 00:20:49,620 --> 00:20:51,420 like open URL which we saw 414 00:20:51,420 --> 00:20:54,600 or Electron's internal IPC channel. 415 00:20:54,600 --> 00:20:57,570 So this is the novel prototype pollution gadget 416 00:20:57,570 --> 00:21:00,690 we discovered for the latest Electron version. 417 00:21:00,690 --> 00:21:02,730 And the concept of prototype pollution 418 00:21:02,730 --> 00:21:04,560 on context disable window 419 00:21:04,560 --> 00:21:08,790 was first proposed by Masato Kinugawa in 2018, 420 00:21:08,790 --> 00:21:12,210 but that exploit was working on the older Electron version. 421 00:21:12,210 --> 00:21:15,210 And this one would work even on the latest one. 422 00:21:15,210 --> 00:21:16,770 So what this exploit does, 423 00:21:16,770 --> 00:21:20,850 I override certain JavaScript inbuilt properties 424 00:21:20,850 --> 00:21:23,280 like EndsWith EndCall. 425 00:21:23,280 --> 00:21:26,520 And on number three, I get access to webpack.require, 426 00:21:26,520 --> 00:21:29,700 which contains all this Node Electron modules 427 00:21:29,700 --> 00:21:33,390 which you can use to pop a calc in your favorite apps. 428 00:21:33,390 --> 00:21:36,210 So for a situation where Sandbox is false 429 00:21:36,210 --> 00:21:38,400 and context isolation is false, 430 00:21:38,400 --> 00:21:41,520 you may be wondering why not just run a V8 exploit. 431 00:21:41,520 --> 00:21:45,570 But with prototype pollution or with webpack.require, 432 00:21:45,570 --> 00:21:47,820 you get access to Node primitives, 433 00:21:47,820 --> 00:21:50,550 and you get access to Electron common API, 434 00:21:50,550 --> 00:21:53,010 which can be easily used to pop a calc. 435 00:21:53,010 --> 00:21:55,950 So the benefit for using a prototype pollution compared 436 00:21:55,950 --> 00:21:59,520 to a V8 exploit is that here you don't require 437 00:21:59,520 --> 00:22:01,530 any binary exploitation skill. 438 00:22:01,530 --> 00:22:04,110 It is a complete web attack. 439 00:22:04,110 --> 00:22:05,070 The second one is, 440 00:22:05,070 --> 00:22:08,130 it is more reliable compared to for example, a V8 exploit, 441 00:22:08,130 --> 00:22:12,420 which can be more of hip massaging in certain cases. 442 00:22:12,420 --> 00:22:13,253 And the third one is, 443 00:22:13,253 --> 00:22:15,870 what if the app which you are targeting 444 00:22:15,870 --> 00:22:18,810 is using a very late test Electron version, 445 00:22:18,810 --> 00:22:21,930 which doesn't have any Chrome end within the patch gap? 446 00:22:21,930 --> 00:22:23,700 So this will be helpful. 447 00:22:23,700 --> 00:22:27,360 But let's return to our original case where Sandbox is true. 448 00:22:27,360 --> 00:22:29,100 Let's see what we can leak. 449 00:22:29,100 --> 00:22:32,120 So in this case, we don't have access to Node 450 00:22:32,120 --> 00:22:35,580 or Electron common APIs like previously, 451 00:22:35,580 --> 00:22:37,140 but what we can do is, 452 00:22:37,140 --> 00:22:41,220 we can leak Electron's internal IPC bindings. 453 00:22:41,220 --> 00:22:45,390 For example, IPC renderer and IPC renderer internal. 454 00:22:45,390 --> 00:22:47,610 So the IPC renderer is used 455 00:22:47,610 --> 00:22:50,190 to invoke developer defined channels. 456 00:22:50,190 --> 00:22:52,410 Whereas IPC render internal 457 00:22:52,410 --> 00:22:56,610 is used to invoke Electrons internally defined channels. 458 00:22:56,610 --> 00:22:59,370 So let's see how we use in a real world app. 459 00:22:59,370 --> 00:23:00,900 So, what I'm gonna talk about 460 00:23:00,900 --> 00:23:03,750 is a local file read in Microsoft Teams, 461 00:23:03,750 --> 00:23:05,460 which leads to account takeover. 462 00:23:05,460 --> 00:23:07,350 So Microsoft Team was using 463 00:23:07,350 --> 00:23:09,153 an Electron version less than 15. 464 00:23:10,110 --> 00:23:14,580 We found an XSS in renderer using a 0day in CKEditor, 465 00:23:14,580 --> 00:23:18,840 which is used for rich text formatting for Markdown. 466 00:23:18,840 --> 00:23:20,490 And what we noticed is, 467 00:23:20,490 --> 00:23:23,730 when you create a new window similar to Discord, 468 00:23:23,730 --> 00:23:28,290 context isolation is disabled and Sandbox will be enabled. 469 00:23:28,290 --> 00:23:30,750 So as context isolation is disabled, 470 00:23:30,750 --> 00:23:34,170 what we can do is run the prototype pollution gadget, 471 00:23:34,170 --> 00:23:36,900 leak the IPC using XSS. 472 00:23:36,900 --> 00:23:39,810 So once we leak this IPC bindings, 473 00:23:39,810 --> 00:23:42,510 we were not able to find any misconfiguration 474 00:23:42,510 --> 00:23:45,840 within developer defined IPC in Microsoft Teams. 475 00:23:45,840 --> 00:23:48,810 But we were able to notice a misconfiguration 476 00:23:48,810 --> 00:23:51,180 in Electron's internal IPC. 477 00:23:51,180 --> 00:23:53,430 So Electron has this IPC channel 478 00:23:53,430 --> 00:23:56,940 known as native image create thumbnail from path, 479 00:23:56,940 --> 00:23:59,940 which takes a path and reads that file 480 00:23:59,940 --> 00:24:01,500 and gives you an output. 481 00:24:01,500 --> 00:24:04,890 Think of it as a local file inclusion or local file read. 482 00:24:04,890 --> 00:24:07,620 So what we were able to do is in Microsoft Teams, 483 00:24:07,620 --> 00:24:10,650 we were able to read desktopconfig.json, 484 00:24:10,650 --> 00:24:12,900 which contains user specific property, 485 00:24:12,900 --> 00:24:15,450 including the JWT token of the user. 486 00:24:15,450 --> 00:24:17,700 So let's see how the exploit would look like. 487 00:24:25,620 --> 00:24:28,050 So here text access is triggered. 488 00:24:28,050 --> 00:24:30,150 And as you can see on the attacker's website, 489 00:24:30,150 --> 00:24:32,940 they have access to desktopconfig.json. 490 00:24:32,940 --> 00:24:34,380 It is a bit small to read, 491 00:24:34,380 --> 00:24:36,120 but this is the content of the file 492 00:24:36,120 --> 00:24:38,790 which contains the access token of the users. 493 00:24:38,790 --> 00:24:39,660 And with that, 494 00:24:39,660 --> 00:24:43,083 they can compromise the victims' Microsoft Teams' account. 495 00:24:44,731 --> 00:24:47,814 (audience clapping) 496 00:24:52,140 --> 00:24:56,103 So we received $3,000 bounty from Microsoft for this issue. 497 00:24:56,970 --> 00:24:59,340 Let's move on to the last scenario 498 00:24:59,340 --> 00:25:00,870 where everything is green. 499 00:25:00,870 --> 00:25:05,190 So this type of app runs with the most secure settings, 500 00:25:05,190 --> 00:25:07,410 and it is used by most of the application. 501 00:25:07,410 --> 00:25:09,060 So Node integration is false. 502 00:25:09,060 --> 00:25:12,570 So you cannot get Node primitives directly on the webpage. 503 00:25:12,570 --> 00:25:15,930 IPC cannot be leaked because context isolation is enabled 504 00:25:15,930 --> 00:25:18,000 and it is fully Sandboxed. 505 00:25:18,000 --> 00:25:22,230 So to hack this is the main part of our research. 506 00:25:22,230 --> 00:25:26,260 So in the diagram, we are right now in the Sandbox renderer, 507 00:25:26,260 --> 00:25:28,830 and this is the most safest configuration possible 508 00:25:28,830 --> 00:25:29,793 in Electron today. 509 00:25:30,690 --> 00:25:33,690 So at this point, you might be wondering that in this case, 510 00:25:33,690 --> 00:25:38,220 XSS in an Electron app would be same as XSS in a browser. 511 00:25:38,220 --> 00:25:40,710 And the answer to that is, no. 512 00:25:40,710 --> 00:25:44,250 The reason is that Electron apps are not same 513 00:25:44,250 --> 00:25:47,460 as your day to day use Chromium browser. 514 00:25:47,460 --> 00:25:52,460 Electron app is a combination of Electron native C++ code 515 00:25:52,860 --> 00:25:54,600 and Chromium code. 516 00:25:54,600 --> 00:25:59,600 So can we somehow find a way to abuse this intersection 517 00:25:59,700 --> 00:26:01,650 between Chrome and Electron, 518 00:26:01,650 --> 00:26:04,860 and subvert all the security features possible? 519 00:26:04,860 --> 00:26:06,210 Let's see. 520 00:26:06,210 --> 00:26:09,386 So we move on to enabling nodeIntegrationInSubFrames 521 00:26:09,386 --> 00:26:11,190 from a compromised renderer, 522 00:26:11,190 --> 00:26:14,130 which is a CVE which was assigned to our findings. 523 00:26:14,130 --> 00:26:15,270 So let's first talk about 524 00:26:15,270 --> 00:26:17,640 what is nodeIntegrationInSubFrames? 525 00:26:17,640 --> 00:26:22,380 So let's say you have a webpage which is called example.com. 526 00:26:22,380 --> 00:26:26,160 And within this webpage, you create multiple Iframes 527 00:26:26,160 --> 00:26:28,200 to load another webpage. 528 00:26:28,200 --> 00:26:32,370 Now let's say, if you want to provide this Iframe access 529 00:26:32,370 --> 00:26:36,030 to Node primitives or pre-load APIs, 530 00:26:36,030 --> 00:26:37,830 then how would you do it? 531 00:26:37,830 --> 00:26:39,270 The answer to that is, 532 00:26:39,270 --> 00:26:42,540 enable a feature known as nodeIntegrationInSubFrames. 533 00:26:42,540 --> 00:26:44,640 So once you enable this feature, 534 00:26:44,640 --> 00:26:47,610 all your child windows or subframes 535 00:26:47,610 --> 00:26:49,560 will have access to Node primitives 536 00:26:49,560 --> 00:26:52,740 or contextBridge exposed API. 537 00:26:52,740 --> 00:26:57,300 So for every sub frame if your parent page example.com, 538 00:26:57,300 --> 00:27:01,230 has Node integration enabled and Sandbox disabled, 539 00:27:01,230 --> 00:27:03,510 then Node JS primitives will be available 540 00:27:03,510 --> 00:27:05,490 within your Iframes. 541 00:27:05,490 --> 00:27:07,560 If Node integration is disabled, 542 00:27:07,560 --> 00:27:10,830 and Sandbox it doesn't matter enabled or disabled, 543 00:27:10,830 --> 00:27:13,983 then all your preload or contextBridge exposed API 544 00:27:13,983 --> 00:27:16,410 will load within the Iframe. 545 00:27:16,410 --> 00:27:19,290 Let's take a look in the code to understand it a bit more. 546 00:27:19,290 --> 00:27:20,820 So main process, 547 00:27:20,820 --> 00:27:24,000 here we have nodeIntegrationInSubFrames set to false. 548 00:27:24,000 --> 00:27:26,580 Renderer process, we define open URL channel, 549 00:27:26,580 --> 00:27:28,620 just like the first example. 550 00:27:28,620 --> 00:27:32,160 And this is our main window, which is google.com. 551 00:27:32,160 --> 00:27:36,750 What it does, it creates an Iframe with a URL pwn.af, 552 00:27:36,750 --> 00:27:40,020 and then it access window.electron.open URL. 553 00:27:40,020 --> 00:27:40,980 That's fine. 554 00:27:40,980 --> 00:27:44,430 But when you try to access window.electron.open URL 555 00:27:44,430 --> 00:27:47,400 from the Iframe, it's gonna throw an error. 556 00:27:47,400 --> 00:27:48,233 Why? 557 00:27:48,233 --> 00:27:51,030 Because nodeIntegrationInSubFrames is disabled. 558 00:27:51,030 --> 00:27:55,470 This case, let's turn it to true and let's see what happens. 559 00:27:55,470 --> 00:27:57,990 So here, Iframe will have access 560 00:27:57,990 --> 00:28:02,040 to that contextBridge exposed or preload APIs, 561 00:28:02,040 --> 00:28:05,010 and is able to invoke it successfully. 562 00:28:05,010 --> 00:28:08,460 So most of the time when we get XSS in all these apps, 563 00:28:08,460 --> 00:28:10,470 it is usually in embeds. 564 00:28:10,470 --> 00:28:12,600 So for example, if you saw with Discord, 565 00:28:12,600 --> 00:28:15,030 we had an XSS in Vimeo embed. 566 00:28:15,030 --> 00:28:18,000 And in this case, a Node integration in subframes 567 00:28:18,000 --> 00:28:21,240 is mostly disable because developers, again, 568 00:28:21,240 --> 00:28:23,730 do not go out of their way to enable it. 569 00:28:23,730 --> 00:28:27,030 So, it's a bit sad because you don't now have access 570 00:28:27,030 --> 00:28:29,400 to contextBridge exposed API. 571 00:28:29,400 --> 00:28:30,990 So what can we do here? 572 00:28:30,990 --> 00:28:32,310 Can we still hack it? 573 00:28:32,310 --> 00:28:33,720 Let's see. 574 00:28:33,720 --> 00:28:35,100 So let's take a deep dive 575 00:28:35,100 --> 00:28:38,760 into how nodeIntegrationInSubFrames is enabled in Electron. 576 00:28:38,760 --> 00:28:42,090 So Electron patches blink web reference 577 00:28:42,090 --> 00:28:44,400 and add security featured flags. 578 00:28:44,400 --> 00:28:47,730 For example, it implements nodeIntegrationInSubFrames 579 00:28:47,730 --> 00:28:50,040 by patching this file. 580 00:28:50,040 --> 00:28:52,680 And this is the code where that anti logic 581 00:28:52,680 --> 00:28:55,950 of enabling and disabling a feature takes place. 582 00:28:55,950 --> 00:28:59,700 So if you're able to read or not, there is a file, 583 00:28:59,700 --> 00:29:04,260 which is under a directory known as shell/renderer. 584 00:29:04,260 --> 00:29:06,630 It's renderer folder. 585 00:29:06,630 --> 00:29:10,410 And this file contains a code in which the area marked 586 00:29:10,410 --> 00:29:13,170 as read has something like renderer frame, 587 00:29:13,170 --> 00:29:16,830 where it gets access to blink web preferences 588 00:29:16,830 --> 00:29:19,140 and then access like a property, 589 00:29:19,140 --> 00:29:21,240 which is nodeIntegrationInSubFrames. 590 00:29:21,240 --> 00:29:24,390 And based on the value of it, one or zero, 591 00:29:24,390 --> 00:29:26,910 it's gonna enable or disable it. 592 00:29:26,910 --> 00:29:29,460 So if you are paying careful attention, 593 00:29:29,460 --> 00:29:32,820 you see that this feature and all these checks 594 00:29:32,820 --> 00:29:35,490 were implemented on the renderer side 595 00:29:35,490 --> 00:29:38,010 and not on the Sandbox side. 596 00:29:38,010 --> 00:29:42,330 So if you can use a renderer Chrome V8 exploit 597 00:29:42,330 --> 00:29:45,990 and set nodeIntegrationInSubFrames to one, 598 00:29:45,990 --> 00:29:48,690 then it should be able to enable it. 599 00:29:48,690 --> 00:29:53,130 So let's look at an annotated version of our binary exploit. 600 00:29:53,130 --> 00:29:54,690 So here on number one, 601 00:29:54,690 --> 00:29:59,690 we get access to the web reference offset in the memory. 602 00:29:59,790 --> 00:30:02,130 Then we add this static offset to get access 603 00:30:02,130 --> 00:30:03,900 to nodeIntegrationInSubFrames, 604 00:30:03,900 --> 00:30:08,190 and then we override its value to one from zero, 605 00:30:08,190 --> 00:30:10,290 which means enabling it. 606 00:30:10,290 --> 00:30:12,360 Let's see where in real world application 607 00:30:12,360 --> 00:30:13,980 we were able to find this. 608 00:30:13,980 --> 00:30:18,630 So Element is one of a commonly used texting app, 609 00:30:18,630 --> 00:30:23,261 and it was using Chrome 91 and Electron 13.5.1. 610 00:30:23,261 --> 00:30:25,410 We find an XSS on embed 611 00:30:25,410 --> 00:30:27,750 through a deep link mis-configuration. 612 00:30:27,750 --> 00:30:29,790 And as we had XSS on embed, 613 00:30:29,790 --> 00:30:33,661 no contextBridge API was exposed to embed. 614 00:30:33,661 --> 00:30:36,930 So we run a Chrome renderer V8 exploit for Chrome 91 615 00:30:36,930 --> 00:30:40,890 to expose contextBridge API on embed. 616 00:30:40,890 --> 00:30:42,810 So, this is a code of element. 617 00:30:42,810 --> 00:30:46,290 Here, they define a channel on main.js, 618 00:30:46,290 --> 00:30:48,270 known as user download open. 619 00:30:48,270 --> 00:30:50,490 And whatever the argument is passed, 620 00:30:50,490 --> 00:30:53,250 it goes inside a dangerous Node JS function, 621 00:30:53,250 --> 00:30:54,533 which is shell.openpath. 622 00:30:54,533 --> 00:30:58,050 This is a dangerous sync for arbitrary code execution. 623 00:30:58,050 --> 00:30:59,940 On the other side on the preload, 624 00:30:59,940 --> 00:31:03,410 it exposes a send method to the webpage, 625 00:31:03,410 --> 00:31:07,530 in which you can pass any channel and argument to it. 626 00:31:07,530 --> 00:31:11,130 So as a diagram, let's go from sync to source. 627 00:31:11,130 --> 00:31:14,280 So main.js contains our RCE sync. 628 00:31:14,280 --> 00:31:16,890 Preload.js contains send method. 629 00:31:16,890 --> 00:31:19,200 Your main website of Element, 630 00:31:19,200 --> 00:31:21,810 has access to window.electron.send, 631 00:31:21,810 --> 00:31:25,140 but your XSS doesn't have access to that API. 632 00:31:25,140 --> 00:31:28,110 So with your exploit, what you can do is, 633 00:31:28,110 --> 00:31:30,720 you can run a multi-stage exploit. 634 00:31:30,720 --> 00:31:33,420 For the stage one, you run V8 exploit 635 00:31:33,420 --> 00:31:35,460 and send nodeIntegrationInSubFrame 636 00:31:35,460 --> 00:31:38,340 from zero to one, which enables it. 637 00:31:38,340 --> 00:31:41,700 And on the stage two, you create an Iframe 638 00:31:41,700 --> 00:31:43,290 within your first Iframe. 639 00:31:43,290 --> 00:31:45,750 And this second Iframe will load 640 00:31:45,750 --> 00:31:48,120 with nodeIntegrationInSubFrame through. 641 00:31:48,120 --> 00:31:50,760 So it'll have access to that send method, 642 00:31:50,760 --> 00:31:54,420 which you want to get that code execution. 643 00:31:54,420 --> 00:31:56,970 So, this is the code version of the exploit, 644 00:31:56,970 --> 00:31:58,830 and I create an Iframe within Iframe 645 00:31:58,830 --> 00:32:01,710 after enabling nodeIntegrationInSubFrame. 646 00:32:01,710 --> 00:32:03,750 So this will create another Iframe, 647 00:32:03,750 --> 00:32:05,340 and that's gonna pop a calc. 648 00:32:05,340 --> 00:32:07,680 Let's see how it looks like in the demo. 649 00:32:07,680 --> 00:32:10,680 Attacker is sending a URL to the victim. 650 00:32:10,680 --> 00:32:12,393 Victim is opening in the browser. 651 00:32:13,350 --> 00:32:16,680 They're gonna open in Element app. 652 00:32:16,680 --> 00:32:18,150 So it's a video conference. 653 00:32:18,150 --> 00:32:20,190 Everyone wants to join a video conference. 654 00:32:20,190 --> 00:32:22,530 So let's tap on join conference. 655 00:32:22,530 --> 00:32:24,450 And as you can see on the console, 656 00:32:24,450 --> 00:32:27,060 this is where our exploit is running behind the scene. 657 00:32:27,060 --> 00:32:29,850 It takes time to perform this hip massaging 658 00:32:29,850 --> 00:32:31,953 and calculating all this offset. 659 00:32:35,160 --> 00:32:36,960 And as you can see, we pop the calc. 660 00:32:38,084 --> 00:32:41,167 (audience clapping) 661 00:32:46,170 --> 00:32:48,570 So we received $3,000 bug bounty 662 00:32:48,570 --> 00:32:51,060 from Internet Bug Bounty program, 663 00:32:51,060 --> 00:32:55,140 and they fixed this entire Electron specific feature 664 00:32:55,140 --> 00:32:58,740 by not exposing this contextBridge IPC 665 00:32:58,740 --> 00:33:00,810 to child renderer process. 666 00:33:00,810 --> 00:33:03,570 So if you do the same in the latest Electron version, 667 00:33:03,570 --> 00:33:07,320 you won't be able to get access to window.electron.send 668 00:33:07,320 --> 00:33:09,420 within the Iframe inside your Iframe. 669 00:33:09,420 --> 00:33:13,350 So second, we move on to disabling context isolation, 670 00:33:13,350 --> 00:33:16,410 the most coveted feature of Electron JS 671 00:33:16,410 --> 00:33:18,240 from a compromised renderer. 672 00:33:18,240 --> 00:33:20,760 So same story, Electron defines that 673 00:33:20,760 --> 00:33:23,040 on the renderer side as well. 674 00:33:23,040 --> 00:33:27,270 In the code, we again go to shell/renderer folder, 675 00:33:27,270 --> 00:33:29,070 which is a renderer side code. 676 00:33:29,070 --> 00:33:32,580 And it gets context render code isolation variable 677 00:33:32,580 --> 00:33:35,370 in step one from blink web preferences 678 00:33:35,370 --> 00:33:36,720 for a renderer frame. 679 00:33:36,720 --> 00:33:39,600 And then on the step two, it has a Boolean, 680 00:33:39,600 --> 00:33:42,330 which should create isolated context, 681 00:33:42,330 --> 00:33:45,030 which is based on the value from step number one. 682 00:33:45,030 --> 00:33:47,130 And at step three, there is a if statement. 683 00:33:47,130 --> 00:33:49,950 If it's true, then enable context isolation. 684 00:33:49,950 --> 00:33:52,260 If it's false, don't enable. 685 00:33:52,260 --> 00:33:55,800 So same story, use a V8 Chrome renderer exploit 686 00:33:55,800 --> 00:33:59,700 and set context_isolation from one to zero. 687 00:33:59,700 --> 00:34:02,310 So our annotated exploit would look the same 688 00:34:02,310 --> 00:34:03,660 as the previous one. 689 00:34:03,660 --> 00:34:07,080 We get access to context isolation in the memory, 690 00:34:07,080 --> 00:34:11,550 and then we override to zero from one. 691 00:34:11,550 --> 00:34:14,280 So let's take a look at our final case study, 692 00:34:14,280 --> 00:34:17,310 where we found RCE in an undisclosed app. 693 00:34:17,310 --> 00:34:20,790 This app was using Chrome 94 and Electron version 15. 694 00:34:20,790 --> 00:34:24,240 And it had a feature to embed untrusted content 695 00:34:24,240 --> 00:34:25,800 within Iframe. 696 00:34:25,800 --> 00:34:27,570 So the code looks like this. 697 00:34:27,570 --> 00:34:29,820 On the right, we have the main.js, 698 00:34:29,820 --> 00:34:32,850 which defines the same open and Discord external channel, 699 00:34:32,850 --> 00:34:36,000 which goes into dangerous Node JS sync. 700 00:34:36,000 --> 00:34:41,000 On the left, we have a preload.js which implements a wrapper 701 00:34:41,550 --> 00:34:45,390 and has a function known as IsAllowed URL. 702 00:34:45,390 --> 00:34:49,860 This IsAllowed URL function will check whether a URL starts 703 00:34:49,860 --> 00:34:53,040 with a file protocol, which is HTTPS. 704 00:34:53,040 --> 00:34:56,040 So, if we try to use the similar exploit as previous, 705 00:34:56,040 --> 00:34:59,820 it's not gonna work because we were passing like file path 706 00:34:59,820 --> 00:35:00,840 to calc.app. 707 00:35:00,840 --> 00:35:04,440 And in this case, file is the protocol, not HTPs. 708 00:35:04,440 --> 00:35:06,540 So let's see what we can do here. 709 00:35:06,540 --> 00:35:08,760 So schematics again. 710 00:35:08,760 --> 00:35:11,700 If we try to run the nodeIntegrationInSubFrame exploit, 711 00:35:11,700 --> 00:35:15,090 we have access to open external URL API, 712 00:35:15,090 --> 00:35:17,040 which was defined on the preload, 713 00:35:17,040 --> 00:35:21,330 but still it will be subjected to the HTTPS check. 714 00:35:21,330 --> 00:35:25,410 So how can we somehow directly make a call 715 00:35:25,410 --> 00:35:28,380 to the main process from our Iframe? 716 00:35:28,380 --> 00:35:29,910 Let's see. 717 00:35:29,910 --> 00:35:33,270 So here is our exploit on the stage one. 718 00:35:33,270 --> 00:35:37,440 We will run a V8 exploit to change context isolation 719 00:35:37,440 --> 00:35:41,730 from one to zero, which means disabling context isolation. 720 00:35:41,730 --> 00:35:45,630 Then we perform a redirect after that step has happened. 721 00:35:45,630 --> 00:35:47,190 And we load a stage two, 722 00:35:47,190 --> 00:35:49,680 which is another page on your attacker website. 723 00:35:49,680 --> 00:35:52,740 And here we perform a prototype pollution attack, 724 00:35:52,740 --> 00:35:54,960 which I showed you in the earlier slide 725 00:35:54,960 --> 00:35:57,120 for CI disabled Windows. 726 00:35:57,120 --> 00:36:01,680 And this prototype pollution will leak you IPC bindings. 727 00:36:01,680 --> 00:36:04,680 And once you have access to this IPC binding, 728 00:36:04,680 --> 00:36:07,260 you can make a direct call to the main process 729 00:36:07,260 --> 00:36:11,820 using IPC.send with that particular IPC. 730 00:36:11,820 --> 00:36:16,050 So here, we are making a direct call to the main.js. 731 00:36:16,050 --> 00:36:18,120 So, this is our exploit. 732 00:36:18,120 --> 00:36:19,800 This is how it looks in the code. 733 00:36:19,800 --> 00:36:22,920 So this is the disabling part. 734 00:36:22,920 --> 00:36:25,680 We redirect to leak.html. 735 00:36:25,680 --> 00:36:27,750 We perform over prototype pollution, 736 00:36:27,750 --> 00:36:31,290 and we do an IPC.send with two arguments 737 00:36:31,290 --> 00:36:32,970 within the fastest channel. 738 00:36:32,970 --> 00:36:36,210 And the second is file part to calc. 739 00:36:36,210 --> 00:36:38,820 So let's see how we exploit would look like. 740 00:36:38,820 --> 00:36:42,780 So this is that famous undisclosed app running over exploit. 741 00:36:42,780 --> 00:36:46,830 So as you can see, it is calculating certain offsets, 742 00:36:46,830 --> 00:36:50,010 and then it is gonna perform the same thing 743 00:36:50,010 --> 00:36:51,860 which we had in the previous example. 744 00:36:54,660 --> 00:36:57,090 So this will be its log. 745 00:36:57,090 --> 00:37:01,410 And as you can see, now we have access to that, click me, 746 00:37:01,410 --> 00:37:02,613 which can pop a calc. 747 00:37:03,769 --> 00:37:06,852 (audience clapping) 748 00:37:10,620 --> 00:37:15,513 So we received $5,000 bounty for this bug for this program. 749 00:37:16,560 --> 00:37:20,850 So now we will take a look into same site origin spoofing. 750 00:37:20,850 --> 00:37:24,510 So for example, this is your shiny new Electron app, 751 00:37:24,510 --> 00:37:29,510 and it is loading a webpage known as main.example.com. 752 00:37:29,730 --> 00:37:32,550 This webpage creates two Iframes. 753 00:37:32,550 --> 00:37:34,770 The first one is youtube.com. 754 00:37:34,770 --> 00:37:38,280 And second one is Sandbox.example.com. 755 00:37:38,280 --> 00:37:40,890 So let's see how the process are created 756 00:37:40,890 --> 00:37:42,600 within Electron apps. 757 00:37:42,600 --> 00:37:46,050 So it creates a separate process for youtube.com, 758 00:37:46,050 --> 00:37:51,050 but it uses the same process for the Sandbox.example.com. 759 00:37:52,470 --> 00:37:55,170 And this happens because Chrome 760 00:37:55,170 --> 00:37:57,630 has a feature known as site isolation. 761 00:37:57,630 --> 00:38:00,240 And site isolation doesn't apply 762 00:38:00,240 --> 00:38:03,120 when your top level domain are the same. 763 00:38:03,120 --> 00:38:04,170 So in this case, 764 00:38:04,170 --> 00:38:07,650 the common between the main and Sandbox example.com, 765 00:38:07,650 --> 00:38:10,290 is the example.com top level domain. 766 00:38:10,290 --> 00:38:13,590 So Chrome uses the same process of both page. 767 00:38:13,590 --> 00:38:16,620 So in this case, if you are exploiting a real world app 768 00:38:16,620 --> 00:38:18,960 and you have XSS in Sandbox, 769 00:38:18,960 --> 00:38:22,680 which is on the Sandbox example.com process, 770 00:38:22,680 --> 00:38:24,090 then what you can do is, 771 00:38:24,090 --> 00:38:26,550 within a Chrome renderer V8 exploit, 772 00:38:26,550 --> 00:38:31,290 you can change document.url to main.example.com, 773 00:38:31,290 --> 00:38:35,430 and security context origin port to 443. 774 00:38:35,430 --> 00:38:38,700 This way, you will be effectively able 775 00:38:38,700 --> 00:38:41,850 to masquerade to your parent window 776 00:38:41,850 --> 00:38:46,200 and are able to access all the contextBridge exposed APIs 777 00:38:46,200 --> 00:38:49,140 or Node primitives which are available to the main window. 778 00:38:49,140 --> 00:38:51,720 So, this is one way to do this. 779 00:38:51,720 --> 00:38:54,330 So, let's talk about patch gap. 780 00:38:54,330 --> 00:38:57,380 So, as we noticed in a lot of this real world applications, 781 00:38:57,380 --> 00:39:01,230 we have used Chrome V8 renderer exploit. 782 00:39:01,230 --> 00:39:05,130 You might be wondering, is it really very likely 783 00:39:05,130 --> 00:39:07,710 to use a V8 exploit in all this real world app? 784 00:39:07,710 --> 00:39:09,810 And the answer is, yes. 785 00:39:09,810 --> 00:39:11,910 And this stems from the fact 786 00:39:11,910 --> 00:39:13,830 that there is a noticeable patch gap 787 00:39:13,830 --> 00:39:18,330 between Chrome, Electron, and Electron applications, 788 00:39:18,330 --> 00:39:21,540 which makes most of them susceptible to this attack. 789 00:39:21,540 --> 00:39:25,920 And an adversary or an attacker can also go one step further 790 00:39:25,920 --> 00:39:28,170 and can use Sandbox Escape for Chrome, 791 00:39:28,170 --> 00:39:31,200 but here, which I showed even with a renderer exploit, 792 00:39:31,200 --> 00:39:32,730 you can do a lot of stuff 793 00:39:32,730 --> 00:39:37,410 and just defeat the entire Electron JS security features. 794 00:39:37,410 --> 00:39:39,480 So let's talk about the mitigations. 795 00:39:39,480 --> 00:39:41,700 So for the developers, 796 00:39:41,700 --> 00:39:45,120 I would suggest that enable all the security features 797 00:39:45,120 --> 00:39:46,470 because a lot of these bugs 798 00:39:46,470 --> 00:39:49,080 which we submitted to Electron JS frameworks 799 00:39:49,080 --> 00:39:51,210 were fixed promptly by it. 800 00:39:51,210 --> 00:39:54,030 But there is a design flaw 801 00:39:54,030 --> 00:39:56,790 which is present in the Electron JS framework, 802 00:39:56,790 --> 00:40:00,090 which allows you to access these features 803 00:40:00,090 --> 00:40:01,980 from a renderer process. 804 00:40:01,980 --> 00:40:04,980 So this flaw is currently still present. 805 00:40:04,980 --> 00:40:07,620 So even with the renderer exploit today, 806 00:40:07,620 --> 00:40:11,130 you can disable context isolation, for example. 807 00:40:11,130 --> 00:40:14,430 But Electron JS developers have enough step 808 00:40:14,430 --> 00:40:16,758 to not expose APIs, for example, 809 00:40:16,758 --> 00:40:18,480 in nodeIntegrationInSubFrames, 810 00:40:18,480 --> 00:40:21,900 which prevents a few of our exploits here. 811 00:40:21,900 --> 00:40:24,150 So if you are using an app, 812 00:40:24,150 --> 00:40:27,510 make sure to upgrade your Electron version very regularly. 813 00:40:27,510 --> 00:40:30,930 So, if you are a developer who is always keeping up 814 00:40:30,930 --> 00:40:33,780 with the pace of this Electron releases, 815 00:40:33,780 --> 00:40:35,190 then you should be pretty much safe 816 00:40:35,190 --> 00:40:37,410 for this patch cap and it will be narrow. 817 00:40:37,410 --> 00:40:39,600 And if you have an organization 818 00:40:39,600 --> 00:40:42,510 who can maintain your own fork of Electron, 819 00:40:42,510 --> 00:40:44,790 you can cherry pick this V8 fixes 820 00:40:44,790 --> 00:40:48,210 and can deploy it there to be one step further. 821 00:40:48,210 --> 00:40:49,890 So, another important aspect 822 00:40:49,890 --> 00:40:53,250 is to don't use a third party embeds on your website. 823 00:40:53,250 --> 00:40:55,170 We saw that a failure point with Discord 824 00:40:55,170 --> 00:40:58,560 was to use Vimeo embed for example here. 825 00:40:58,560 --> 00:41:02,130 So make sure that you use pretty trusted embeds. 826 00:41:02,130 --> 00:41:03,600 And even if you use, 827 00:41:03,600 --> 00:41:05,940 make sure you have enough defense in depth, 828 00:41:05,940 --> 00:41:09,030 because that embed can lead to a code execution 829 00:41:09,030 --> 00:41:10,650 in your own app. 830 00:41:10,650 --> 00:41:12,570 So be careful about that. 831 00:41:12,570 --> 00:41:14,280 And the last suggestion here 832 00:41:14,280 --> 00:41:17,880 is to mitigate vulnerabilities across all your assets. 833 00:41:17,880 --> 00:41:19,650 So even if you have sub domains, 834 00:41:19,650 --> 00:41:23,280 as we saw that you can use an XSS on sub domain 835 00:41:23,280 --> 00:41:25,890 and then just go back to the main window 836 00:41:25,890 --> 00:41:28,530 using the same site exploit. 837 00:41:28,530 --> 00:41:32,100 So, that should be the part of our mitigations. 838 00:41:32,100 --> 00:41:35,790 So as a part of our epilogue, what I wanna mention is, 839 00:41:35,790 --> 00:41:37,440 we were able to compromise 840 00:41:37,440 --> 00:41:39,637 20 different Electron applications. 841 00:41:39,637 --> 00:41:42,330 These are used by millions of people. 842 00:41:42,330 --> 00:41:45,420 And some of the examples which I didn't show in the talk 843 00:41:45,420 --> 00:41:50,070 are JupyterLab, Mattermost, Basecamp, Notion, 844 00:41:50,070 --> 00:41:52,023 Rocket.Chat, and others. 845 00:41:53,070 --> 00:41:56,610 So for our takeaways as a part of this talk, 846 00:41:56,610 --> 00:41:59,280 I wanna emphasize on three key points. 847 00:41:59,280 --> 00:42:02,340 The first one is related to bug bounty hunters 848 00:42:02,340 --> 00:42:04,230 and security researcher. 849 00:42:04,230 --> 00:42:05,850 And it is to dig deeper 850 00:42:05,850 --> 00:42:08,130 into the framework which you are auditing 851 00:42:08,130 --> 00:42:11,400 and to not limit yourself to the application layer. 852 00:42:11,400 --> 00:42:13,440 So in our research, 853 00:42:13,440 --> 00:42:16,500 we didn't stop on just the JavaScript side 854 00:42:16,500 --> 00:42:17,970 of the things on Electron, 855 00:42:17,970 --> 00:42:21,180 but we took a look into how these features were implemented 856 00:42:21,180 --> 00:42:24,210 and what are the possibilities to tamper with those. 857 00:42:24,210 --> 00:42:26,430 So, go as deep as possible 858 00:42:26,430 --> 00:42:29,520 when you are auditing this sort of frameworks. 859 00:42:29,520 --> 00:42:30,630 The second one is, 860 00:42:30,630 --> 00:42:33,720 Electron apps are a very ideal adversarial 861 00:42:33,720 --> 00:42:35,430 or red team target. 862 00:42:35,430 --> 00:42:38,040 As you can see all this app; Discord, Element, 863 00:42:38,040 --> 00:42:41,460 you just send a link, and it just requires single click. 864 00:42:41,460 --> 00:42:43,860 And some of our exploit even doesn't require a click 865 00:42:43,860 --> 00:42:46,590 and you can get a system label shell 866 00:42:46,590 --> 00:42:48,300 on the operating system. 867 00:42:48,300 --> 00:42:50,880 So users are gonna open the link. 868 00:42:50,880 --> 00:42:52,770 They are going to join conferences 869 00:42:52,770 --> 00:42:55,740 and they are going to click on certain stuff. 870 00:42:55,740 --> 00:42:57,750 So this is really important. 871 00:42:57,750 --> 00:43:00,300 And if you're on the detection team or blue team, 872 00:43:00,300 --> 00:43:03,390 it is important to also consider Electron's app 873 00:43:03,390 --> 00:43:04,770 as a part of your threat model 874 00:43:04,770 --> 00:43:06,960 and see as the same entry point 875 00:43:06,960 --> 00:43:10,170 as any other site you have in your organization. 876 00:43:10,170 --> 00:43:12,750 The third one, if you are a developer, 877 00:43:12,750 --> 00:43:15,600 minimize attack surface on your application 878 00:43:15,600 --> 00:43:17,190 as much as possible. 879 00:43:17,190 --> 00:43:19,080 So Electron is not bad. 880 00:43:19,080 --> 00:43:19,913 I would say, 881 00:43:19,913 --> 00:43:22,863 if you are implementing and doing all the best practices, 882 00:43:23,893 --> 00:43:24,990 it is still gonna provide you 883 00:43:24,990 --> 00:43:27,360 and guarantee you security features. 884 00:43:27,360 --> 00:43:29,880 But you need to work towards that. 885 00:43:29,880 --> 00:43:32,190 You need to minimize this attack surface. 886 00:43:32,190 --> 00:43:36,690 So, a good example to this is a textbook low level attack 887 00:43:36,690 --> 00:43:38,430 known as open URL redirection, 888 00:43:38,430 --> 00:43:41,460 which is a PFI on a lot of bug bounty program. 889 00:43:41,460 --> 00:43:44,790 In Electron app, if you find a open URL redirection, 890 00:43:44,790 --> 00:43:46,860 you can redirect to your own website 891 00:43:46,860 --> 00:43:48,570 and you have control to the window, 892 00:43:48,570 --> 00:43:52,470 and then you can just run this Electron exploit to gain RCE. 893 00:43:52,470 --> 00:43:53,403 So who knows? 894 00:43:54,779 --> 00:43:58,740 Sometime open URL redirection in your app can lead to RCE. 895 00:43:58,740 --> 00:44:03,240 So, please pay careful attention to your assets as well. 896 00:44:03,240 --> 00:44:06,840 So, at the end of this, I would like to thank everyone 897 00:44:06,840 --> 00:44:08,520 for coming and viewing our talk, 898 00:44:08,520 --> 00:44:11,100 and for your attention, time and interest. 899 00:44:11,100 --> 00:44:14,790 And if you wanna understand in details about our findings, 900 00:44:14,790 --> 00:44:18,750 we have created a website which is electrovolt.io. 901 00:44:18,750 --> 00:44:21,930 And within this website, there is a menu for blog, 902 00:44:21,930 --> 00:44:24,630 which opens blog.electrovolt.io. 903 00:44:24,630 --> 00:44:26,730 And there you can find proof of concept 904 00:44:26,730 --> 00:44:30,210 and this exploit code for the use cases 905 00:44:30,210 --> 00:44:31,830 which I mentioned here. 906 00:44:31,830 --> 00:44:35,010 And we will be also updating this site time to time 907 00:44:35,010 --> 00:44:37,470 to include all the 20 use cases 908 00:44:37,470 --> 00:44:39,660 and Electron JS specific flaws. 909 00:44:39,660 --> 00:44:42,810 So with that, I conclude my presentation here. 910 00:44:42,810 --> 00:44:46,089 And thanks again for coming to see Electrovolt. 911 00:44:46,089 --> 00:44:47,268 (audience clapping)