1 00:00:14,130 --> 00:00:18,770 Welcome back and thanks for hanging with us here at AppSecVillage at DEF CON 2020. 2 00:00:19,270 --> 00:00:24,790 Before we get to our next speaker, I'd like for you to take a moment and take a look at appsecvillage.com. 3 00:00:25,050 --> 00:00:28,330 Out there you can find this year's t-shirt, which is incredible. 4 00:00:28,330 --> 00:00:30,050 This is last year's t-shirt. 5 00:00:30,050 --> 00:00:32,710 This year's has got more color, it's got an awesome design. 6 00:00:32,710 --> 00:00:35,170 I just got mine in the mail a couple of days ago. 7 00:00:35,350 --> 00:00:36,210 Check it out. 8 00:00:36,210 --> 00:00:47,750 It's a great way to support AppSecVillage and make sure that we can bring you the same kind of content and application developer security focus that we've brought the last two years. 9 00:00:47,750 --> 00:00:50,270 So, that's appsecvillage.com. 10 00:00:50,270 --> 00:00:51,610 And now for our next talk. 11 00:00:51,610 --> 00:00:56,750 It's entitled Local Ghost, Escaping the Browser Sandbox Without Zero Days. 12 00:00:56,910 --> 00:01:01,470 Parsia Hakimian is a senior security engineer at Electronic Arts. 13 00:01:01,470 --> 00:01:05,890 He works mostly in video games and their surprise mechanics. 14 00:01:05,990 --> 00:01:08,910 On a different continent, he was a C developer. 15 00:01:08,910 --> 00:01:17,070 You can find his rants over at parsia.net or on Twitter at at sign crypto gangsta. 16 00:01:17,070 --> 00:01:23,330 Now remember, crypto stands for cryptography, as everybody over in the cryptography village would tell you. 17 00:01:23,330 --> 00:01:27,650 So with that, welcome Parsia to the AppSecVillage stage. 18 00:01:30,910 --> 00:01:32,110 Hello everyone. 19 00:01:32,110 --> 00:01:34,050 Thanks for giving me your time. 20 00:01:34,050 --> 00:01:41,450 Today I'm going to talk to you about how we can jump the browser sandbox using localhost web servers without any sort of ODAs. 21 00:01:41,450 --> 00:01:49,250 This is part of the AppSecVillage on DEF CON 28 in the year 2020, which has been a very, very long year. 22 00:01:49,930 --> 00:01:51,210 My name is Parsia. 23 00:01:51,210 --> 00:01:54,550 I am a security engineer at Electronic Arts. 24 00:01:54,730 --> 00:01:56,670 Mostly work with video games. 25 00:01:56,790 --> 00:01:59,890 I'm the shorter guy in the picture, not the other one. 26 00:01:59,890 --> 00:02:05,270 I'm not here representing EA, user of my own, you know, the usual boilerplate. 27 00:02:05,270 --> 00:02:10,210 Similar to the boilerplate you see on the coffee cups, you know, that says caution, contents are hot. 28 00:02:10,270 --> 00:02:17,450 When I moved to Canada last year from the US, people told me they don't have it in Canada, but they do. 29 00:02:17,450 --> 00:02:19,390 So I would like my money back. 30 00:02:19,650 --> 00:02:22,130 This is my second time at DEF CON. 31 00:02:22,170 --> 00:02:23,770 First time at the village. 32 00:02:23,770 --> 00:02:28,030 I was here on DEF CON 2018 where I talked about enterprise blockchain. 33 00:02:28,030 --> 00:02:32,990 I play a lot of video games, which is good because I work for a video game company. 34 00:02:33,390 --> 00:02:36,630 Now, this is a slide that I put on all my presentations. 35 00:02:36,630 --> 00:02:42,650 It is here to tell you what I'm going to talk about. 36 00:02:42,710 --> 00:02:47,250 So you can decide if this is a talk for you. 37 00:02:47,310 --> 00:02:49,050 So your time is valuable. 38 00:02:49,050 --> 00:02:55,730 I don't want you to sit to the end of it and say, this is useless or I already knew this. 39 00:02:55,730 --> 00:03:02,690 You know, I would consider this a favor if everyone else did it too. 40 00:03:03,130 --> 00:03:11,790 So I'm going to talk about why modern desktop applications use local host servers to do inter-process communications. 41 00:03:11,810 --> 00:03:18,970 And how this is bad from a security perspective, because JavaScript and browsers can connect to these websites. 42 00:03:19,510 --> 00:03:24,950 Usually there's no authentication and you can get some really easy remote code executions using this. 43 00:03:24,950 --> 00:03:29,530 I was also discussing browser concepts and bugs related to them. 44 00:03:29,530 --> 00:03:33,850 And finally, I will talk about remediation and how we can fix things. 45 00:03:34,010 --> 00:03:37,530 And not just point and say something is bad. 46 00:03:37,830 --> 00:03:41,710 So these local web servers are like ghosts in your machine. 47 00:03:41,810 --> 00:03:48,830 You think you don't have any, but go to your machine, run netstat and check. 48 00:03:48,830 --> 00:03:51,990 And you will have at least a dozen of these. 49 00:03:51,990 --> 00:03:54,930 I cropped the screenshot, there were more. 50 00:03:54,930 --> 00:04:03,410 As you can see, these are like normal, typical everyday use apps like Discord and Dropbox and Apple and iTunes and NVIDIA. 51 00:04:03,410 --> 00:04:04,790 I mean, all of these have them. 52 00:04:04,790 --> 00:04:09,630 Why would Discord or Dropbox have a local web server? 53 00:04:09,730 --> 00:04:12,850 It's usually used for inter-process communications. 54 00:04:12,890 --> 00:04:15,190 Usually you have an Electron frontend. 55 00:04:15,250 --> 00:04:20,150 And the Electron frontend talks to a local web server that serves content to it. 56 00:04:20,290 --> 00:04:22,890 Sometimes you have a Windows service running a system. 57 00:04:22,890 --> 00:04:23,930 Those are fun. 58 00:04:23,930 --> 00:04:28,230 And then there's a frontend app that talks to them and they talk with each other. 59 00:04:28,230 --> 00:04:35,030 Sometimes you have a local host server that allows you to talk to different applications. 60 00:04:35,030 --> 00:04:37,710 Discord and Overvolt talk with each other. 61 00:04:38,710 --> 00:04:44,110 Another use case is using seamless transition from a website to a desktop app. 62 00:04:45,070 --> 00:04:47,450 Video conferencing apps used to do this. 63 00:04:47,450 --> 00:04:51,030 You would go to a meeting page. 64 00:04:51,030 --> 00:04:57,270 The JavaScript in the meeting page would talk to the local server from the desktop app. 65 00:04:57,270 --> 00:05:03,870 And the web desktop app would bring up the video conferencing app and connect to the meeting. 66 00:05:03,870 --> 00:05:05,470 Seamless interaction. 67 00:05:05,490 --> 00:05:07,270 Great for user experience. 68 00:05:07,590 --> 00:05:09,590 Dropbox also does this. 69 00:05:09,590 --> 00:05:18,990 If you have the Dropbox desktop application on your machine and you go to the web interface, sometimes you have an open button in front of a file. 70 00:05:18,990 --> 00:05:23,690 Let's say it's a Microsoft Office, like a doc file. 71 00:05:24,290 --> 00:05:28,550 You click on the open button in the website. 72 00:05:28,790 --> 00:05:32,690 The website talks to the local Dropbox app on your machine. 73 00:05:32,690 --> 00:05:36,770 The Dropbox app opens Microsoft Office and opens that doc. 74 00:05:36,770 --> 00:05:37,710 Great again. 75 00:05:37,710 --> 00:05:39,510 Great user experience. 76 00:05:39,510 --> 00:05:42,050 But is this really secure? 77 00:05:42,170 --> 00:05:43,630 Let's see. 78 00:05:44,410 --> 00:05:50,350 Another thing that websites do and gain a lot of traction was port scanning. 79 00:05:50,850 --> 00:05:56,230 Someone went to the eBay website and saw that it's scanning a lot of local ports. 80 00:05:56,230 --> 00:06:02,370 For example, to see if you have running a local VNC server or the remote desktop application. 81 00:06:02,370 --> 00:06:03,650 Like certain ports. 82 00:06:03,790 --> 00:06:05,950 Banks have been doing it for like four or five years. 83 00:06:05,950 --> 00:06:08,890 I remember I went to a bank website in 2018. 84 00:06:09,010 --> 00:06:10,450 It was doing the same. 85 00:06:10,450 --> 00:06:13,930 This is part of the fraud detection thing. 86 00:06:13,930 --> 00:06:22,550 They grab the results and feed it to a complex fraud detection algorithm. 87 00:06:22,550 --> 00:06:31,670 And it decides if your machine connected to the website is part of a botnet or is being remotely accessed or not. 88 00:06:31,670 --> 00:06:33,710 Should they let the transactions go through? 89 00:06:33,710 --> 00:06:35,150 Should they lock your account? 90 00:06:35,150 --> 00:06:36,010 So on and so forth. 91 00:06:36,010 --> 00:06:37,410 Typical stuff. 92 00:06:37,410 --> 00:06:42,750 If these websites are doing it, what prevents bad websites from doing it? 93 00:06:43,310 --> 00:06:47,290 Your app is internet connected because of that. 94 00:06:47,810 --> 00:06:51,650 Raymond Chen is a Microsoft employee. 95 00:06:51,650 --> 00:06:56,430 And he has been writing this very, very useful blog called The Old New Think. 96 00:06:56,890 --> 00:07:01,470 And one of his blogs, which starts with that quote. 97 00:07:01,470 --> 00:07:05,210 It's rather involved beings on the other side of this airtight hatchway. 98 00:07:05,210 --> 00:07:10,470 And by the way, this is a quote from Douglas Adams' book, Hitchhiker's Guide to the Galaxy. 99 00:07:10,670 --> 00:07:12,450 It's an amazing book. 100 00:07:12,530 --> 00:07:18,350 So Raymond talks about three privileged levels on a typical Windows machine. 101 00:07:18,350 --> 00:07:21,170 You have a remote attacker who is not on the machine. 102 00:07:21,190 --> 00:07:23,890 You have a local attacker who is a standard user. 103 00:07:23,890 --> 00:07:27,010 And then finally you have the local admin or system. 104 00:07:27,190 --> 00:07:32,170 Now browsers can be remote attackers, although they are running on your machine. 105 00:07:32,170 --> 00:07:37,750 So the JavaScript in the browser can talk to the local web server or talk to the local WebSocket server. 106 00:07:37,830 --> 00:07:40,890 And then a remote attacker can gain privilege on your machine. 107 00:07:40,910 --> 00:07:44,070 He also talks about how your app is internet connected. 108 00:07:44,070 --> 00:07:46,090 And this is from 2006. 109 00:07:46,310 --> 00:07:55,170 He says, if you have an app and it handles files, people can create network shares on a remote machine somewhere else. 110 00:07:55,210 --> 00:07:58,030 And then they can pass it to your app. 111 00:07:58,030 --> 00:08:02,290 And now your app is internet connected because it's grabbing a resource from a different site. 112 00:08:02,290 --> 00:08:04,370 Although it wasn't in your threat model. 113 00:08:04,890 --> 00:08:11,090 We've talked a lot about browsers and how browsers can be remote attackers. 114 00:08:11,090 --> 00:08:17,250 Let's talk about how browsers want to keep us safe, but they can, but they cannot. 115 00:08:17,310 --> 00:08:21,270 And what protections are there and how we can bypass them. 116 00:08:21,730 --> 00:08:24,290 The first thing is called same-origin policy. 117 00:08:24,290 --> 00:08:28,750 It's probably the most important part of the browser security model. 118 00:08:28,770 --> 00:08:30,550 So an origin has three parts. 119 00:08:30,550 --> 00:08:35,330 You have a protocol, which is HTTP, HTTPS. 120 00:08:35,330 --> 00:08:39,890 You have a domain, which is something like example.net. 121 00:08:39,990 --> 00:08:42,890 And then finally, you have a port, which is optional. 122 00:08:42,910 --> 00:08:46,610 If you don't include the port, the default port is used. 123 00:08:47,310 --> 00:08:52,970 Some browsers, for example, Internet Explorer, don't care about the port in the origin. 124 00:08:52,970 --> 00:08:56,290 The path is almost always ignored. 125 00:08:56,290 --> 00:09:02,230 Usually, one origin cannot talk to a different origin and grab resources and read them. 126 00:09:02,230 --> 00:09:09,370 So for example, if you open example.net, example.net sends a request to facebook.com and grabs some data. 127 00:09:09,370 --> 00:09:12,970 Browser doesn't let example.net read the response. 128 00:09:13,590 --> 00:09:18,290 Absent some other things are cores, but we're not going to talk about cores today. 129 00:09:18,850 --> 00:09:23,790 And that's a really good thing, because otherwise example.net would have all my Facebook data. 130 00:09:24,130 --> 00:09:28,230 So reads are usually not okay, but writes are. 131 00:09:28,350 --> 00:09:37,950 So if I open example.net and send a POST request to Facebook to change something, if there's no C-SERV protection, it goes through. 132 00:09:38,270 --> 00:09:41,950 As a result, C-SERV exists, which is not really so great for us. 133 00:09:41,950 --> 00:09:46,290 So the SOP protects us in some cases, but not in every case. 134 00:09:47,190 --> 00:09:58,890 But SOP also has this problem that just because the browser doesn't let you see the response to the request, doesn't mean the request is not sent. 135 00:09:59,230 --> 00:10:02,330 So browser sends simple requests. 136 00:10:02,330 --> 00:10:06,210 Simple request is a request that has some requirements. 137 00:10:06,370 --> 00:10:09,710 The HTTP verb can only be GET, HEAD, and POST. 138 00:10:09,890 --> 00:10:11,970 It cannot have any custom headers. 139 00:10:12,530 --> 00:10:15,690 And it cannot have every header. 140 00:10:16,070 --> 00:10:18,010 Only some headers are allowed. 141 00:10:18,030 --> 00:10:21,070 And of those headers, the most important one is content type. 142 00:10:21,210 --> 00:10:24,050 The content type for those headers can only be one of those. 143 00:10:24,110 --> 00:10:35,790 So one of the tricks that we usually use when bypassing this, if you have an application slash JSON request, you change the content type to text slash plain, see if it becomes a simple request and goes through. 144 00:10:35,790 --> 00:10:39,610 And now you have bypassed a bunch of protections in the app. 145 00:10:39,670 --> 00:10:41,190 And that brings us to our first bug. 146 00:10:42,370 --> 00:10:46,270 This is a bug by Tavish Romandy from 2016. 147 00:10:46,450 --> 00:10:49,090 Tavish Romandy is a really smart dude. 148 00:10:49,090 --> 00:10:51,330 He's part of the Google Project Zero. 149 00:10:51,330 --> 00:10:57,270 He installs Trend Micro Antivirus, and that antivirus has a password manager. 150 00:10:57,390 --> 00:11:05,290 So the way password managers usually work is that you have an extension in the browser, and you have a local web server, a WebSocket server. 151 00:11:05,290 --> 00:11:12,490 The local server is responsible for storing the passwords, updating, and a bunch of those. 152 00:11:12,490 --> 00:11:22,530 The extension in the browser, when, for example, you go to facebook.com, the extension in the browser talks to the web server and says, give me my username and password for facebook.com. 153 00:11:22,530 --> 00:11:25,090 And the web server gives it to it. 154 00:11:25,090 --> 00:11:29,090 And then the extension fills up the username and password. 155 00:11:30,190 --> 00:11:42,610 In the case of Trend Micro, the local web server was unauthenticated, and you could basically do remote code execution with a simple GET request, as you can see on this slide. 156 00:11:42,830 --> 00:11:54,430 You could say, OK, run this URL in the default browser, which in this case opens up the calc, runs the calc manually instead of opening it in a browser. 157 00:11:54,830 --> 00:12:08,910 If you go and read the bug from the URL, from the link in this slide, you can see that Tavisor says, yeah, we can see the response, but the GET request goes through because it's a simple GET request. 158 00:12:09,330 --> 00:12:11,350 So damage is already done. 159 00:12:11,350 --> 00:12:13,830 We can't see the response, but who cares about that? 160 00:12:14,510 --> 00:12:19,030 Another thing that is used for local IPC are WebSockets. 161 00:12:19,170 --> 00:12:23,970 A WebSocket is different from your typical HTTP request. 162 00:12:23,970 --> 00:12:32,250 In a typical HTTP request, you create a connection to a server, you send a request, get a response back, and then you close the connection. 163 00:12:32,250 --> 00:12:38,850 In a WebSocket, you create a WebSocket and you keep it alive. 164 00:12:38,850 --> 00:12:41,210 You can write to it, you can read from it. 165 00:12:41,210 --> 00:12:51,330 It's great for real-time data things, real-time data updates, like, you know, chats and video games and, like, stock trackers, I guess. 166 00:12:52,030 --> 00:12:54,590 But the WebSocket doesn't come out of the blue. 167 00:12:55,090 --> 00:13:02,090 It starts with a GET request that is a normal handshake. 168 00:13:02,410 --> 00:13:06,070 So the GET request is your typical GET request with some special headers. 169 00:13:06,390 --> 00:13:13,010 Now, remember, the GET request for a WebSocket is a simple request, so it always goes through. 170 00:13:13,050 --> 00:13:18,870 On the response side, the other side basically says, here are the things I agreed on. 171 00:13:18,870 --> 00:13:20,830 Yes, we can make a connection. 172 00:13:20,830 --> 00:13:22,250 Here's our protocol. 173 00:13:22,250 --> 00:13:35,010 One mistake that developers usually make is that they think that SEC WebSocket key in the request and the WebSocket ACCEPT key in the response are based on security. 174 00:13:35,110 --> 00:13:36,150 They're not. 175 00:13:36,310 --> 00:13:40,390 You can usually put something, anything in there and it usually goes through. 176 00:13:40,390 --> 00:13:41,570 It doesn't really matter. 177 00:13:41,570 --> 00:13:43,410 That's not a security control. 178 00:13:43,770 --> 00:13:48,030 So don't care about that. 179 00:13:48,030 --> 00:13:48,890 It's always there. 180 00:13:48,890 --> 00:13:49,690 It goes through. 181 00:13:49,690 --> 00:13:51,030 It doesn't really matter. 182 00:13:51,030 --> 00:13:59,050 And if you can see the response, you can see that there's nothing really needed there apart from how we can make a connection. 183 00:13:59,110 --> 00:14:09,450 And as a result, the browsers are not bound by the same-origin policy because there's nothing in the response that the browser doesn't already know. 184 00:14:10,070 --> 00:14:17,950 So if you send a GET request and there's no cores, you can't see the response, but the browser makes the connection for you anyway. 185 00:14:18,150 --> 00:14:22,510 So if you have a local WebSocket server, everyone can connect to it and talk to it. 186 00:14:22,510 --> 00:14:25,990 You can't rely on SOP or cores or whatever, any of that. 187 00:14:25,990 --> 00:14:29,010 And that brings us to our second Aviso bug. 188 00:14:30,690 --> 00:14:32,930 As I said, this guy is smart. 189 00:14:33,090 --> 00:14:38,370 This is from 2018, and he wanted to re-bind his mouse key. 190 00:14:38,370 --> 00:14:42,030 It was a Logitech mouse, so he installs an app called Logitech Options. 191 00:14:42,490 --> 00:14:47,530 Logitech Options runs a local WebSocket server, some port 10134. 192 00:14:48,030 --> 00:14:53,510 As I said, WebSockets are not bound by the SOP, and the WebSocket server didn't have any checks. 193 00:14:53,530 --> 00:15:01,130 The only authentication it had was when you sent a message to it, you had to provide a process ID of a process that the user owns. 194 00:15:01,230 --> 00:15:05,470 A process ID that are like three, four or five digit numbers. 195 00:15:05,770 --> 00:15:10,990 And you can brute force them quite easily in a few minutes until you find one that works for you. 196 00:15:11,270 --> 00:15:18,170 Fortunately for Logitech Options, you couldn't get remote code execution, you could create crashes. 197 00:15:18,730 --> 00:15:24,050 So imagine you have this app running on your machine, and it's always running because you have a Logitech mouse. 198 00:15:24,050 --> 00:15:26,730 You go to a website, and the app crashes. 199 00:15:26,730 --> 00:15:28,730 You go to the other website, the app crashes. 200 00:15:28,730 --> 00:15:33,910 That's not really useful, and that makes your experience really bad. 201 00:15:33,910 --> 00:15:38,630 On the plus side, you couldn't get remote code execution, so that's really great. 202 00:15:38,630 --> 00:15:42,650 The next iteration of the app, similar app, called Logitech Hub. 203 00:15:42,650 --> 00:15:47,470 It runs two local WebSocket servers, on port 9010 and 9100. 204 00:15:48,590 --> 00:15:53,650 Now, this iteration checks the origin header, which is really great. 205 00:15:53,650 --> 00:16:01,710 The origin header is a forbidden header, which means the JavaScript in the app cannot set it, only the browser can. 206 00:16:01,710 --> 00:16:04,750 There are other forbidden headers, like the host header, for example. 207 00:16:05,730 --> 00:16:10,830 And the origin header is always set by the browser for every cross-origin request. 208 00:16:10,830 --> 00:16:19,730 A request goes from one origin to a different origin, the browser sets the origin header to tell the server on the other side where this request comes from. 209 00:16:19,890 --> 00:16:29,970 So what Logitech Hub does in the WebSocket servers is if you send a request with an origin that is not part of their allow list, then they just say, we can't connect. 210 00:16:30,030 --> 00:16:37,070 And when the browser sees a response like this, which is not a 200 OK response, it says, well, I can't create a WebSocket connection. 211 00:16:37,230 --> 00:16:45,730 So websites cannot talk to Logitech Hub WebSockets, so this is a great thing, and this is a good thing that Logitech has done. 212 00:16:46,170 --> 00:16:56,190 We've talked about local WebSockets servers, but we also want to talk about how frameworks can help us get remote code execution. 213 00:16:56,190 --> 00:16:59,130 And I'm going to talk about one of them, which is called Electron. 214 00:16:59,130 --> 00:17:08,170 Electron is probably the most popular desktop application framework out there. 215 00:17:08,170 --> 00:17:10,110 It is based on Chromium. 216 00:17:10,110 --> 00:17:19,990 Chromium is the open source version, I'm sorry, the open source base for a bunch of browsers like Google Chrome and Microsoft Edge. 217 00:17:19,990 --> 00:17:23,990 So everything in an Electron app is a browser window. 218 00:17:24,090 --> 00:17:28,010 So if you open Visual Studio Code, you're looking at a browser window. 219 00:17:28,750 --> 00:17:31,650 Yeah, I know, it's silly like that. 220 00:17:32,490 --> 00:17:34,690 And Electron is very popular. 221 00:17:34,750 --> 00:17:36,310 You can see these apps on this. 222 00:17:36,310 --> 00:17:38,110 There are so many of these apps. 223 00:17:38,110 --> 00:17:43,610 And these apps that you see on the slide, you probably have at least one of them on your machine. 224 00:17:43,650 --> 00:17:48,590 Slack or Discord or Visual Studio Code or Skype or whatever. 225 00:17:49,190 --> 00:17:58,650 The problem with Electron apps is that if you get a cross-site scripting, it might lead to remote code execution. 226 00:17:58,870 --> 00:18:05,550 So in an Electron app, you can write Node.js code that is run in the browser and can do stuff. 227 00:18:05,830 --> 00:18:14,070 The way for this Node.js code to run is you want this Node.js code to run, so you flip a switch. 228 00:18:14,070 --> 00:18:18,950 The switch is called node integration, which is off by default for a good reason. 229 00:18:19,150 --> 00:18:33,350 So if you set it to true, the JavaScript in your browser window in the Electron app can now talk to the Node.js APIs and, for example, spawn processes on your machine. 230 00:18:33,590 --> 00:18:41,130 And as a result, if you have this switch set to true and you get cross-site scripting, now you have remote code execution, which is really bad. 231 00:18:41,130 --> 00:18:48,370 If you have an open redirect, which means that you can click on a link and the browser goes to a different link, or you can do something like that. 232 00:18:48,370 --> 00:19:00,770 You can embed remote code execution payloads on your website that you control, and then you have remote code execution on someone's machine through an Electron app. 233 00:19:00,770 --> 00:19:07,290 This is by default set to off, and as we saw, it's great for a good reason. 234 00:19:07,690 --> 00:19:10,090 Now I'm going to talk about one of my own bugs. 235 00:19:10,090 --> 00:19:16,690 It's a remote code execution in a Tagged Surface Analyzer, which is an open-source Microsoft application. 236 00:19:16,710 --> 00:19:21,310 And we're going to talk about version two of it because it has two versions. 237 00:19:21,490 --> 00:19:34,470 When the second version was released, our CISO, who was one of the people who created the original app, said, oh, I worked on the original app, and I went and looked at it and see what kind of app it is. 238 00:19:34,470 --> 00:19:37,850 And it's a very useful app for desktop security research. 239 00:19:38,670 --> 00:19:44,470 What you can do is you can create runs, which are basically snapshots. 240 00:19:44,630 --> 00:20:00,850 So you can tell a Tagged Surface Analyzer to create a snapshot before you install an application on your machine, and then you install the application, and then you create a snapshot or run after you install the application. 241 00:20:00,850 --> 00:20:03,950 And now you can compare these two. 242 00:20:03,950 --> 00:20:13,090 And you can see what files were added, what registry keys were added, if there were any open ports, if there were any new Windows services. 243 00:20:13,330 --> 00:20:18,770 So again, it's very useful for this kind of security research. 244 00:20:19,090 --> 00:20:20,870 It comes in two flavors. 245 00:20:20,890 --> 00:20:23,510 There's a command line interface, and there's a GUI. 246 00:20:23,590 --> 00:20:25,850 I usually want to run it as admin. 247 00:20:26,030 --> 00:20:31,910 In fact, if you don't run it as admin, it basically tells you you're not running as admin. 248 00:20:31,910 --> 00:20:33,330 You should be running as admin. 249 00:20:33,330 --> 00:20:38,190 Because if you're not running as admin, you can't see everything that happens in the computer. 250 00:20:38,350 --> 00:20:40,770 You can't see what the application does. 251 00:20:40,770 --> 00:20:42,490 You can't get the big picture. 252 00:20:43,430 --> 00:20:44,590 It's open source. 253 00:20:44,770 --> 00:20:54,130 The GUI is based on electron.net, which is, again, another open source project, which is basically electron, but for .net. 254 00:20:55,930 --> 00:20:58,170 Which is... I mean, it works, right? 255 00:20:59,170 --> 00:21:06,190 So after I created the... I'm sorry, after I installed the app and ran it for the first time, I saw this pop-up. 256 00:21:06,190 --> 00:21:14,430 And this is a Windows firewall pop-up that says, oh, this app wants to listen on all interfaces and open ports in the firewall. 257 00:21:14,530 --> 00:21:19,890 And I was wondering, why would a local application, a tag surface analyzer, want to do that? 258 00:21:19,890 --> 00:21:28,870 So I looked at the console logs for the app, and I saw that, yeah, it is listening on all interfaces, 0, 0, 0, 0, port 8001. 259 00:21:29,470 --> 00:21:31,550 That sounds really great. 260 00:21:31,690 --> 00:21:33,790 So I started to dig further. 261 00:21:33,790 --> 00:21:38,810 I mean, this was the cue to tell me that there might be something wrong with this application. 262 00:21:38,810 --> 00:21:43,850 So I go to port 8001 on my own, on the... 263 00:21:43,850 --> 00:21:49,890 I'm sorry, on the machine that is running the tag surface analyzer app, and I see the GUI. 264 00:21:49,890 --> 00:21:55,530 So the way the app works is it has an Electron frontend and a web server in the back. 265 00:21:55,530 --> 00:22:08,790 Electron frontend just opens this website, similar to what is in the browser, as you can see, and it does REST, which is, I guess, normal for Electron applications. 266 00:22:08,790 --> 00:22:16,190 Next thing I did, I tried to connect to it from outside, because it's opening the port and listening on all interfaces. 267 00:22:16,190 --> 00:22:17,790 I might be able to talk to it. 268 00:22:17,790 --> 00:22:20,770 So this is from the virtual machine host. 269 00:22:21,050 --> 00:22:26,170 I went to the virtual machine on 8001, and it didn't work. 270 00:22:26,370 --> 00:22:29,150 I saw this error that says invalid hosting. 271 00:22:29,730 --> 00:22:33,010 So I was looking at it, what is wrong with that? 272 00:22:33,010 --> 00:22:43,210 I went and saw it's because the web server that is serving content is a Kestrel web server, which is an ASP.NET web server. 273 00:22:43,210 --> 00:22:46,650 I'm sorry, a web server written in ASP.NET. 274 00:22:46,830 --> 00:22:50,690 It has a host header filtering. 275 00:22:50,950 --> 00:22:53,870 So when you see the request, it looks at the host header. 276 00:22:53,870 --> 00:22:57,710 If it's not local host, it says, I can't do it. 277 00:22:57,710 --> 00:23:11,470 But here's the thing, because we are connecting from outside, and we are not bound by being in a browser on the machine, I can change the host header because I can create a tool that talks to this and changes the host header. 278 00:23:11,470 --> 00:23:21,130 To do this, to simulate this, I added a match-replace ruling verb that whenever it saw the host header, it would replace it with local host. 279 00:23:21,230 --> 00:23:24,410 And that means I would be able to connect to it. 280 00:23:24,870 --> 00:23:30,950 So this is me connecting to the app from outside. 281 00:23:30,950 --> 00:23:33,590 And doing quest.scripting. 282 00:23:33,590 --> 00:23:41,150 The next thing I did is I wanted to check if there was a way that I can do inject JavaScript, because I want to get remote code execution. 283 00:23:41,550 --> 00:23:49,270 Fortunately, the app only has one place to do user input, and that's the name of the run or snapshot. 284 00:23:49,390 --> 00:23:56,910 Again, fortunately for me, it was vulnerable to vanilla script, alert one script JavaScript. 285 00:23:56,910 --> 00:24:06,410 So when you start a run, you type the name of the run, script alert one script, and then you start it. 286 00:24:06,410 --> 00:24:10,890 At the bottom of the picture, you can see where it says status report for dot. 287 00:24:11,030 --> 00:24:16,270 The place before dot is where the script was injected, and the alert pops up. 288 00:24:17,370 --> 00:24:27,230 So this is in the web application from outside, but I want to run JavaScript code on the Electron app inside, and I got really lucky. 289 00:24:27,650 --> 00:24:49,750 Because when you go to the Electron GUI inside the app, and someone has already started a run from outside, the alert pops up, which is really interesting and really useful for us, because I can start a run from outside, and I can get a pop-up on a user inside. 290 00:24:50,090 --> 00:24:53,230 And the way to create a run is a simple GET request. 291 00:24:53,230 --> 00:24:59,490 And as you can see, it's a simple request, so it always goes through, which is really great again for me. 292 00:24:59,490 --> 00:25:04,330 So I started looking at it, and I was like, okay, so what can I do? 293 00:25:04,510 --> 00:25:06,450 How can I use this? 294 00:25:06,590 --> 00:25:09,430 So I created a payload and a proof of concept. 295 00:25:10,110 --> 00:25:17,530 I start the Electron app in the virtual machine, then I go to it from the virtual machine host from outside. 296 00:25:17,530 --> 00:25:24,290 I start a new run, I paste the payload, that pops calc, which is, again, a simple GET request. 297 00:25:24,450 --> 00:25:35,030 Now the run is completed, I go to the Electron app, and I click on scan, and the calc pops up, which is the payload that I injected into it. 298 00:25:35,030 --> 00:25:39,730 And now, remember, attack surface analyzer is running as admin. 299 00:25:39,730 --> 00:25:44,150 That means someone from outside can connect to your machine and get remote code execution. 300 00:25:45,010 --> 00:25:46,030 Nice, right? 301 00:25:46,030 --> 00:25:50,330 So I reported it to Microsoft. 302 00:25:50,330 --> 00:26:00,190 I did responsible disclosure, they fixed it, and then I did a write-up after they said something is fixed, and it gained a little bit of traction. 303 00:26:01,130 --> 00:26:13,350 But what happened is Taviso replied to the tweet and said, I hope they actually fixed the injection point, and not just the single null interfaces, because the browser can connect to it. 304 00:26:13,490 --> 00:26:19,450 And I was thinking and said, yeah, that is exactly it. 305 00:26:19,450 --> 00:26:33,250 So I created a web page that sends this GET request, which is basically a way to pop calc in Node.js, and I want to do another proof of concept and see what is up. 306 00:26:33,330 --> 00:26:40,250 So I created a web page with that payload, and then opened the web page in the browser on the virtual machine. 307 00:26:40,250 --> 00:26:44,230 To the right you have the browser, to the left you have the Electron GUI. 308 00:26:44,230 --> 00:26:49,330 I open it, and the browser says, oh, I can't see the response because there's no cores. 309 00:26:49,330 --> 00:26:51,070 It doesn't really matter, does it? 310 00:26:51,070 --> 00:26:55,830 The GET request has already gone through, the damage is done, the run has been started. 311 00:26:55,830 --> 00:27:01,390 And now you click on the Electron app and go to scan, and calc pops up. 312 00:27:01,390 --> 00:27:02,110 Yay! 313 00:27:02,150 --> 00:27:13,170 So if the injection hadn't been fixed, and only the listening on all interfaces had been fixed, then we would have had a problem. 314 00:27:13,170 --> 00:27:25,430 Imagine you're running a tag surface analyzer on a machine, running it as admin, you open a website, and that website runs code on your machine, literally jumping the browser sandbox and getting back to your machine. 315 00:27:26,070 --> 00:27:27,410 So really fun. 316 00:27:28,310 --> 00:27:31,210 One of the funnest bugs I have found. 317 00:27:31,390 --> 00:27:38,050 Fortunately, I found a different bug that was much better than this. 318 00:27:38,050 --> 00:27:42,190 Unfortunately, it hasn't been disclosed yet, so I cannot talk about it today. 319 00:27:42,370 --> 00:27:47,550 But life is full of disappointments anyway, so that's one on top of the other ones. 320 00:27:48,050 --> 00:27:52,610 As a product security engineer, I do a lot of remediation. 321 00:27:52,610 --> 00:27:58,250 We have talked a lot about bugs and pointing at things and saying, this is bad, this is bad, and this is bad. 322 00:27:58,910 --> 00:28:03,710 But half of my job is talking to developers and telling them how to fix things. 323 00:28:03,710 --> 00:28:07,890 Or better yet, how we can eliminate an entire class of bugs together. 324 00:28:09,010 --> 00:28:13,670 This picture is from a YouTube video from a game design college. 325 00:28:13,670 --> 00:28:15,310 This is pretty old. 326 00:28:15,310 --> 00:28:22,090 These two guys are playing video games, and the boss comes in and says, have you guys finished this game? 327 00:28:22,090 --> 00:28:24,510 I need another video game designed. 328 00:28:24,510 --> 00:28:30,310 This guy says, we just finished level 3, so we need to tighten up the graphics a little bit. 329 00:28:31,470 --> 00:28:33,930 I don't know, for some reason I love it. 330 00:28:33,930 --> 00:28:44,770 Every time someone asks me what I do at my job, I tell them that I write how to tighten up the graphics a little bit of level 3. 331 00:28:44,830 --> 00:28:46,230 So it's a great thing. 332 00:28:46,230 --> 00:28:52,710 It's from Westwood College, which has nothing to do with the Westwood studios who made the Command & Conquer applications. 333 00:28:52,750 --> 00:28:55,750 I'm sorry, Command & Conquer games, which are now part of EA. 334 00:28:56,190 --> 00:28:58,390 So what can help us? 335 00:28:58,670 --> 00:29:02,550 Our most trustworthy friend, in this case, is the browser. 336 00:29:02,990 --> 00:29:08,890 I talked about how the browser doesn't help us, but the browsers can help us through the origin header. 337 00:29:08,890 --> 00:29:13,150 So origin header is set by the browsers on every cross-origin request. 338 00:29:13,250 --> 00:29:16,210 Example.net to facebook.com, you have an origin header. 339 00:29:16,210 --> 00:29:19,490 Example.net to example.net, don't have an origin header. 340 00:29:19,490 --> 00:29:23,750 It's a forbidden header, so JavaScript in the browsers cannot change it. 341 00:29:24,290 --> 00:29:31,790 So if you're a local web server, you see a request that comes in, you do not process the request before checking the origin header. 342 00:29:31,790 --> 00:29:35,350 You have an allow list of headers that are good. 343 00:29:35,350 --> 00:29:36,290 You check. 344 00:29:36,290 --> 00:29:39,210 If it works, then you get to let the request go through. 345 00:29:39,210 --> 00:29:41,410 Do not rely on same-origin policy. 346 00:29:41,410 --> 00:29:45,950 We already know that the simple GET requests are not going to go through. 347 00:29:45,950 --> 00:29:48,450 Do not learn cross-origin resource sharing. 348 00:29:48,450 --> 00:29:50,330 We don't need to see the response. 349 00:29:50,330 --> 00:29:53,950 We sent a GET request, we got remote code execution. 350 00:29:54,430 --> 00:29:58,190 Check the origin header before processing the request. 351 00:29:58,290 --> 00:30:00,910 Same thing can help us with WebSockets. 352 00:30:00,910 --> 00:30:07,550 Again, with WebSockets, they are not bound by the same-origin policy, but the handshake was a GET request. 353 00:30:07,550 --> 00:30:14,250 So when you see a handshake in your WebSocket server, you do not process it, you do not respond. 354 00:30:14,250 --> 00:30:15,630 You check the origin header. 355 00:30:15,630 --> 00:30:20,070 If it's something that you want, then you send a correct response. 356 00:30:20,070 --> 00:30:26,370 If it's not, do something like what Logitech Hub did, return a 403, 404, or whatever. 357 00:30:26,370 --> 00:30:30,230 Anything that tells the browser that this request was not successful. 358 00:30:30,230 --> 00:30:35,530 That means the WebSocket is not going to get created. 359 00:30:35,870 --> 00:30:40,690 One thing that I've seen developers do that is not useful is checking the remote address. 360 00:30:40,690 --> 00:30:44,270 That's where the request is coming from. 361 00:30:44,270 --> 00:30:51,730 This works to some extent if you have something listening along interfaces and don't want local address, you only want local addresses. 362 00:30:51,730 --> 00:31:07,970 But that's not useful in browsers, because if a request is coming from your browser, the browser is running on your machine, the JavaScript is running in the browser, and as a result, the remote address of the request coming from the browser from a website, 363 00:31:07,970 --> 00:31:12,950 example.net, is actually local host because the browser is running on your machine. 364 00:31:13,770 --> 00:31:15,010 That's really useful. 365 00:31:15,170 --> 00:31:16,190 Don't do that. 366 00:31:16,750 --> 00:31:22,850 I know, it took a little bit of time to wrap my head around this, but I finally got it. 367 00:31:23,130 --> 00:31:25,990 It's a simple check, so check the origin header. 368 00:31:25,990 --> 00:31:31,870 With Electron, there's a lot of advice, but I'm going to give you some generic XSS advice. 369 00:31:31,870 --> 00:31:35,010 Don't trust user input because you don't want XSS. 370 00:31:35,690 --> 00:31:46,070 But more importantly, in order to eliminate an entire class of bugs, you set node integration to false, which is off by default. 371 00:31:46,070 --> 00:31:49,230 Don't set it to true if you don't absolutely need it. 372 00:31:49,350 --> 00:31:56,230 A lot of developers set it to true because the Electron app needs to run Node.js code in the back. 373 00:31:58,130 --> 00:32:01,370 And I don't really blame them because it's very convenient. 374 00:32:01,770 --> 00:32:07,510 But what you can do is you can run your Node.js code in preload. 375 00:32:07,510 --> 00:32:12,590 So preload is a script that gets loaded in the browser window before everything else. 376 00:32:12,590 --> 00:32:20,370 Even if you have set node integration to false, the JavaScript in the preload has access to the Node.js API. 377 00:32:20,370 --> 00:32:28,350 So that means that you can't run your own Node.js code and you can't have node integration set to false. 378 00:32:28,350 --> 00:32:34,190 Even if you have XSS in this case, you have XSS, which is really not great. 379 00:32:34,190 --> 00:32:37,650 But on the plus side, you won't have remote code execution. 380 00:32:37,710 --> 00:32:47,810 If you click on the link in the Electron.js website, they have a lot of useful information on how to prevent these attacks, how to do things properly. 381 00:32:47,810 --> 00:32:56,790 If you use a local web server to serve content to an Electron app, disable cores. 382 00:32:56,990 --> 00:33:06,370 So if you have a local web server, so there was this app I was looking at, a third-party app, and it was running a local web server system that had a front-end Electron. 383 00:33:06,370 --> 00:33:19,950 They had enabled cores on the web server, so basically access control allow origin was star, which is not really great, because that means any browser could talk to the web server and grab the results. 384 00:33:19,950 --> 00:33:26,410 There was no sort of checking the path, so any website could read all files on your machine. 385 00:33:26,410 --> 00:33:32,170 And the server was running a system, which means that it could read everything, and that's not really great. 386 00:33:32,170 --> 00:33:33,890 That's not something you want to do. 387 00:33:33,890 --> 00:33:40,370 So disable cores, that means you are not leaking information to websites when they talk to it. 388 00:33:40,370 --> 00:33:44,390 And last but not least, you want to add browsers to your thread models. 389 00:33:45,250 --> 00:33:47,030 So this is Crypto. 390 00:33:47,030 --> 00:33:52,630 He's a hacker character in Apex Legends, the video game. 391 00:33:54,350 --> 00:34:01,910 Crypto doesn't need to be in an internet cafe somewhere and directly connected to a machine to be enabled as a hacker machine. 392 00:34:02,290 --> 00:34:19,830 If you have one of these servers on your machine, and you go to a website where Crypto controls, or if Crypto has injected JavaScript into, and he might get remote code execution on your machine, and as a result, he's now listening to what you are saying on the machine, 393 00:34:19,830 --> 00:34:22,410 listening to a Discord conversation, so on and so forth. 394 00:34:22,410 --> 00:34:23,770 So don't do that. 395 00:34:23,770 --> 00:34:31,270 If you have a local server, think browsers can connect to it and add them to a thread model, have your proper checks. 396 00:34:31,990 --> 00:34:37,350 As I said, checks are really simple and we can defeat it and we'll be fine. 397 00:34:37,350 --> 00:34:48,950 So I've talked a lot about how to find things, how to fix things, but your next question is, how do I get started in this niche? 398 00:34:49,370 --> 00:34:52,170 Practice is the best thing. 399 00:34:52,170 --> 00:34:59,050 Start a virtual machine, install a bunch of these client apps, run Headstat, see what servers you have. 400 00:34:59,050 --> 00:35:09,930 Start poking at those servers, look at the cores, look at the APIs they expose. 401 00:35:10,330 --> 00:35:15,350 The peripheral utility apps are really great candidates. 402 00:35:15,350 --> 00:35:23,970 If you have a mouse that comes with a utility to control it, they are usually good candidates. 403 00:35:24,090 --> 00:35:28,610 Or you can go to that link on Electron.js website, which has all the Electron apps. 404 00:35:28,610 --> 00:35:31,430 Electron apps are usually to have the same thing. 405 00:35:31,430 --> 00:35:43,830 If you want to learn more about hacking Electron, there is a GitHub repository with a bunch of links , a lot of useful information, a lot of great research, a lot of great books. 406 00:35:43,990 --> 00:35:46,690 And last but not least, read Taviso books. 407 00:35:47,190 --> 00:35:56,190 The awesome book that I told you about that hasn't been disclosed, it was two Taviso books mixed together. 408 00:35:56,190 --> 00:35:59,890 So I combined two of them and it worked. 409 00:36:00,130 --> 00:36:02,330 So that was great. 410 00:36:03,510 --> 00:36:07,050 And finally, thanks for giving me your time. 411 00:36:07,110 --> 00:36:12,350 Because this is recorded, so I can't answer your questions on the fly in this presentation. 412 00:36:12,350 --> 00:36:17,910 What's going to happen is I'm going to be on the Discord and I will answer your questions there and then. 413 00:36:17,910 --> 00:36:29,590 To find more about me or if you want to ask questions, you can contact me on those social media links, Twitter or my website or on GitHub. 414 00:36:29,610 --> 00:36:32,970 If you have any questions, I'll be happy to answer. 415 00:36:32,990 --> 00:36:39,010 Again, thanks for listening to my presentation and giving me your time. 416 00:36:39,090 --> 00:36:42,650 And fingers crossed, 2020 won't get worse than this. 417 00:36:42,650 --> 00:36:44,110 We can get through this. 418 00:36:44,110 --> 00:36:45,610 Have a great day.