1 00:00:01,230 --> 00:00:03,308 - Anyway, this is Steve, Sam and the Door. 2 00:00:03,308 --> 00:00:05,808 (Intro music) 3 00:00:07,290 --> 00:00:08,904 Let's give a big DEFCON welcome. 4 00:00:08,904 --> 00:00:12,071 (audience applauding) 5 00:00:14,340 --> 00:00:15,570 - Afternoon, everyone. 6 00:00:15,570 --> 00:00:16,403 Welcome. 7 00:00:16,403 --> 00:00:17,550 Thanks for having us here. 8 00:00:17,550 --> 00:00:18,480 You may not believe it, 9 00:00:18,480 --> 00:00:20,624 but not only was that our first shot at DEFCON, 10 00:00:20,624 --> 00:00:22,620 it was actually our first shot ever. 11 00:00:22,620 --> 00:00:25,170 Since this we got away from breakfast this morning, anyway. 12 00:00:25,170 --> 00:00:27,630 So, all right, well welcome guys. 13 00:00:27,630 --> 00:00:28,500 Thanks for having us. 14 00:00:28,500 --> 00:00:31,378 We're here to talk about the conclusion of our research. 15 00:00:31,378 --> 00:00:33,000 Feels like it's been a long time 16 00:00:33,000 --> 00:00:34,923 into hacking an access control system. 17 00:00:34,923 --> 00:00:36,983 So this is called Perimeter Breach. 18 00:00:36,983 --> 00:00:38,758 My name is Steve Povolny, 19 00:00:38,758 --> 00:00:40,470 Head of Advanced Threat Research 20 00:00:40,470 --> 00:00:42,540 and Principal Engineer at Trellix, 21 00:00:42,540 --> 00:00:43,740 and my Twitter handles here, 22 00:00:43,740 --> 00:00:45,501 if you wanna connect afterwards. 23 00:00:45,501 --> 00:00:48,360 Most of the team makes fun of me since I'm a manager. 24 00:00:48,360 --> 00:00:50,430 Usually they joke that I'm not allowed to do anything 25 00:00:50,430 --> 00:00:51,810 but Excel spreadsheets, 26 00:00:51,810 --> 00:00:53,160 which I can write a mean function, 27 00:00:53,160 --> 00:00:54,930 but when I'm doing technical stuff, 28 00:00:54,930 --> 00:00:58,290 I'm interested in vulnerability root cause analysis, 29 00:00:58,290 --> 00:01:00,810 reverse engineering, exploitation, 30 00:01:00,810 --> 00:01:02,820 and actually with this project got some experience 31 00:01:02,820 --> 00:01:04,870 for the first time with Hardware Hacking. 32 00:01:05,850 --> 00:01:07,500 - And my name is Sam Quinn. 33 00:01:07,500 --> 00:01:10,320 I'm a Senior Security Researcher at Trellix. 34 00:01:10,320 --> 00:01:12,540 I could have summed all this up, which is hacking. 35 00:01:12,540 --> 00:01:14,490 I really like all aspects of it, 36 00:01:14,490 --> 00:01:17,520 but some of my core technical interests are listed here. 37 00:01:17,520 --> 00:01:19,861 I like exploitation, hardware hacking, 38 00:01:19,861 --> 00:01:21,690 looking at VETEM systems, 39 00:01:21,690 --> 00:01:23,790 like IOT devices and things like that, 40 00:01:23,790 --> 00:01:25,390 as well as just OS fundamentals. 41 00:01:26,850 --> 00:01:28,800 - Now, Sam and I have interests outside 42 00:01:28,800 --> 00:01:30,150 of just hacking and computers, 43 00:01:30,150 --> 00:01:32,610 and we're both avid mountain bikers as well, 44 00:01:32,610 --> 00:01:35,430 as you'll see when we're not in the lab finding crashes, 45 00:01:35,430 --> 00:01:37,080 we're somewhere out there and crashes managed 46 00:01:37,080 --> 00:01:38,280 to find us either way. 47 00:01:38,280 --> 00:01:40,178 So, this is real footage by the way. 48 00:01:40,178 --> 00:01:41,984 We're not faking anything here. 49 00:01:41,984 --> 00:01:43,936 All right, let's get right to it. 50 00:01:43,936 --> 00:01:45,420 The target for today, 51 00:01:45,420 --> 00:01:49,260 and what we chose is the HID Mercury Access Control Panel, 52 00:01:49,260 --> 00:01:52,200 which is this beautiful bright red board that you see. 53 00:01:52,200 --> 00:01:53,932 We chose the Lenel-4420, 54 00:01:53,932 --> 00:01:56,580 which is a partner of HID mercury. 55 00:01:56,580 --> 00:01:58,830 And the reason we got interested in it, 56 00:01:58,830 --> 00:02:00,780 we're gonna talk about the how, the what, 57 00:02:00,780 --> 00:02:02,490 the why's, of this project. 58 00:02:02,490 --> 00:02:03,968 But we got interested in it because, 59 00:02:03,968 --> 00:02:06,750 obviously access control is one of those areas 60 00:02:06,750 --> 00:02:10,110 of critical infrastructure and industrial control systems, 61 00:02:10,110 --> 00:02:11,700 that is really prevalent 62 00:02:11,700 --> 00:02:14,460 in this increasingly targeted attack space, 63 00:02:14,460 --> 00:02:16,470 and really has not been widely researched, 64 00:02:16,470 --> 00:02:18,000 especially over the past few years. 65 00:02:18,000 --> 00:02:20,757 So we got interested in it for that reason. 66 00:02:20,757 --> 00:02:22,257 Before we get into the 'why' 67 00:02:22,257 --> 00:02:23,950 and the 'how' we did this project, 68 00:02:23,950 --> 00:02:27,000 let's set the stage for how this is typically deployed? 69 00:02:27,000 --> 00:02:29,100 Well, you see this beautiful door on stage 70 00:02:29,100 --> 00:02:31,920 that we unceremoniously brought in halfway 71 00:02:31,920 --> 00:02:34,230 through the last person's presentation. 72 00:02:34,230 --> 00:02:37,440 This is actually the Lenel card reader controller 73 00:02:37,440 --> 00:02:39,090 is plugged in behind there, 74 00:02:39,090 --> 00:02:40,860 and we have a managed to a badge reader. 75 00:02:40,860 --> 00:02:43,560 This is typically gonna be deployed on a local network. 76 00:02:43,560 --> 00:02:46,980 It is possible to make this cloud facing or internet facing, 77 00:02:46,980 --> 00:02:49,020 but highly non recommended. 78 00:02:49,020 --> 00:02:52,740 The panel itself can manage up to 64 different devices. 79 00:02:52,740 --> 00:02:54,780 In this case, we're using a badge reader 80 00:02:54,780 --> 00:02:57,120 and being on a local network. 81 00:02:57,120 --> 00:02:59,680 We use a local network manager or an LSM 82 00:02:59,680 --> 00:03:02,190 to actually manage the door operations. 83 00:03:02,190 --> 00:03:05,160 And for Lenel, that's this server called OnGuard. 84 00:03:05,160 --> 00:03:06,450 That's the server that's responsible 85 00:03:06,450 --> 00:03:09,570 for facilitating all of the user control, 86 00:03:09,570 --> 00:03:12,123 badges, access, all of that provisioning. 87 00:03:12,123 --> 00:03:15,480 And then the board itself is kind of a dumb control relay 88 00:03:15,480 --> 00:03:17,760 it essentially just flipped electric relays 89 00:03:17,760 --> 00:03:20,580 and we'll talk about that quite a bit more. 90 00:03:20,580 --> 00:03:22,260 Well, one of the things that first caught our eyes 91 00:03:22,260 --> 00:03:24,180 when we were exploring this target, 92 00:03:24,180 --> 00:03:27,090 this 4400 panel was some marketing material 93 00:03:27,090 --> 00:03:28,530 from Lenel that had specified 94 00:03:28,530 --> 00:03:29,700 that this had been approved 95 00:03:29,700 --> 00:03:31,500 for use in government facilities 96 00:03:31,500 --> 00:03:33,870 following rigorous security, vulnerability, 97 00:03:33,870 --> 00:03:35,730 and interoperability testing. 98 00:03:35,730 --> 00:03:38,130 Well, obviously this really kind of intrigued us. 99 00:03:38,130 --> 00:03:40,410 We found out through the research process 100 00:03:40,410 --> 00:03:43,918 that this has intended to specify physical security testing, 101 00:03:43,918 --> 00:03:46,050 but really led us down the track of saying, 102 00:03:46,050 --> 00:03:49,020 how does this hold up from a cyber security perspective? 103 00:03:49,020 --> 00:03:51,330 And that's what led us to these findings. 104 00:03:51,330 --> 00:03:52,710 Now we did originally disclose 105 00:03:52,710 --> 00:03:55,860 all of this just a couple months ago at hardware IO, 106 00:03:55,860 --> 00:03:57,780 where we spent a lot more time focusing 107 00:03:57,780 --> 00:03:59,580 on the hardware hacking process 108 00:03:59,580 --> 00:04:00,840 and getting to a root shell, 109 00:04:00,840 --> 00:04:01,860 which we'll show you is gonna 110 00:04:01,860 --> 00:04:03,450 be our starting point for today. 111 00:04:03,450 --> 00:04:05,370 And so for the purposes of this talk, 112 00:04:05,370 --> 00:04:08,370 we're gonna focus on just three of the eight CVEs, 113 00:04:08,370 --> 00:04:11,460 but we submitted and ultimately got patched eight CVEs, 114 00:04:11,460 --> 00:04:13,380 four of which are zero day 115 00:04:13,380 --> 00:04:16,380 unauthenticated remote code execution vulnerabilities, 116 00:04:16,380 --> 00:04:18,300 or were at the time we disclosed them. 117 00:04:18,300 --> 00:04:20,373 These are now all fully patched. 118 00:04:21,240 --> 00:04:24,420 The who in this scenario is who was affected by this. 119 00:04:24,420 --> 00:04:26,130 And as you can see here, 120 00:04:26,130 --> 00:04:28,950 the 4420 panel was the one that we chose 121 00:04:28,950 --> 00:04:31,320 and ordered off of eBay for a few hundred bucks. 122 00:04:31,320 --> 00:04:33,030 But throughout the research process, 123 00:04:33,030 --> 00:04:36,720 we did find out that additional eight boards manufactured 124 00:04:36,720 --> 00:04:40,290 by HID were also vulnerable to these same issues. 125 00:04:40,290 --> 00:04:42,600 And so there was a much wider install base 126 00:04:42,600 --> 00:04:44,490 than we had originally thought. 127 00:04:44,490 --> 00:04:46,830 Furthermore, there's more than 20 partners 128 00:04:46,830 --> 00:04:48,960 of HID Mercury, including Lenel 129 00:04:48,960 --> 00:04:50,627 the board that we looked at there 130 00:04:50,627 --> 00:04:52,746 that used these boards and rely on them 131 00:04:52,746 --> 00:04:56,580 and all of them were vulnerable to the same issues as well. 132 00:04:56,580 --> 00:04:58,740 So this represents millions of controllers 133 00:04:58,740 --> 00:05:01,110 at tens of thousands of sites worldwide, 134 00:05:01,110 --> 00:05:03,900 and really the vast majority of the Fortune 100 companies. 135 00:05:03,900 --> 00:05:06,363 So the install base is pretty impactful. 136 00:05:07,320 --> 00:05:08,970 We chose to approach this project 137 00:05:08,970 --> 00:05:10,950 and what we call choose your pwn adventure, 138 00:05:10,950 --> 00:05:13,710 a little spin on the classical phrase here. 139 00:05:13,710 --> 00:05:14,880 And what that means to us 140 00:05:14,880 --> 00:05:16,740 is we're gonna explain the process we took 141 00:05:16,740 --> 00:05:18,630 at various iterations of the project 142 00:05:18,630 --> 00:05:21,473 and the decisions we made at those steps and why. 143 00:05:21,473 --> 00:05:24,570 Now again, I mentioned how we have already disclosed 144 00:05:24,570 --> 00:05:26,033 these issues at hardwear.io. 145 00:05:26,033 --> 00:05:28,170 So for today, we're gonna start assuming 146 00:05:28,170 --> 00:05:29,910 we have a Root Shell on the device, 147 00:05:29,910 --> 00:05:32,310 which we do and we're gonna actually live hack 148 00:05:32,310 --> 00:05:35,040 it in iterations on stage here throughout the process. 149 00:05:35,040 --> 00:05:36,570 So of course, what could go wrong? 150 00:05:36,570 --> 00:05:37,770 We're not doing just one demo, 151 00:05:37,770 --> 00:05:39,060 but like three live ones. 152 00:05:39,060 --> 00:05:41,520 So we're gonna really tempt the demo gods. 153 00:05:41,520 --> 00:05:43,500 This is all a network vulnerability. 154 00:05:43,500 --> 00:05:45,360 So you have to be on the same network as the device, 155 00:05:45,360 --> 00:05:47,790 which many of you know is kind of the low bar 156 00:05:47,790 --> 00:05:49,500 of exploitation, but either way, 157 00:05:49,500 --> 00:05:51,483 these are unauthenticated RCEs. 158 00:05:52,440 --> 00:05:54,570 As far as standard operations for the panel, 159 00:05:54,570 --> 00:05:56,610 one of the first things we looked at was 160 00:05:56,610 --> 00:05:58,470 of course doing a network scan 161 00:05:58,470 --> 00:06:01,590 and we used Nmap to find just these three open ports. 162 00:06:01,590 --> 00:06:02,820 I know with the lights, 163 00:06:02,820 --> 00:06:04,080 it might be kind of hard to read. 164 00:06:04,080 --> 00:06:06,180 So just like throw your hand up if you can't see 165 00:06:06,180 --> 00:06:07,680 you're interested in something, 166 00:06:07,680 --> 00:06:10,560 but the ports that were showed up on the scan 167 00:06:10,560 --> 00:06:13,590 were Port 80 and 443 for the embedded web server 168 00:06:13,590 --> 00:06:16,950 that runs and a separate port 3001, 169 00:06:16,950 --> 00:06:18,480 which at the time we didn't know what it did 170 00:06:18,480 --> 00:06:20,460 and found out later that was that management server, 171 00:06:20,460 --> 00:06:22,050 the OnGuard management server, 172 00:06:22,050 --> 00:06:24,450 how it communicates to the panel directly, 173 00:06:24,450 --> 00:06:25,950 but because we bought it off eBay, 174 00:06:25,950 --> 00:06:28,230 we had kind of this half baked solution 175 00:06:28,230 --> 00:06:30,780 and we didn't have the OnGuard setup at this point. 176 00:06:31,650 --> 00:06:33,630 When you boot up the web server on the device, 177 00:06:33,630 --> 00:06:35,900 which comes on automatically and by default, 178 00:06:35,900 --> 00:06:39,180 you're greeted with a typical login screen, admin password. 179 00:06:39,180 --> 00:06:40,530 You'll see this in a moment. 180 00:06:40,530 --> 00:06:42,720 It does pretty standard session management, 181 00:06:42,720 --> 00:06:45,810 including cookies for the most part, 182 00:06:45,810 --> 00:06:47,790 little preview of things to come there. 183 00:06:47,790 --> 00:06:49,770 It does it quite well. 184 00:06:49,770 --> 00:06:51,930 Configuration pages are primarily 185 00:06:51,930 --> 00:06:54,150 what you see inside of this web server. 186 00:06:54,150 --> 00:06:55,800 So if you look closely, 187 00:06:55,800 --> 00:06:57,600 there's almost nothing that's related 188 00:06:57,600 --> 00:07:01,020 to actual badge usage or anything related to doors. 189 00:07:01,020 --> 00:07:03,076 This web server is used to configure the panel 190 00:07:03,076 --> 00:07:06,059 and then it becomes kind of useless from that point on 191 00:07:06,059 --> 00:07:08,220 where you'll take over with the OnGuard server 192 00:07:08,220 --> 00:07:10,900 and do all of the door specific functions. 193 00:07:10,900 --> 00:07:13,500 The network setup page really caught our attention. 194 00:07:13,500 --> 00:07:14,850 It has a number of inputs. 195 00:07:14,850 --> 00:07:15,960 We'll show you why it was really 196 00:07:15,960 --> 00:07:17,095 interesting in a moment here. 197 00:07:17,095 --> 00:07:19,410 For right now, you can just see that it's managing 198 00:07:19,410 --> 00:07:20,610 the host name of the device 199 00:07:20,610 --> 00:07:22,560 and we'll come back to that. 200 00:07:22,560 --> 00:07:23,820 All right, so that brings us 201 00:07:23,820 --> 00:07:25,560 to choose your pwn adventure number one, 202 00:07:25,560 --> 00:07:27,720 where early in this project we were just trying 203 00:07:27,720 --> 00:07:30,420 to look for an RCE our first zero day 204 00:07:30,420 --> 00:07:31,918 and hypothetically unauthenticated. 205 00:07:31,918 --> 00:07:35,340 Three different areas that we could have explored here. 206 00:07:35,340 --> 00:07:38,190 The first one being an operating system, vulnerability, 207 00:07:38,190 --> 00:07:39,810 this would include things like the vendor 208 00:07:39,810 --> 00:07:41,777 and product specific libraries and files, 209 00:07:41,777 --> 00:07:43,920 keys, creds, crypto, 210 00:07:43,920 --> 00:07:45,030 you know the typical stuff here, 211 00:07:45,030 --> 00:07:46,292 maybe configuration flaws. 212 00:07:46,292 --> 00:07:48,810 We chose to go with more of a combination 213 00:07:48,810 --> 00:07:50,639 of web based and network vulnerability. 214 00:07:50,639 --> 00:07:53,520 And we decided to look at things like command injection, 215 00:07:53,520 --> 00:07:55,503 because we had a web server that took user input 216 00:07:55,503 --> 00:07:58,290 and directly contacted the board and work with the board. 217 00:07:58,290 --> 00:08:00,480 So bypassing the network stack, 218 00:08:00,480 --> 00:08:01,650 which would've really been looking 219 00:08:01,650 --> 00:08:04,350 for probably an end day or maybe a really cool Oday 220 00:08:04,350 --> 00:08:07,978 in third party libraries or networking stack itself. 221 00:08:07,978 --> 00:08:10,530 So the process we went about as we decided 222 00:08:10,530 --> 00:08:12,090 to look at the web form, 223 00:08:12,090 --> 00:08:13,680 and of course we're shortening this a little bit, 224 00:08:13,680 --> 00:08:15,570 but one of the areas that was interesting 225 00:08:15,570 --> 00:08:18,120 was command injection and our injection candidate 226 00:08:18,120 --> 00:08:20,370 here was the device host name itself. 227 00:08:20,370 --> 00:08:22,650 If you look at one of the root processes that spun up, 228 00:08:22,650 --> 00:08:24,120 when the board boots here, 229 00:08:24,120 --> 00:08:25,880 there's a DHCP call where it does all 230 00:08:25,880 --> 00:08:27,109 of the network factoring. 231 00:08:27,109 --> 00:08:30,660 And one of the parameters to that DHCP call 232 00:08:30,660 --> 00:08:33,210 is dash H or host name of the controller 233 00:08:33,210 --> 00:08:34,770 In this case, it's controller one 234 00:08:34,770 --> 00:08:36,643 and we can see by catting out the host name file 235 00:08:36,643 --> 00:08:39,150 that it is coming from the controller one. 236 00:08:39,150 --> 00:08:41,568 So if we can control input through the web server 237 00:08:41,568 --> 00:08:44,640 and get it to actually execute commands as root, 238 00:08:44,640 --> 00:08:47,280 that's a pretty cool command injection. 239 00:08:47,280 --> 00:08:49,290 Now, before we talk about that some more 240 00:08:49,290 --> 00:08:50,786 let's look at what are the restrictions. 241 00:08:50,786 --> 00:08:53,670 Everybody has client side, JavaScript restrictions. 242 00:08:53,670 --> 00:08:54,810 This is no different. 243 00:08:54,810 --> 00:08:56,340 What you'll see here if you can't read it 244 00:08:56,340 --> 00:08:59,490 is this is a alpha numeric and period and hyphen 245 00:08:59,490 --> 00:09:02,280 are the only characters allowed on the client side. 246 00:09:02,280 --> 00:09:04,110 When we look at the actual JavaScript, 247 00:09:04,110 --> 00:09:05,910 it matches up very well to the string. 248 00:09:05,910 --> 00:09:08,913 It's only allowing alpha numeric and period and hyphen. 249 00:09:09,780 --> 00:09:10,710 On the server side, 250 00:09:10,710 --> 00:09:12,960 there's a function called XSS string test 251 00:09:12,960 --> 00:09:14,970 for cross-site scripting string test 252 00:09:14,970 --> 00:09:16,380 and that looks for some additional 253 00:09:16,380 --> 00:09:18,000 kind of funky characters here, 254 00:09:18,000 --> 00:09:19,890 of course tied to cross-site scripting 255 00:09:19,890 --> 00:09:21,046 and other injection attacks. 256 00:09:21,046 --> 00:09:23,127 But for us the ones that were most harmful 257 00:09:23,127 --> 00:09:25,740 to work around were the forward slash of course, 258 00:09:25,740 --> 00:09:28,170 if we wanted to do a path and a command injection, 259 00:09:28,170 --> 00:09:30,519 the ampersand and the semicolon character 260 00:09:30,519 --> 00:09:33,434 for eliminating commands. 261 00:09:33,434 --> 00:09:37,376 One final thing here was this parse forms data function. 262 00:09:37,376 --> 00:09:39,600 And the thing to pay attention to here 263 00:09:39,600 --> 00:09:41,565 is this a string tokenizer function, 264 00:09:41,565 --> 00:09:43,980 which will split our host name every time it sees 265 00:09:43,980 --> 00:09:45,446 either an equals or space. 266 00:09:45,446 --> 00:09:47,370 Equals we probably don't care about, 267 00:09:47,370 --> 00:09:49,290 but the space is a really useful character 268 00:09:49,290 --> 00:09:50,430 in command injection 269 00:09:50,430 --> 00:09:53,040 and so we had to find a way around that. 270 00:09:53,040 --> 00:09:53,940 Before we get into that, 271 00:09:53,940 --> 00:09:56,550 let's talk about authentication and how it's handled. 272 00:09:56,550 --> 00:09:58,380 For Get and Post this is kind of funny here. 273 00:09:58,380 --> 00:10:01,503 So Get requests are handled exactly as you'd imagine. 274 00:10:01,503 --> 00:10:03,270 A session ID is created 275 00:10:03,270 --> 00:10:05,670 by calling Get session ID and return. 276 00:10:05,670 --> 00:10:07,830 And then as you'd expect that session ID 277 00:10:07,830 --> 00:10:10,050 is compared to the session ID that's taken 278 00:10:10,050 --> 00:10:11,310 from the cookie value. 279 00:10:11,310 --> 00:10:13,860 If it checks out the page is authenticated. 280 00:10:13,860 --> 00:10:15,030 Now for Post requests, 281 00:10:15,030 --> 00:10:18,120 it's done slightly differently and pretty poorly here. 282 00:10:18,120 --> 00:10:20,109 So if calls get session ID from cookie 283 00:10:20,109 --> 00:10:22,410 so good or so far so good, 284 00:10:22,410 --> 00:10:24,360 but then it never compares that to anything 285 00:10:24,360 --> 00:10:27,167 so we can use any arbitrary session cookie value. 286 00:10:27,167 --> 00:10:30,966 You'll see Sam use 13371337 in a moment here, 287 00:10:30,966 --> 00:10:34,326 and we can send any Post data completely unauthenticated. 288 00:10:34,326 --> 00:10:36,810 It'll actually redirect to get requests 289 00:10:36,810 --> 00:10:37,770 looking like it failed, 290 00:10:37,770 --> 00:10:39,540 but it'll actually send the data. 291 00:10:39,540 --> 00:10:41,400 All right, let's temp the demo gods 292 00:10:41,400 --> 00:10:43,050 and Sam you wanna take over 293 00:10:43,050 --> 00:10:45,060 and do a little live demo for us? 294 00:10:45,060 --> 00:10:46,560 - Oh yeah, thank you. 295 00:10:46,560 --> 00:10:47,810 All right, so here we go. 296 00:10:49,350 --> 00:10:53,730 Let's get the correct window where it should be, 297 00:10:53,730 --> 00:10:54,563 it's over here. 298 00:10:56,996 --> 00:11:01,546 I'm gonna go a little bit bigger hopefully that's better. 299 00:11:01,546 --> 00:11:05,490 Alright, so didn't clear this from our test before, 300 00:11:05,490 --> 00:11:07,490 but we're gonna start a listening server. 301 00:11:07,490 --> 00:11:10,650 This is gonna be kind of the command 302 00:11:10,650 --> 00:11:13,140 and control aspect of this. 303 00:11:13,140 --> 00:11:16,290 We'll kind of dive into this a little bit more in detail. 304 00:11:16,290 --> 00:11:17,310 However, we'll start that off 305 00:11:17,310 --> 00:11:19,980 and just had that run in the background. 306 00:11:19,980 --> 00:11:21,693 When we now go to, 307 00:11:22,812 --> 00:11:26,913 we'll actually bring up the web server. 308 00:11:29,730 --> 00:11:33,840 So this is actually the website 309 00:11:33,840 --> 00:11:37,020 that is running on the Linux system on the board itself. 310 00:11:37,020 --> 00:11:38,280 And of course, as you can see, 311 00:11:38,280 --> 00:11:41,550 there is a login page as normal. 312 00:11:41,550 --> 00:11:43,503 And if we go ahead and log in, 313 00:11:44,940 --> 00:11:46,890 it will indeed give us that cookie 314 00:11:46,890 --> 00:11:48,813 that Steve mentioned earlier. 315 00:11:51,420 --> 00:11:54,335 All right, so logging in and it might be hard to see, 316 00:11:54,335 --> 00:11:58,230 but over here, there are some session IDs 317 00:11:58,230 --> 00:12:00,090 getting appended to the GET requests. 318 00:12:00,090 --> 00:12:02,790 And if we looked into the Post parameters, 319 00:12:02,790 --> 00:12:05,160 there's also a cookie there as well, 320 00:12:05,160 --> 00:12:07,590 but we'll go over to that network host name 321 00:12:07,590 --> 00:12:10,080 that we wanted to command eject into. 322 00:12:10,080 --> 00:12:12,720 As you can see, it is controller one at the moment. 323 00:12:12,720 --> 00:12:15,780 And now if we go ahead and actually try 324 00:12:15,780 --> 00:12:18,360 to do our unauthentic command injection 325 00:12:18,360 --> 00:12:21,450 by running this command where it is, 326 00:12:21,450 --> 00:12:24,270 we saved it off CI one. 327 00:12:24,270 --> 00:12:25,710 So this is the command injection 328 00:12:25,710 --> 00:12:26,970 where it's now bypassing 329 00:12:26,970 --> 00:12:28,680 that JavaScript that Steve showed earlier, 330 00:12:28,680 --> 00:12:31,098 where it's restricting characters and whatnot. 331 00:12:31,098 --> 00:12:36,098 We do have the cookie as just a bogus 1337, 332 00:12:36,240 --> 00:12:38,040 super elite cookie there. 333 00:12:38,040 --> 00:12:40,830 And then the host name has this command injection 334 00:12:40,830 --> 00:12:42,810 that will cover in more detail in just a second. 335 00:12:42,810 --> 00:12:44,310 So hold on for that. 336 00:12:44,310 --> 00:12:45,450 But as you can see, 337 00:12:45,450 --> 00:12:48,120 there's really nothing here that should have allowed 338 00:12:48,120 --> 00:12:49,650 this to take place. 339 00:12:49,650 --> 00:12:51,363 So if we go ahead and run this, 340 00:12:53,250 --> 00:12:54,540 it looks like it failed. 341 00:12:54,540 --> 00:12:57,810 That's because the Post data actually did take effect, 342 00:12:57,810 --> 00:12:59,670 but then when it tries to refresh the page, 343 00:12:59,670 --> 00:13:01,110 the Get request actually failed 344 00:13:01,110 --> 00:13:03,480 so that's why we see this timeout error here. 345 00:13:03,480 --> 00:13:06,120 But if we go back to the webpage 346 00:13:06,120 --> 00:13:07,410 and actually refresh this 347 00:13:07,410 --> 00:13:08,970 by just clicking on network again, 348 00:13:08,970 --> 00:13:10,230 you can see now the host name 349 00:13:10,230 --> 00:13:13,260 is that big long command injection that we actually sent. 350 00:13:13,260 --> 00:13:14,640 That was all unauthenticated. 351 00:13:14,640 --> 00:13:15,900 Anyone could have done 352 00:13:15,900 --> 00:13:18,840 that without knowing the password or anything. 353 00:13:18,840 --> 00:13:20,970 So now we'll go back into our slides 354 00:13:20,970 --> 00:13:23,550 and I'll kind of explain why we chose 355 00:13:23,550 --> 00:13:27,480 that set of command injection characters and whatnot. 356 00:13:27,480 --> 00:13:30,360 So as Steve mentioned, this is not a space, 357 00:13:30,360 --> 00:13:34,410 but it works just as just the same in Linux interpreters. 358 00:13:34,410 --> 00:13:36,060 So that is actually a tab character, 359 00:13:36,060 --> 00:13:38,370 and that was not bypassed or checked 360 00:13:38,370 --> 00:13:40,719 in that XSS string test function. 361 00:13:40,719 --> 00:13:42,390 And as Steve also mentioned, 362 00:13:42,390 --> 00:13:43,710 this is the function that we're trying 363 00:13:43,710 --> 00:13:47,040 to get into more importantly, into the host name. 364 00:13:47,040 --> 00:13:51,039 And because this is when you're injecting into a process, 365 00:13:51,039 --> 00:13:55,800 it's a halting operation and it's kind of a hard place 366 00:13:55,800 --> 00:13:57,660 to halt when you don't even have internet yet. 367 00:13:57,660 --> 00:13:59,340 So we wanted to actually reach out 368 00:13:59,340 --> 00:14:01,080 to that command and control server 369 00:14:01,080 --> 00:14:02,520 to download more commands, 370 00:14:02,520 --> 00:14:06,120 not having to go through the host name 371 00:14:06,120 --> 00:14:08,130 with all those restrictions for forward slashes 372 00:14:08,130 --> 00:14:09,330 and things like that. 373 00:14:09,330 --> 00:14:11,940 So the way that we wanted to get this command 374 00:14:11,940 --> 00:14:14,130 to actually run where it's actually wget in 375 00:14:14,130 --> 00:14:15,480 more commands from that listener 376 00:14:15,480 --> 00:14:19,200 that we set up is to actually nest another DHCP 377 00:14:19,200 --> 00:14:21,826 call in here to actually have the network, 378 00:14:21,826 --> 00:14:25,111 finish its upbringing and actually get a valid IP address. 379 00:14:25,111 --> 00:14:28,830 So the desired command injection can take place. 380 00:14:28,830 --> 00:14:30,570 And that worked actually pretty well. 381 00:14:30,570 --> 00:14:32,070 And that's why we filed it 382 00:14:32,070 --> 00:14:35,468 as our first CVE unauthenticated command injection. 383 00:14:35,468 --> 00:14:40,110 The only reason this is only rated as a CVSS 9.0 384 00:14:40,110 --> 00:14:43,830 is because we can't trigger it on command. 385 00:14:43,830 --> 00:14:46,260 It had to actually be on a reboot call 386 00:14:46,260 --> 00:14:50,970 where that DHCP process pulls in our host name 387 00:14:50,970 --> 00:14:52,920 that we modified. 388 00:14:52,920 --> 00:14:54,720 And that's kinda where our second 389 00:14:54,720 --> 00:14:56,580 choose your pwn adventure took place, 390 00:14:56,580 --> 00:14:59,216 where we needed to find some sort of reboot primitive 391 00:14:59,216 --> 00:15:02,550 and there's a few ways that we went about looking at this. 392 00:15:02,550 --> 00:15:05,100 The first was looking at the web server, 393 00:15:05,100 --> 00:15:06,780 as we just found that command injection, 394 00:15:06,780 --> 00:15:09,480 is there any valid ways to cause a reboot 395 00:15:09,480 --> 00:15:12,900 and the apply settings tab did indeed at the end, 396 00:15:12,900 --> 00:15:14,220 reboot the device. 397 00:15:14,220 --> 00:15:16,890 However, it did check for cookies correctly. 398 00:15:16,890 --> 00:15:18,240 So we couldn't use that 399 00:15:18,240 --> 00:15:22,770 for this unauthenticated command injection here. 400 00:15:22,770 --> 00:15:24,780 The next thing we could have looked at is looking 401 00:15:24,780 --> 00:15:26,580 for a system exhaustion, 402 00:15:26,580 --> 00:15:28,740 where we are trying to trigger some of the wash dogs 403 00:15:28,740 --> 00:15:31,286 on the device to actually forcefully reboot the device 404 00:15:31,286 --> 00:15:35,430 or the controller and that did work. 405 00:15:35,430 --> 00:15:37,950 It took about an hour to actually do 406 00:15:37,950 --> 00:15:39,090 and it was really noisy. 407 00:15:39,090 --> 00:15:41,670 It was thousands and thousands of requests, 408 00:15:41,670 --> 00:15:43,560 but it did actually trigger the watchdog. 409 00:15:43,560 --> 00:15:44,790 That was always a fallback, 410 00:15:44,790 --> 00:15:46,170 but we didn't really like that. 411 00:15:46,170 --> 00:15:49,470 We wanted to be a little bit more meticulous about it 412 00:15:49,470 --> 00:15:51,180 and actually try to find something better. 413 00:15:51,180 --> 00:15:53,460 So what we ended up looking at was trying 414 00:15:53,460 --> 00:15:55,350 to find some sort of crash 415 00:15:55,350 --> 00:15:58,890 that would cause a Segfault and then look 416 00:15:58,890 --> 00:16:00,960 for more memory corruption vulnerabilities, 417 00:16:00,960 --> 00:16:01,980 where we can actually use that 418 00:16:01,980 --> 00:16:03,570 to actually reboot the device. 419 00:16:03,570 --> 00:16:07,290 And the reason a Segfault here would cause a reboot 420 00:16:07,290 --> 00:16:10,471 is when we started to look at that as an avenue, 421 00:16:10,471 --> 00:16:12,990 all segmentation faults on their device 422 00:16:12,990 --> 00:16:14,880 called a custom CoreDump handler. 423 00:16:14,880 --> 00:16:16,860 And you can always check what CoreDump handler 424 00:16:16,860 --> 00:16:19,800 is on your machine by catting out this core pattern file 425 00:16:19,800 --> 00:16:21,895 in your proc file system. 426 00:16:21,895 --> 00:16:23,190 And as you can see here, 427 00:16:23,190 --> 00:16:26,640 this was even says CustomMSC_CoreDump handler. 428 00:16:26,640 --> 00:16:28,347 So that was kind of interesting. 429 00:16:28,347 --> 00:16:30,012 And that is just a bash script 430 00:16:30,012 --> 00:16:32,303 that if you look at the very bottom, 431 00:16:32,303 --> 00:16:34,571 it eventually does call reboot. 432 00:16:34,571 --> 00:16:35,940 And this was perfect for us 433 00:16:35,940 --> 00:16:39,690 since all of the websites or web pages 434 00:16:39,690 --> 00:16:44,670 on the device are CGI bin compiled files. 435 00:16:44,670 --> 00:16:45,930 Any of them if you can 436 00:16:45,930 --> 00:16:47,430 cause a memory corruption vulnerability 437 00:16:47,430 --> 00:16:48,480 will dump their core. 438 00:16:48,480 --> 00:16:50,967 So that's where we started to look 439 00:16:50,967 --> 00:16:55,890 with our as much as possible and to do that, 440 00:16:55,890 --> 00:16:57,660 we wanted to really kind of improve 441 00:16:57,660 --> 00:16:59,040 our odds with automation. 442 00:16:59,040 --> 00:17:01,200 Anytime I get a write tool, I get pretty happy. 443 00:17:01,200 --> 00:17:03,895 So using IDA Python here, 444 00:17:03,895 --> 00:17:06,570 we started to look for some of these dangerous functions 445 00:17:06,570 --> 00:17:09,720 that you're can most familiar kind of 446 00:17:09,720 --> 00:17:12,000 or most common ways 447 00:17:12,000 --> 00:17:14,730 to actually get memory corruption vulnerabilities. 448 00:17:14,730 --> 00:17:16,020 So there's a list here. 449 00:17:16,020 --> 00:17:17,220 I'm not gonna go through them 450 00:17:17,220 --> 00:17:18,780 but looking for these 451 00:17:18,780 --> 00:17:20,730 and with the power of automation 452 00:17:20,730 --> 00:17:21,840 through IDA Python, 453 00:17:21,840 --> 00:17:22,950 we wanted to actually find 454 00:17:22,950 --> 00:17:26,006 where these were user input could actually hit these 455 00:17:26,006 --> 00:17:28,434 before any authentication took place. 456 00:17:28,434 --> 00:17:30,720 So the Python script would find 457 00:17:30,720 --> 00:17:33,270 where these were being ran 458 00:17:33,270 --> 00:17:36,630 before any sort of authentication 459 00:17:36,630 --> 00:17:38,250 or cookie check would take place. 460 00:17:38,250 --> 00:17:40,770 And as you can see, we did find a few 461 00:17:40,770 --> 00:17:42,943 however all of them were actually programmed 462 00:17:42,943 --> 00:17:46,560 perfectly fine with static size fields, things like that. 463 00:17:46,560 --> 00:17:47,940 Not very helpful for us 464 00:17:47,940 --> 00:17:50,250 to find memory corruption vulnerabilities. 465 00:17:50,250 --> 00:17:51,740 However, on the next page here, 466 00:17:51,740 --> 00:17:53,190 as the list continues, 467 00:17:53,190 --> 00:17:56,057 the last one is a advanced network CGI, 468 00:17:56,057 --> 00:17:59,370 which did have eight stir copies 469 00:17:59,370 --> 00:18:01,800 that we could actually use for command 470 00:18:01,800 --> 00:18:03,990 or for memory corruption vulnerabilities, 471 00:18:03,990 --> 00:18:06,900 where they source in destination pointers, 472 00:18:06,900 --> 00:18:09,600 where actually attacker controlled our user. 473 00:18:09,600 --> 00:18:13,563 What we passed in as the user we could modify. 474 00:18:14,910 --> 00:18:16,740 The way we wanted to test this, 475 00:18:16,740 --> 00:18:18,930 cause it's never good to test live 476 00:18:18,930 --> 00:18:20,970 on the only board that you bought off eBay 477 00:18:20,970 --> 00:18:25,650 is we actually set up an arm Qemu virtual machine 478 00:18:25,650 --> 00:18:27,030 to actually emulate these. 479 00:18:27,030 --> 00:18:28,470 And the way that we emulated it is 480 00:18:28,470 --> 00:18:30,660 since we have that root access on the machine, 481 00:18:30,660 --> 00:18:33,330 we actually dumped the whole MTD partitions 482 00:18:33,330 --> 00:18:37,980 of all of the file system, the boot all of that 483 00:18:37,980 --> 00:18:40,110 and then actually Chrooted into it 484 00:18:40,110 --> 00:18:42,570 through this arm Qemu and that means 485 00:18:42,570 --> 00:18:44,520 that all of the configuration files 486 00:18:44,520 --> 00:18:48,150 and all of the other files that it's looking 487 00:18:48,150 --> 00:18:49,590 for are actually in the right spot. 488 00:18:49,590 --> 00:18:52,110 Since now we're into the Chroot environment 489 00:18:52,110 --> 00:18:54,930 and we can execute these binaries as usual. 490 00:18:54,930 --> 00:18:56,310 So you can see this is kind of a joke, 491 00:18:56,310 --> 00:18:58,230 but we're actually interacting 492 00:18:58,230 --> 00:19:00,450 with that advanced network CGI bin file 493 00:19:00,450 --> 00:19:02,850 that we identified statically could have 494 00:19:02,850 --> 00:19:04,740 these memory corruption vulnerabilities 495 00:19:04,740 --> 00:19:09,030 in by just echoing parameters into it. 496 00:19:09,030 --> 00:19:12,870 So this is how the CGI bin files take Post parameters 497 00:19:12,870 --> 00:19:15,390 and you can see right below 498 00:19:15,390 --> 00:19:17,730 there is the timeout window 499 00:19:17,730 --> 00:19:20,070 that we saw when we did the live demo earlier. 500 00:19:20,070 --> 00:19:22,260 So it is working properly. 501 00:19:22,260 --> 00:19:23,820 Now we wanted to fuzz it. 502 00:19:23,820 --> 00:19:26,310 So to do that, we used Radamsa. 503 00:19:26,310 --> 00:19:29,370 It's a pretty really simple fuzzer 504 00:19:29,370 --> 00:19:31,710 that just is mutates whatever you pass 505 00:19:31,710 --> 00:19:34,410 into the standard in and then on its standard out 506 00:19:34,410 --> 00:19:36,630 will have something modified. 507 00:19:36,630 --> 00:19:39,930 So you see here this is a test passed directly 508 00:19:39,930 --> 00:19:43,740 into Radamsa and then it gets mutated to something else. 509 00:19:43,740 --> 00:19:47,070 They change some bytes to non printables 510 00:19:47,070 --> 00:19:49,800 and to do this for the CGI bin files, 511 00:19:49,800 --> 00:19:51,330 since they take the Post parameters 512 00:19:51,330 --> 00:19:53,760 over standard in as well, 513 00:19:53,760 --> 00:19:56,100 we can take a valid post parameter strain 514 00:19:56,100 --> 00:19:57,890 just pulled right out of the web server 515 00:19:57,890 --> 00:19:59,667 and then pass it into Radansa 516 00:19:59,667 --> 00:20:00,930 and as you can see, 517 00:20:00,930 --> 00:20:03,540 it flipped one of the last octets 518 00:20:03,540 --> 00:20:05,460 on this DNS server to negative one, 519 00:20:05,460 --> 00:20:07,410 which pretty good test in my opinion. 520 00:20:07,410 --> 00:20:12,000 So we didn't wanna run this fully manual every single time. 521 00:20:12,000 --> 00:20:13,350 That's not how fuzzing works 522 00:20:13,350 --> 00:20:17,280 so we set up this little fuzzer that I think pretty cute. 523 00:20:17,280 --> 00:20:19,980 It's like 13 lines of code or something, 524 00:20:19,980 --> 00:20:21,872 but it is all written in shell 525 00:20:21,872 --> 00:20:25,950 and it uses the Radamsa mutator. 526 00:20:25,950 --> 00:20:29,400 So you pass in the normal post parameter files here 527 00:20:29,400 --> 00:20:30,464 to get mutated. 528 00:20:30,464 --> 00:20:32,190 Soon as it gets mutated, 529 00:20:32,190 --> 00:20:33,210 we actually pass that directly 530 00:20:33,210 --> 00:20:36,080 into whatever CGI bin file we wanna look at. 531 00:20:36,080 --> 00:20:38,400 And then of course, if it crashes, 532 00:20:38,400 --> 00:20:41,258 which means it returned a return code, other than zero, 533 00:20:41,258 --> 00:20:44,220 we rerun the whole test case 534 00:20:44,220 --> 00:20:46,920 with the mutated data inside a GDB 535 00:20:46,920 --> 00:20:49,290 and then call a back trace on it. 536 00:20:49,290 --> 00:20:51,030 So while it looks super simple, 537 00:20:51,030 --> 00:20:53,280 it actually gives great results 538 00:20:53,280 --> 00:20:56,940 where this is a crash that we found from that. 539 00:20:56,940 --> 00:20:59,820 So you can see that the account stir here 540 00:20:59,820 --> 00:21:02,078 has a much longer string than it usually has 541 00:21:02,078 --> 00:21:05,910 and that is what Radamsa decided to mutate on this run. 542 00:21:05,910 --> 00:21:09,510 And you can see that it crashed right below in stir copy, 543 00:21:09,510 --> 00:21:12,441 right as we suspected from our static analysis, 544 00:21:12,441 --> 00:21:13,800 which kind of goes to show 545 00:21:13,800 --> 00:21:14,790 that we spent all this time 546 00:21:14,790 --> 00:21:16,740 getting this emulator set up and whatnot, 547 00:21:16,740 --> 00:21:19,050 and didn't actually found any more crashes 548 00:21:19,050 --> 00:21:20,370 than we did statically, 549 00:21:20,370 --> 00:21:23,880 but it was still a kind of fun learning experience. 550 00:21:23,880 --> 00:21:26,502 And this is where we filed this as our second CVE 551 00:21:26,502 --> 00:21:30,540 for this talk here that it's an unauthenticated denial 552 00:21:30,540 --> 00:21:33,510 of service where it is be just 553 00:21:33,510 --> 00:21:36,087 because it can cause a reboot on command 554 00:21:36,087 --> 00:21:38,640 that's why it's just a denial of service. 555 00:21:38,640 --> 00:21:40,200 The crash and stir copy 556 00:21:40,200 --> 00:21:41,670 was actually just an outer bounds read. 557 00:21:41,670 --> 00:21:43,800 So we couldn't use it to write anything, 558 00:21:43,800 --> 00:21:47,310 but I'll let Steve cover how we use these together 559 00:21:47,310 --> 00:21:50,103 as a chain to kind of continue our exploitation. 560 00:21:51,634 --> 00:21:54,810 - Okay, so now we've got two vulnerabilities, 561 00:21:54,810 --> 00:21:55,830 which work in concert. 562 00:21:55,830 --> 00:21:56,940 We have a command injection, 563 00:21:56,940 --> 00:21:58,320 which is triggered at reboot 564 00:21:58,320 --> 00:22:00,570 and we have a way to trigger reboot via Segfault. 565 00:22:00,570 --> 00:22:03,447 So we have a way to get full unauthenticated code execution, 566 00:22:03,447 --> 00:22:05,370 and that meant it was time to upgrade 567 00:22:05,370 --> 00:22:07,470 to the latest firmware and kind of bypass 568 00:22:07,470 --> 00:22:10,170 our eBay Yolo route and see if we could make 569 00:22:10,170 --> 00:22:11,640 this a little bit more official. 570 00:22:11,640 --> 00:22:12,570 So we actually called up, 571 00:22:12,570 --> 00:22:13,403 we live in Portland, 572 00:22:13,403 --> 00:22:15,660 we called up one of the actual legitimate third party 573 00:22:15,660 --> 00:22:17,325 installers for Lenel systems, 574 00:22:17,325 --> 00:22:19,012 a company called Convergint. 575 00:22:19,012 --> 00:22:21,870 We put heavy air pods around social engineering. 576 00:22:21,870 --> 00:22:24,330 We're not like doing a ton of social engineering here, 577 00:22:24,330 --> 00:22:25,890 but we may have done a little cloak and dagger 578 00:22:25,890 --> 00:22:27,360 when we described the project to them 579 00:22:27,360 --> 00:22:29,100 of what we wanted them to build out. 580 00:22:29,100 --> 00:22:31,290 This monstrosity that you see on stage here. 581 00:22:31,290 --> 00:22:33,810 So they're like, you want us to build what, why? 582 00:22:33,810 --> 00:22:35,610 Okay, here you're paying us how much. 583 00:22:35,610 --> 00:22:36,630 Okay. we're good. 584 00:22:36,630 --> 00:22:37,860 All right so they came to the lab 585 00:22:37,860 --> 00:22:39,690 and actually built out this full system 586 00:22:39,690 --> 00:22:43,110 and they integrated in the OnGuard as a standalone server. 587 00:22:43,110 --> 00:22:45,870 And you can kind of see some of the pictures here. 588 00:22:45,870 --> 00:22:48,090 It was wired up with a controller and card reader. 589 00:22:48,090 --> 00:22:50,010 So this is essentially an installation 590 00:22:50,010 --> 00:22:53,010 that mirrors a production building install minus 591 00:22:53,010 --> 00:22:55,170 the fact that we have no glass in there, 592 00:22:55,170 --> 00:22:56,970 but we'll mind that, 593 00:22:56,970 --> 00:22:59,130 and it actually works just like you would. 594 00:22:59,130 --> 00:23:01,230 And our controller is actually on the back 595 00:23:01,230 --> 00:23:03,810 on a panel where you can't see it above the door 596 00:23:03,810 --> 00:23:05,550 that would be in a server closet typically, 597 00:23:05,550 --> 00:23:07,350 but we obviously don't have room for that. 598 00:23:07,350 --> 00:23:10,110 So otherwise this is a production system. 599 00:23:10,110 --> 00:23:12,390 They also gave us some training and hands on experience 600 00:23:12,390 --> 00:23:15,240 with how to provision doors and badges and users 601 00:23:15,240 --> 00:23:17,546 and all the fun stuff that came with the software. 602 00:23:17,546 --> 00:23:19,100 That was good for us to learn, 603 00:23:19,100 --> 00:23:21,810 but it paled and compared to the usefulness 604 00:23:21,810 --> 00:23:23,760 of being able to finally download 605 00:23:23,760 --> 00:23:25,380 and push firmware to the device. 606 00:23:25,380 --> 00:23:28,025 So we could test whether our vulnerabilities survived 607 00:23:28,025 --> 00:23:30,976 from an older version of firmware to the latest one, 608 00:23:30,976 --> 00:23:33,120 just doing this and we also had a copy 609 00:23:33,120 --> 00:23:35,640 of a legitimate firmware on the file system, 610 00:23:35,640 --> 00:23:38,338 despite being encrypted on the Lenel that we had 611 00:23:38,338 --> 00:23:40,800 or on the OnGuard system that we had. 612 00:23:40,800 --> 00:23:42,300 All right so that brought us to a success 613 00:23:42,300 --> 00:23:43,950 and failure point here. 614 00:23:43,950 --> 00:23:46,260 Let's start with the failure and the before, 615 00:23:46,260 --> 00:23:47,610 as you recall, Sam saying, 616 00:23:47,610 --> 00:23:49,773 there was a Segfault on every system binary, 617 00:23:49,773 --> 00:23:51,694 meaning it would reboot the system. 618 00:23:51,694 --> 00:23:54,600 Well afterwards they had restricted this just 619 00:23:54,600 --> 00:23:56,430 to the two main Lenel system 620 00:23:56,430 --> 00:23:58,140 or mercury system binaries here 621 00:23:58,140 --> 00:24:01,680 and actually that meant that we had lost the Segfault 622 00:24:01,680 --> 00:24:03,180 that led to our reboot 623 00:24:03,180 --> 00:24:04,770 and we couldn't arbitrarily trigger 624 00:24:04,770 --> 00:24:06,600 our command injection anymore 625 00:24:06,600 --> 00:24:07,560 and those are the two. 626 00:24:07,560 --> 00:24:08,393 I know you can't read it, 627 00:24:08,393 --> 00:24:09,450 but those are the two files 628 00:24:09,450 --> 00:24:14,130 that are now in the new CrashDump handling file. 629 00:24:14,130 --> 00:24:16,980 However, our command injection did survive an update 630 00:24:16,980 --> 00:24:18,240 to the latest firmware version 631 00:24:18,240 --> 00:24:19,763 and that was really the higher bar here. 632 00:24:19,763 --> 00:24:22,020 We knew we could find some way to get this thing 633 00:24:22,020 --> 00:24:23,249 to crash or reboot 634 00:24:23,249 --> 00:24:26,040 and that was really the next step of this process. 635 00:24:26,040 --> 00:24:28,020 Choose your pwn adventure number three. 636 00:24:28,020 --> 00:24:29,910 Now we needed an alternative method 637 00:24:29,910 --> 00:24:32,490 of getting that unauthenticated RCE back 638 00:24:32,490 --> 00:24:34,704 because all we had is code execution 639 00:24:34,704 --> 00:24:36,781 unauthenticated but not on demand. 640 00:24:36,781 --> 00:24:39,750 So we could have looked for a new standalone vulnerability, 641 00:24:39,750 --> 00:24:42,960 a zero or one click kind of do it all in one here, 642 00:24:42,960 --> 00:24:45,420 we could have looked for a new reboot primitive 643 00:24:45,420 --> 00:24:47,400 or a crash to replace the one 644 00:24:47,400 --> 00:24:48,720 that we missed in this chain here 645 00:24:48,720 --> 00:24:50,760 that we lost in the upgrade process. 646 00:24:50,760 --> 00:24:53,190 And I suppose we could have updated 647 00:24:53,190 --> 00:24:55,230 actually moved on and just done our malware 648 00:24:55,230 --> 00:24:57,360 or door exploit because at some point 649 00:24:57,360 --> 00:24:58,530 the board's gonna go down 650 00:24:58,530 --> 00:25:00,060 or gonna be rebooted for maintenance 651 00:25:00,060 --> 00:25:02,160 and it's gonna trigger that command injection, 652 00:25:02,160 --> 00:25:04,260 obviously we're way too lazy to do that 653 00:25:04,260 --> 00:25:08,340 so we went ahead looking for a new toy to play with. 654 00:25:08,340 --> 00:25:09,990 Now, luckily with this upgrade 655 00:25:09,990 --> 00:25:12,420 came some new fun functionality here, 656 00:25:12,420 --> 00:25:14,820 specifically the firmware upload option. 657 00:25:14,820 --> 00:25:17,190 And what you'll see is this diagnostics page 658 00:25:17,190 --> 00:25:21,060 on the web server added the ability to upload firmware. 659 00:25:21,060 --> 00:25:23,730 And it says specifically will reboot board. 660 00:25:23,730 --> 00:25:25,740 It's almost like they were in our heads here. 661 00:25:25,740 --> 00:25:27,780 This was exactly what we were looking for. 662 00:25:27,780 --> 00:25:30,540 So we're gonna go ahead and do another live demo here 663 00:25:30,540 --> 00:25:32,108 or attempt to kind of showing you 664 00:25:32,108 --> 00:25:35,373 how we manage to play with this a little bit. 665 00:25:37,997 --> 00:25:39,971 All right, cool. 666 00:25:39,971 --> 00:25:43,395 So we're back at the web server here. 667 00:25:43,395 --> 00:25:44,330 Where is it? 668 00:25:44,330 --> 00:25:45,163 To the left? 669 00:25:45,163 --> 00:25:45,996 Okay. 670 00:25:46,920 --> 00:25:47,753 Alright, cool. 671 00:25:48,780 --> 00:25:49,770 It has timed out. 672 00:25:49,770 --> 00:25:53,040 So I'm gonna try my best to log back in. 673 00:25:53,040 --> 00:25:54,360 Can't see anything down there, 674 00:25:54,360 --> 00:25:57,870 but am I on it? 675 00:25:57,870 --> 00:25:59,943 Anybody read it okay, cool. 676 00:26:02,130 --> 00:26:04,080 It made that really hard to see 677 00:26:04,080 --> 00:26:06,930 you know drag it over and I'll pull it back. 678 00:26:06,930 --> 00:26:09,273 Okay, wrong address, that's why. 679 00:26:10,140 --> 00:26:11,790 Okay, so what I'm gonna show you here 680 00:26:11,790 --> 00:26:15,180 is that we're gonna log into the web server itself 681 00:26:15,180 --> 00:26:18,526 and we're going to basically try to show you two things. 682 00:26:18,526 --> 00:26:22,530 The ability to arbitrarily reboot the board. 683 00:26:22,530 --> 00:26:24,540 Sam runs everything into Dvorak keyboard, 684 00:26:24,540 --> 00:26:26,580 which is really fun to switch back and forth 685 00:26:26,580 --> 00:26:28,230 from English to Dvorak. 686 00:26:28,230 --> 00:26:30,030 I knew this would bite me somewhere. 687 00:26:30,030 --> 00:26:31,800 All right, so we're gonna show you basically trying 688 00:26:31,800 --> 00:26:32,790 to log in the device, 689 00:26:32,790 --> 00:26:36,385 do a bypass of the command of the login 690 00:26:36,385 --> 00:26:39,240 and actually show you 691 00:26:39,240 --> 00:26:40,920 what the session management looks like. 692 00:26:40,920 --> 00:26:41,753 A problem with that. 693 00:26:41,753 --> 00:26:42,853 - Yeah, it's eight. 694 00:26:43,857 --> 00:26:45,186 - Oh! Cool. 695 00:26:45,186 --> 00:26:46,530 - All right. 696 00:26:46,530 --> 00:26:47,493 - Ain't that 100? 697 00:26:51,540 --> 00:26:52,683 - This is fun, okay. 698 00:26:53,790 --> 00:26:54,837 - All right. 699 00:26:54,837 --> 00:26:55,670 Let me pull this back on screen 700 00:26:55,670 --> 00:26:57,333 so you can see it here. 701 00:26:58,219 --> 00:27:00,300 So we're back at the login screen 702 00:27:00,300 --> 00:27:02,070 and I have the developer tools up 703 00:27:02,070 --> 00:27:04,200 so we can see session management a little bit here, 704 00:27:04,200 --> 00:27:05,460 just like Sam showed. 705 00:27:05,460 --> 00:27:07,470 I'm gonna log in for the first time legitimately 706 00:27:07,470 --> 00:27:09,480 so we can get a valid session cookie. 707 00:27:09,480 --> 00:27:11,010 Then we're gonna capture the give request, 708 00:27:11,010 --> 00:27:13,530 log out and see if it handles it properly. 709 00:27:13,530 --> 00:27:17,790 So if we go over to the diagnostics tab 710 00:27:17,790 --> 00:27:19,380 that was added here, 711 00:27:19,380 --> 00:27:20,790 that's the one that I mentioned was added 712 00:27:20,790 --> 00:27:22,830 that has the firmware upload feature. 713 00:27:22,830 --> 00:27:24,720 And you probably can't see this. 714 00:27:24,720 --> 00:27:26,520 I'm gonna highlight and developer tools. 715 00:27:26,520 --> 00:27:28,740 There is a diagnostic CGI tab 716 00:27:28,740 --> 00:27:30,420 that was requested and the session ID 717 00:27:30,420 --> 00:27:32,460 is validly appended onto there. 718 00:27:32,460 --> 00:27:33,720 So I'm gonna right click 719 00:27:33,720 --> 00:27:36,030 and copy essentially the Get request 720 00:27:36,030 --> 00:27:38,250 so we can test that logged out as well 721 00:27:38,250 --> 00:27:39,150 before we do that, 722 00:27:39,150 --> 00:27:41,910 if you look just a little bit further down here, 723 00:27:41,910 --> 00:27:43,440 what you might see is there's a request 724 00:27:43,440 --> 00:27:46,980 to another CGI page called View Firmware Update dot cgi 725 00:27:46,980 --> 00:27:49,020 and you may have sharp eyes 726 00:27:49,020 --> 00:27:50,250 and see that does not 727 00:27:50,250 --> 00:27:52,260 have a session ID appended onto it. 728 00:27:52,260 --> 00:27:54,420 So let's look at that a little bit closer. 729 00:27:54,420 --> 00:27:56,670 We'll log out and we'll try this, 730 00:27:56,670 --> 00:27:58,840 Get request to the diagnostics page 731 00:28:00,180 --> 00:28:01,170 and see if it fails, 732 00:28:01,170 --> 00:28:02,880 which we expect it to. 733 00:28:02,880 --> 00:28:05,010 Well yes, the session cookie was not valid. 734 00:28:05,010 --> 00:28:06,180 It handled that properly. 735 00:28:06,180 --> 00:28:08,516 So it was unable to actually log in. 736 00:28:08,516 --> 00:28:10,140 So I gotta bring this back over 737 00:28:10,140 --> 00:28:11,670 and I'll pull it over in just a minute 738 00:28:11,670 --> 00:28:13,413 so you can see this, all right. 739 00:28:14,340 --> 00:28:17,850 So now I'm gonna go directly to that CGI page 740 00:28:17,850 --> 00:28:20,700 that I showed you before that was loaded, 741 00:28:20,700 --> 00:28:23,610 which is view firmware update directly. 742 00:28:23,610 --> 00:28:25,410 And what you'll see is we can browse 743 00:28:25,410 --> 00:28:27,210 that page completely unauthenticated 744 00:28:27,210 --> 00:28:28,980 without logging in whatsoever 745 00:28:28,980 --> 00:28:30,960 and randomly upload files to it 746 00:28:30,960 --> 00:28:32,643 which we could not believe. 747 00:28:33,720 --> 00:28:34,590 Thank you, thank you. 748 00:28:34,590 --> 00:28:37,080 Yes, all right. 749 00:28:37,080 --> 00:28:38,310 Thanks for bearing with me 750 00:28:38,310 --> 00:28:40,920 through that demo train wreck. 751 00:28:40,920 --> 00:28:43,080 All right, so now we can upload a file. 752 00:28:43,080 --> 00:28:45,060 What I'm gonna do is I'm gonna choose a file 753 00:28:45,060 --> 00:28:46,830 from the file system here, 754 00:28:46,830 --> 00:28:48,600 and this is actually gonna be running 755 00:28:48,600 --> 00:28:51,240 in the background it'll cause the Segfault, 756 00:28:51,240 --> 00:28:53,160 which we're gonna explain to you shortly here. 757 00:28:53,160 --> 00:28:54,810 So the people in the front row 758 00:28:54,810 --> 00:28:56,837 may actually hear it reboot the device 759 00:28:56,837 --> 00:29:00,930 as we load this is going to actually Segfault and reboot. 760 00:29:00,930 --> 00:29:02,790 And we'll talk about how and why this works 761 00:29:02,790 --> 00:29:04,230 in just a moment all right. 762 00:29:04,230 --> 00:29:06,450 Let's click load file, installing 763 00:29:06,450 --> 00:29:08,278 and sometime in the next maybe 30 seconds, 764 00:29:08,278 --> 00:29:10,860 some of us will hear a little beep there. 765 00:29:10,860 --> 00:29:12,750 All right, let's go back to slides now 766 00:29:12,750 --> 00:29:14,940 and continue on and explain what's happening 767 00:29:14,940 --> 00:29:16,410 in the background. 768 00:29:16,410 --> 00:29:19,110 Okay, we have a file that we've now controlled 769 00:29:19,110 --> 00:29:21,990 the file input to there's a few areas of interest. 770 00:29:21,990 --> 00:29:24,120 We could look at the file contents itself. 771 00:29:24,120 --> 00:29:26,070 You might have just heard the board reboot 772 00:29:26,070 --> 00:29:27,060 or the controller reboot. 773 00:29:27,060 --> 00:29:28,590 We could look at the file contents itself 774 00:29:28,590 --> 00:29:30,150 for some kind of an overflow, 775 00:29:30,150 --> 00:29:32,073 the file name, the characters that are input 776 00:29:32,073 --> 00:29:34,530 even the things like the file size. 777 00:29:34,530 --> 00:29:36,120 And we started to play around with, 778 00:29:36,120 --> 00:29:38,647 could we control one of these to get a crash? 779 00:29:38,647 --> 00:29:41,340 The first thing that we did on this diagnostics page 780 00:29:41,340 --> 00:29:44,250 is upload an empty file called Fubarta.txt 781 00:29:44,250 --> 00:29:45,540 doesn't matter what it is, 782 00:29:45,540 --> 00:29:46,770 didn't have any contents in it. 783 00:29:46,770 --> 00:29:48,660 We're just trying to see what happens 784 00:29:48,660 --> 00:29:50,820 as it went ahead and tried to install that 785 00:29:50,820 --> 00:29:52,536 it eventually aired out, of course. 786 00:29:52,536 --> 00:29:54,300 And it'd be really awesome if it didn't, 787 00:29:54,300 --> 00:29:55,890 but it aired out and it threw 788 00:29:55,890 --> 00:29:58,110 this error invalid signature size. 789 00:29:58,110 --> 00:29:59,190 So we knew that it was looking 790 00:29:59,190 --> 00:30:00,930 for some kind of a file signature 791 00:30:00,930 --> 00:30:03,630 and more so that it was somehow parsing a size. 792 00:30:03,630 --> 00:30:04,650 Well, maybe that was interesting 793 00:30:04,650 --> 00:30:06,900 to explore a little bit further. 794 00:30:06,900 --> 00:30:07,770 So the next thing that we did 795 00:30:07,770 --> 00:30:11,160 is we pulled up that actual valid firmware file 796 00:30:11,160 --> 00:30:14,460 from the OnGuard system and it's an encrypted file. 797 00:30:14,460 --> 00:30:16,356 So for the most part, it's uninteresting 798 00:30:16,356 --> 00:30:18,210 until you get to the end of the file 799 00:30:18,210 --> 00:30:20,460 and the last x158 bytes 800 00:30:20,460 --> 00:30:24,300 if you have sharp eyes are a base 64 encoded blob, 801 00:30:24,300 --> 00:30:25,170 as you might have guessed 802 00:30:25,170 --> 00:30:28,020 this specifies the file signature and more. 803 00:30:28,020 --> 00:30:30,630 So at the very end, there are three ascii bytes, 804 00:30:30,630 --> 00:30:34,200 158 that specify the size of that file signature. 805 00:30:34,200 --> 00:30:36,300 So it's not doing it dynamically parsing in 806 00:30:36,300 --> 00:30:39,030 byte by byte and determining a size mathematically 807 00:30:39,030 --> 00:30:40,380 it's taking in this case, 808 00:30:40,380 --> 00:30:42,600 what we call a user controlled value here, 809 00:30:42,600 --> 00:30:44,310 because we can upload this file 810 00:30:44,310 --> 00:30:46,104 and it's using that to calculate the size 811 00:30:46,104 --> 00:30:50,280 or to compare the size of the file signature. 812 00:30:50,280 --> 00:30:52,020 So the next thing we did of course, 813 00:30:52,020 --> 00:30:53,880 was go in and look at the code responsible 814 00:30:53,880 --> 00:30:57,810 for parsing this firmware file signature size check. 815 00:30:57,810 --> 00:30:58,950 So the first thing that happens 816 00:30:58,950 --> 00:31:02,550 is there's a malec of a static malec of 190 hex bytes. 817 00:31:02,550 --> 00:31:04,713 And of course, then the file is opened 818 00:31:04,713 --> 00:31:07,770 and saved off using a file open command. 819 00:31:07,770 --> 00:31:09,625 So far so good. 820 00:31:09,625 --> 00:31:11,190 Now this is gonna be hard to read, 821 00:31:11,190 --> 00:31:13,110 so I'll just dictate it as we go. 822 00:31:13,110 --> 00:31:16,410 The next function here is an Fseek or a file seek. 823 00:31:16,410 --> 00:31:18,930 It will go to the end of the file minus three bytes, 824 00:31:18,930 --> 00:31:21,660 of course, to retrieve those last three ascii bytes, 825 00:31:21,660 --> 00:31:24,330 which are a size field and using fread, 826 00:31:24,330 --> 00:31:28,500 we'll read those in as a size value. 827 00:31:28,500 --> 00:31:30,630 Now we'll take a string to long 828 00:31:30,630 --> 00:31:33,352 or stir to L and change that ascii value 829 00:31:33,352 --> 00:31:37,050 to a long value and as you guessed it shortly later 830 00:31:37,050 --> 00:31:38,580 in the fread function, 831 00:31:38,580 --> 00:31:41,430 that'll be used as a parameter here to the size. 832 00:31:41,430 --> 00:31:43,500 And of course, if we have a static buffer 833 00:31:43,500 --> 00:31:44,730 and we have a dynamic size 834 00:31:44,730 --> 00:31:47,100 that we control that's prime for overflow, 835 00:31:47,100 --> 00:31:50,010 and of course this is where a heap overflow does happen. 836 00:31:50,010 --> 00:31:52,050 Shortly later in the file close function 837 00:31:52,050 --> 00:31:54,240 is where we actually see the crash happen 838 00:31:54,240 --> 00:31:55,770 and we can start to leverage it. 839 00:31:55,770 --> 00:31:58,260 We're gonna show you a little bit more detail on that. 840 00:31:58,260 --> 00:31:59,580 All right, our steps to overflow, 841 00:31:59,580 --> 00:32:02,148 or to test this, we created a fake file, 842 00:32:02,148 --> 00:32:05,099 basically a copy of the firmware file, 843 00:32:05,099 --> 00:32:08,400 and we filled it with a unique and predictable pattern. 844 00:32:08,400 --> 00:32:10,770 Just think of your metasploit pattern and create 845 00:32:10,770 --> 00:32:11,850 that's what we're filling it with 846 00:32:11,850 --> 00:32:15,120 to see if we actually control any registers on here. 847 00:32:15,120 --> 00:32:16,740 Now because this is an encrypted file. 848 00:32:16,740 --> 00:32:21,740 It needed the salted underscore underscore file header. 849 00:32:21,750 --> 00:32:23,490 So it does check that and we added 850 00:32:23,490 --> 00:32:25,320 that to the beginning of the file, 851 00:32:25,320 --> 00:32:27,300 and then we changed the file size 852 00:32:27,300 --> 00:32:30,000 or file signature size here to 999, 853 00:32:30,000 --> 00:32:32,010 anything over, well, what was it? 854 00:32:32,010 --> 00:32:34,350 190, the static buffer size will work. 855 00:32:34,350 --> 00:32:35,580 They had used 158. 856 00:32:35,580 --> 00:32:37,203 We changed just to 999. 857 00:32:38,040 --> 00:32:38,873 And then finally, 858 00:32:38,873 --> 00:32:40,211 we set a break point here in 859 00:32:40,211 --> 00:32:43,110 we'll talk about we're going really in the context 860 00:32:43,110 --> 00:32:45,570 of the emulator Sam was talking about earlier, 861 00:32:45,570 --> 00:32:47,040 but we set a break point here 862 00:32:47,040 --> 00:32:48,930 before we thought we controlled execution 863 00:32:48,930 --> 00:32:50,820 in the file close function. 864 00:32:50,820 --> 00:32:52,530 And if you can see what's highlighted, 865 00:32:52,530 --> 00:32:53,730 it's a branch instruction, 866 00:32:53,730 --> 00:32:57,210 an unconditional branch and arm to the r3 register. 867 00:32:57,210 --> 00:32:58,500 Well, we know we're gonna hit this 868 00:32:58,500 --> 00:32:59,940 and why is that important? 869 00:32:59,940 --> 00:33:02,460 Well, if you look to the right side at the registers, 870 00:33:02,460 --> 00:33:06,180 you can see r0, r1, r3 and r6 871 00:33:06,180 --> 00:33:07,410 all have our pattern data. 872 00:33:07,410 --> 00:33:09,630 So they've been fully crushed with the overflow 873 00:33:09,630 --> 00:33:12,180 and R4 has a pointer to the pattern data 874 00:33:12,180 --> 00:33:13,590 that we've overflowed as well. 875 00:33:13,590 --> 00:33:15,420 And that's gonna be important here. 876 00:33:15,420 --> 00:33:17,070 Now, before we go into wrap 877 00:33:17,070 --> 00:33:18,150 and we're gonna spend a few minutes 878 00:33:18,150 --> 00:33:20,100 talking about the wrap we did, 879 00:33:20,100 --> 00:33:21,270 we actually managed to get 880 00:33:21,270 --> 00:33:22,710 this working really beautifully 881 00:33:22,710 --> 00:33:23,970 and ROP the next few slides. 882 00:33:23,970 --> 00:33:25,410 We'll show you how that works. 883 00:33:25,410 --> 00:33:26,700 When we try to transfer it back 884 00:33:26,700 --> 00:33:28,080 to the physical hardware, 885 00:33:28,080 --> 00:33:30,270 we had all sorts of issues like we're just, 886 00:33:30,270 --> 00:33:31,103 it was unbelievable. 887 00:33:31,103 --> 00:33:33,840 We had heap confusion issues, 888 00:33:33,840 --> 00:33:34,680 and process threading, 889 00:33:34,680 --> 00:33:36,900 and just would not transfer back to physical hardware. 890 00:33:36,900 --> 00:33:38,880 So we'll see what we ended up doing 891 00:33:38,880 --> 00:33:40,170 is we just used that file 892 00:33:40,170 --> 00:33:42,330 to cause a reboot and essentially trigger 893 00:33:42,330 --> 00:33:43,500 our command injection. 894 00:33:43,500 --> 00:33:45,390 But we do have full code execution 895 00:33:45,390 --> 00:33:47,670 using the ROP gadget and the emulator. 896 00:33:47,670 --> 00:33:48,720 One is all we needed, 897 00:33:48,720 --> 00:33:50,100 just a single wrap gadget. 898 00:33:50,100 --> 00:33:53,790 And what we have on screen here is two commands. 899 00:33:53,790 --> 00:33:55,230 The first one or the top half 900 00:33:55,230 --> 00:33:57,180 is just a script using Ropper 901 00:33:57,180 --> 00:33:59,490 to search for ROP gadgets in all the binaries 902 00:33:59,490 --> 00:34:01,860 and third party or imported libraries. 903 00:34:01,860 --> 00:34:03,824 We did use that and then we pushed 904 00:34:03,824 --> 00:34:06,240 into a regular expression to filter 905 00:34:06,240 --> 00:34:08,070 it down to a set of useful gadgets. 906 00:34:08,070 --> 00:34:10,164 Now, even if you can read these closely, 907 00:34:10,164 --> 00:34:12,660 you may not know why these are useful gadgets. 908 00:34:12,660 --> 00:34:14,610 Obviously we're going a little bit out of order here 909 00:34:14,610 --> 00:34:16,710 you'll see that in a moment. 910 00:34:16,710 --> 00:34:20,569 The gadget we chose here is just these five instructions 911 00:34:20,569 --> 00:34:23,610 and I'll talk about why these are important here. 912 00:34:23,610 --> 00:34:25,830 The approach that we took is we wanted to, 913 00:34:25,830 --> 00:34:28,860 so there's an unconditional branch r3 as I talked about, 914 00:34:28,860 --> 00:34:30,960 and that's where we get the start of control. 915 00:34:30,960 --> 00:34:33,090 If we can get into r3 916 00:34:33,090 --> 00:34:35,490 and address that points to the beginning of our gadget, 917 00:34:35,490 --> 00:34:36,450 which of course we can, 918 00:34:36,450 --> 00:34:38,400 because we control that register. 919 00:34:38,400 --> 00:34:41,520 We can potentially call a system call here. 920 00:34:41,520 --> 00:34:43,080 All right, so the first step was getting 921 00:34:43,080 --> 00:34:46,170 an address of our gadget into r3 922 00:34:46,170 --> 00:34:49,147 because r0 is moved into our r3 here. 923 00:34:49,147 --> 00:34:52,890 So the first step here is we wanna get r0 924 00:34:52,890 --> 00:34:54,600 as an address to our system call. 925 00:34:54,600 --> 00:34:57,180 It's moved into r3 and then five instructions later 926 00:34:57,180 --> 00:34:59,160 that unconditional branch calls it directly 927 00:34:59,160 --> 00:35:00,960 so it'll be calling system. 928 00:35:00,960 --> 00:35:03,900 However, to get an argument for system in arm, 929 00:35:03,900 --> 00:35:06,660 the argument has to be still an r0. 930 00:35:06,660 --> 00:35:08,970 Well, that's beautiful because the second instruction 931 00:35:08,970 --> 00:35:12,390 of this gadget is moving r4 into r0. 932 00:35:12,390 --> 00:35:14,610 And it's not mangled in between then 933 00:35:14,610 --> 00:35:17,130 so not only can we use r0 to get system, 934 00:35:17,130 --> 00:35:19,440 but we can use r4 to get our parameter 935 00:35:19,440 --> 00:35:22,497 to system or river shell into r0 936 00:35:22,497 --> 00:35:26,089 and it'll be called in the unconditional branch to r3. 937 00:35:26,089 --> 00:35:29,250 Okay, so good things come in small packages here. 938 00:35:29,250 --> 00:35:32,070 When we started to put these into the correct offsets 939 00:35:32,070 --> 00:35:33,300 in our pattern file, 940 00:35:33,300 --> 00:35:35,400 you can see that we used a wget command. 941 00:35:35,400 --> 00:35:38,130 Sam talked about this in the command injection earlier. 942 00:35:38,130 --> 00:35:40,470 This is gonna be our attempted reverse shell. 943 00:35:40,470 --> 00:35:43,319 You can see the locations of where we have r4 and r0. 944 00:35:43,319 --> 00:35:45,660 There's only 28 contiguous bytes though, 945 00:35:45,660 --> 00:35:50,040 for us to get execution before r0 is messed up. 946 00:35:50,040 --> 00:35:51,480 Now, as we were executing this, 947 00:35:51,480 --> 00:35:52,920 we thought it was working perfectly 948 00:35:52,920 --> 00:35:54,870 and we'd be able to get our reverse shell 949 00:35:54,870 --> 00:35:56,130 but for some reason, 950 00:35:56,130 --> 00:35:59,940 four bytes of that reverse shell string get copied 951 00:35:59,940 --> 00:36:02,430 and basically pasted into eight bytes later, 952 00:36:02,430 --> 00:36:03,900 mangling our IP address 953 00:36:03,900 --> 00:36:06,480 and so that caused an epic fail here. 954 00:36:06,480 --> 00:36:08,640 However, in the process of running that, 955 00:36:08,640 --> 00:36:11,100 Sam just, cause he likes to yellow everything 956 00:36:11,100 --> 00:36:13,650 just as like let's change it from, I don't know, 957 00:36:13,650 --> 00:36:15,900 whatever it was IP address to AAAA, 958 00:36:15,900 --> 00:36:17,220 like that'll make some difference. 959 00:36:17,220 --> 00:36:21,108 And of course it did and it caused a similar crash, 960 00:36:21,108 --> 00:36:26,070 but now r4 was located way earlier in the pattern file. 961 00:36:26,070 --> 00:36:28,380 So instead of having 28 contiguous bytes, 962 00:36:28,380 --> 00:36:30,925 we had something like 400 plus contiguous bytes. 963 00:36:30,925 --> 00:36:32,730 So if you can see the pattern here 964 00:36:32,730 --> 00:36:35,880 that r4 points to it says QKAA, 965 00:36:35,880 --> 00:36:37,950 that's the ascii key part of the pattern. 966 00:36:37,950 --> 00:36:40,290 And you'll see it here in our pattern file. 967 00:36:40,290 --> 00:36:42,450 So the ROP gods kind of smiled on us. 968 00:36:42,450 --> 00:36:45,480 So now r4 is way earlier and we don't even have 969 00:36:45,480 --> 00:36:47,880 to bother with this reverse shell 970 00:36:47,880 --> 00:36:51,900 that we essentially push commands to from our C2 server. 971 00:36:51,900 --> 00:36:54,060 We can actually just call system 972 00:36:54,060 --> 00:36:56,430 with a direct reverse shell as the argument to it. 973 00:36:56,430 --> 00:36:57,450 And if we go back, 974 00:36:57,450 --> 00:36:59,010 that's the right side of the screen. 975 00:36:59,010 --> 00:37:00,150 So where r4 is, 976 00:37:00,150 --> 00:37:02,738 we just did a straight up socat reverse shell 977 00:37:02,738 --> 00:37:04,860 and connected to that directly. 978 00:37:04,860 --> 00:37:06,870 And that's what we'll show you in a minute here. 979 00:37:06,870 --> 00:37:07,703 All right. 980 00:37:07,703 --> 00:37:08,536 So let's summarize here. 981 00:37:08,536 --> 00:37:10,860 We have a break point to at the call to Rop, 982 00:37:10,860 --> 00:37:13,444 which is our branch to r3 983 00:37:13,444 --> 00:37:17,730 and r3 has to be address of our gadget. 984 00:37:17,730 --> 00:37:20,070 So we can see that that does match up the address 985 00:37:20,070 --> 00:37:21,330 of our gadget works. 986 00:37:21,330 --> 00:37:22,320 I know we're moving quickly, 987 00:37:22,320 --> 00:37:24,120 but you can go back and check some of these later. 988 00:37:24,120 --> 00:37:25,530 I know it's hard to see. 989 00:37:25,530 --> 00:37:26,460 There's our gadget, 990 00:37:26,460 --> 00:37:28,320 once we get into executing that address, 991 00:37:28,320 --> 00:37:30,270 we have just those five instructions 992 00:37:30,270 --> 00:37:31,710 and inside of it the last thing 993 00:37:31,710 --> 00:37:34,380 is another unconditional branch to r3. 994 00:37:34,380 --> 00:37:35,790 So our complete pattern file 995 00:37:35,790 --> 00:37:38,460 here looks like this r4 has our reverse shell 996 00:37:38,460 --> 00:37:40,890 in the very beginning, some 400 bytes later, 997 00:37:40,890 --> 00:37:43,020 we have a system address in r0 998 00:37:43,020 --> 00:37:44,550 and our gadget address in r3. 999 00:37:44,550 --> 00:37:46,500 And that's really all it took. 1000 00:37:46,500 --> 00:37:48,720 And we'll see here from the complete Rop 1001 00:37:48,720 --> 00:37:50,893 that we now have system execution 1002 00:37:50,893 --> 00:37:55,320 with our arbitrary socat as the parameter to it 1003 00:37:55,320 --> 00:37:57,330 and you see that we're on the break point 1004 00:37:57,330 --> 00:37:58,680 where it's about to get called 1005 00:37:58,680 --> 00:38:00,690 and that of course does work beautifully. 1006 00:38:00,690 --> 00:38:03,270 In an emulator doesn't go back real well to the hardware. 1007 00:38:03,270 --> 00:38:05,430 We might go back and figure that out at some point. 1008 00:38:05,430 --> 00:38:06,990 Either way all we cared about 1009 00:38:06,990 --> 00:38:08,640 was kinda learning this process 1010 00:38:08,640 --> 00:38:09,750 and getting the door to crash 1011 00:38:09,750 --> 00:38:11,880 so we could pick up our command injection. 1012 00:38:11,880 --> 00:38:15,680 That was then filed as our highest CVSS score of 10.0, 1013 00:38:15,680 --> 00:38:18,468 it is arbitrary unauthenticated code injection, 1014 00:38:18,468 --> 00:38:20,725 a code execution, excuse me. 1015 00:38:20,725 --> 00:38:23,340 and that was also patched. 1016 00:38:23,340 --> 00:38:25,230 So for the last part before we do our demo, 1017 00:38:25,230 --> 00:38:28,320 Sam's gonna take us through exploitation of this. 1018 00:38:28,320 --> 00:38:30,360 We call it malware with heavy quotes. 1019 00:38:30,360 --> 00:38:32,160 Obviously we're not releasing malware. 1020 00:38:32,160 --> 00:38:33,900 In fact, we're not even really writing malware, 1021 00:38:33,900 --> 00:38:36,090 but we are trying to interact with the door directly 1022 00:38:36,090 --> 00:38:38,093 and Sam's gonna show you how that's done. 1023 00:38:39,060 --> 00:38:39,893 - All right. 1024 00:38:39,893 --> 00:38:42,960 So we'll wrap this up here and then do the final demo. 1025 00:38:42,960 --> 00:38:44,250 So this kind of brought us 1026 00:38:44,250 --> 00:38:45,750 to the choose your pwn adventure four, 1027 00:38:45,750 --> 00:38:50,608 where now we got back our on command injection 1028 00:38:50,608 --> 00:38:53,430 with that reboot and chaining the two together. 1029 00:38:53,430 --> 00:38:55,200 And we could have gone about creating 1030 00:38:55,200 --> 00:38:57,907 our quote unquote malware in two different ways. 1031 00:38:57,907 --> 00:39:00,420 The people that were actually probably hacking 1032 00:39:00,420 --> 00:39:01,710 this in their life would probably 1033 00:39:01,710 --> 00:39:03,180 want to do some ransomware thing, 1034 00:39:03,180 --> 00:39:05,520 but that's not cool. 1035 00:39:05,520 --> 00:39:07,140 So we wanted to do the more James Bond 1036 00:39:07,140 --> 00:39:08,340 goes in the shell type approach 1037 00:39:08,340 --> 00:39:11,730 where we actually could gain secret access 1038 00:39:11,730 --> 00:39:14,457 into a facility, bypassing all monitoring or whatnot. 1039 00:39:14,457 --> 00:39:18,120 And so that's ended up what we went down that path, 1040 00:39:18,120 --> 00:39:19,680 but to do either of those, 1041 00:39:19,680 --> 00:39:21,000 we actually needed to figure out 1042 00:39:21,000 --> 00:39:23,430 how the door locks even works. 1043 00:39:23,430 --> 00:39:25,950 And I'm gonna kind of go quickly through this section. 1044 00:39:25,950 --> 00:39:27,690 These are through the use of relays, 1045 00:39:27,690 --> 00:39:30,030 which are electrical switches. 1046 00:39:30,030 --> 00:39:30,930 You can see them. 1047 00:39:30,930 --> 00:39:32,490 There's four here right now. 1048 00:39:32,490 --> 00:39:35,340 And then the switch is hooked up 1049 00:39:35,340 --> 00:39:36,600 or each of the door locks 1050 00:39:36,600 --> 00:39:39,300 are actually hooked up to these outputs. 1051 00:39:39,300 --> 00:39:40,860 To find out how the software 1052 00:39:40,860 --> 00:39:42,180 actually controls those relays. 1053 00:39:42,180 --> 00:39:44,310 You can look in the binary 1054 00:39:44,310 --> 00:39:46,890 that has all of its symbols for relays, 1055 00:39:46,890 --> 00:39:49,200 and you can see that there are one function 1056 00:39:49,200 --> 00:39:51,660 for on and off for each of these. 1057 00:39:51,660 --> 00:39:53,580 And there are even more simple when you look at 1058 00:39:53,580 --> 00:39:56,100 there is a simple kernel module 1059 00:39:56,100 --> 00:39:58,253 where you can interact with ioctl 1060 00:39:58,253 --> 00:40:01,190 give it the file descriptor for the GPIO device 1061 00:40:06,210 --> 00:40:09,180 and then a parameter and then a zero indexed array 1062 00:40:09,180 --> 00:40:12,240 of which relay you want actually control. 1063 00:40:12,240 --> 00:40:14,790 So to actually make this into our malware 1064 00:40:14,790 --> 00:40:17,370 and to open the door whenever we want, 1065 00:40:17,370 --> 00:40:19,479 we cross compiled it for arm 1066 00:40:19,479 --> 00:40:22,740 with just copying that ioctl call 1067 00:40:22,740 --> 00:40:24,570 and ran it on the device. 1068 00:40:24,570 --> 00:40:26,100 However, you can probably see 1069 00:40:26,100 --> 00:40:27,600 that there's this wild loop here 1070 00:40:27,600 --> 00:40:28,980 and this was our brute force way 1071 00:40:28,980 --> 00:40:30,870 to actually keep the door unlocked. 1072 00:40:30,870 --> 00:40:33,330 Whenever we would trigger an unlock, 1073 00:40:33,330 --> 00:40:34,890 it would instantly re-lock 1074 00:40:34,890 --> 00:40:36,840 so calling it every millisecond 1075 00:40:36,840 --> 00:40:40,436 was the right way to get it to state persistent, 1076 00:40:40,436 --> 00:40:43,290 which is kind of a fun hack right there. 1077 00:40:43,290 --> 00:40:45,750 But now we'll go on to the demo. 1078 00:40:45,750 --> 00:40:47,250 And I just wanna summarize kind of 1079 00:40:47,250 --> 00:40:49,890 what we've done up here on stage live. 1080 00:40:49,890 --> 00:40:51,600 This could have all been done 1081 00:40:51,600 --> 00:40:53,160 with our single click exploit, 1082 00:40:53,160 --> 00:40:54,900 but we wanted to separate it a little bit 1083 00:40:54,900 --> 00:40:56,940 and try to explain a little bit more. 1084 00:40:56,940 --> 00:40:58,920 The first thing we did was that command injection 1085 00:40:58,920 --> 00:41:01,140 through the host name, unauthenticated. 1086 00:41:01,140 --> 00:41:05,070 We then uploaded a arbitrary file from our update file 1087 00:41:05,070 --> 00:41:06,840 that we can control the signature size 1088 00:41:06,840 --> 00:41:08,760 to which cause a Segfault 1089 00:41:08,760 --> 00:41:12,660 initiating that reboot that we heard just a little bit ago, 1090 00:41:12,660 --> 00:41:15,330 at that point at the device startup 1091 00:41:15,330 --> 00:41:17,370 it's getting an IP address 1092 00:41:17,370 --> 00:41:20,490 and it's calling our command injection 1093 00:41:20,490 --> 00:41:21,990 through that host name parameter. 1094 00:41:21,990 --> 00:41:24,000 And at this point it's actually downloading more scripts 1095 00:41:24,000 --> 00:41:25,500 from this laptop up here 1096 00:41:25,500 --> 00:41:29,010 to run the reverse shell. 1097 00:41:29,010 --> 00:41:31,590 And then that reverse shell gets opened. 1098 00:41:31,590 --> 00:41:33,660 And now we'll show you live connecting 1099 00:41:33,660 --> 00:41:37,470 to that reverse shell and opening the command. 1100 00:41:37,470 --> 00:41:38,730 So here we go. 1101 00:41:38,730 --> 00:41:40,030 Let's see if we can do it. 1102 00:41:46,366 --> 00:41:49,097 All right, switch to Dvorak. 1103 00:41:52,980 --> 00:41:53,883 Let me clear this. 1104 00:42:03,810 --> 00:42:05,790 - Stevens was joking we could make this lot easier 1105 00:42:05,790 --> 00:42:07,830 and save you guys 50 minutes by doing this, 1106 00:42:07,830 --> 00:42:09,980 but I think they were being smart asses so. 1107 00:42:11,850 --> 00:42:14,610 - All right, so here's the reverse shell connection. 1108 00:42:14,610 --> 00:42:15,510 We'll go ahead and connect it 1109 00:42:15,510 --> 00:42:18,210 and you can see that we do have a shell. 1110 00:42:18,210 --> 00:42:19,953 And if I run who am I, 1111 00:42:23,970 --> 00:42:28,620 we are root and then enter to finalize it, 1112 00:42:28,620 --> 00:42:32,310 we'll run our super elite open door hack. 1113 00:42:32,310 --> 00:42:33,143 So here we go. 1114 00:42:35,850 --> 00:42:40,843 Woo! (audience cheering and clapping) 1115 00:42:44,520 --> 00:42:48,390 All right, so that was everything we have today. 1116 00:42:48,390 --> 00:42:49,650 Thank you guys so much for coming. 1117 00:42:49,650 --> 00:42:51,930 We're gonna stick around for a couple minutes for questions. 1118 00:42:51,930 --> 00:42:53,340 Wanna thank carrier as well 1119 00:42:53,340 --> 00:42:55,050 who would handle the disclosure process 1120 00:42:55,050 --> 00:42:56,820 to mercury they're here today. 1121 00:42:56,820 --> 00:42:57,690 Thanks to that team. 1122 00:42:57,690 --> 00:42:59,100 Thank you guys for attending. 1123 00:42:59,100 --> 00:43:01,650 If you want to connect with us on social media 1124 00:43:01,650 --> 00:43:03,810 or just stop by for questions, feel free. 1125 00:43:03,810 --> 00:43:04,643 Thank you so much. 1126 00:43:04,643 --> 00:43:06,000 Enjoy the rest of your DEFCON.