1 00:00:00,720 --> 00:00:01,770 - All right. 2 00:00:01,770 --> 00:00:03,540 Daniel Jensen's gonna be talking to us 3 00:00:03,540 --> 00:00:06,003 about some bug hunting in the tropics. 4 00:00:09,018 --> 00:00:10,650 (audience clapping) 5 00:00:10,650 --> 00:00:11,943 - Thank you, thank you. 6 00:00:13,560 --> 00:00:14,640 Okay. 7 00:00:14,640 --> 00:00:16,860 This is hunting bugs in the tropics. 8 00:00:16,860 --> 00:00:19,140 About me, my name's Daniel Jensen, 9 00:00:19,140 --> 00:00:21,330 I live in Auckland in New Zealand, 10 00:00:21,330 --> 00:00:23,430 and I work as a pen tester and red teamer 11 00:00:23,430 --> 00:00:26,100 at a company called CyberCX. 12 00:00:26,100 --> 00:00:27,600 This talk is about some bugs I found 13 00:00:27,600 --> 00:00:30,030 while I was living in the tropics. 14 00:00:30,030 --> 00:00:32,700 So there's an island called Aruba. 15 00:00:32,700 --> 00:00:34,590 It's a country that's a constituent 16 00:00:34,590 --> 00:00:37,080 of the Kingdom of the Netherlands. 17 00:00:37,080 --> 00:00:39,120 It's just north of Venezuela. 18 00:00:39,120 --> 00:00:41,520 There's also an enterprise networking vendor called Aruba, 19 00:00:41,520 --> 00:00:44,370 and it was bought by HPE in 2015. 20 00:00:44,370 --> 00:00:46,373 And we're gonna be talking about that Aruba. 21 00:00:47,490 --> 00:00:48,870 So a bit of background on this talk, 22 00:00:48,870 --> 00:00:50,880 these are vulnerabilities I've submitted 23 00:00:50,880 --> 00:00:53,160 to Aruba's Bug Bounty Program. 24 00:00:53,160 --> 00:00:56,043 It's a good program, they're good, easy to work with, 25 00:00:57,030 --> 00:00:59,130 and let me talk about these bugs, 26 00:00:59,130 --> 00:01:00,480 which is very cool of them. 27 00:01:02,220 --> 00:01:03,660 Yep. 28 00:01:03,660 --> 00:01:08,040 So I'm gonna cover four products that they make. 29 00:01:08,040 --> 00:01:11,610 So there's the AP, which is like a wireless AP. 30 00:01:11,610 --> 00:01:14,250 There's ClearPass, which is a policy manager. 31 00:01:14,250 --> 00:01:17,040 There's Airwave, which is network management 32 00:01:17,040 --> 00:01:18,660 and along those kind of lines. 33 00:01:18,660 --> 00:01:19,530 And then there's Glass, 34 00:01:19,530 --> 00:01:24,000 which is a single pane of glass that agglomerates 35 00:01:24,000 --> 00:01:26,670 airwave data. 36 00:01:26,670 --> 00:01:29,490 So this is a terrible diagram of how they relate 37 00:01:29,490 --> 00:01:31,320 to each other in a network 38 00:01:31,320 --> 00:01:34,800 and how you might find them configured, just Aruba stuff. 39 00:01:34,800 --> 00:01:36,243 So, first thing is the AP. 40 00:01:38,310 --> 00:01:40,620 I put the least amount of time into researching this, 41 00:01:40,620 --> 00:01:43,350 and mostly focused on post-auth tech servers. 42 00:01:43,350 --> 00:01:45,000 Interestingly, I actually had some bug collisions 43 00:01:45,000 --> 00:01:46,560 with other researchers as well, 44 00:01:46,560 --> 00:01:48,270 which they wrote up in their post, 45 00:01:48,270 --> 00:01:49,653 the Aleph Security. 46 00:01:50,640 --> 00:01:52,650 So a bit of technical details. 47 00:01:52,650 --> 00:01:54,780 The IAPs run something called ArubaOS, 48 00:01:54,780 --> 00:01:58,190 which is a operating system that they chip on it. 49 00:01:58,190 --> 00:02:03,190 It uses a Linux kernel and the newer AP's, mostly ARM, 50 00:02:03,810 --> 00:02:06,720 and some of the old ones use the MIPS architecture 51 00:02:06,720 --> 00:02:10,770 that ArubaOS image is signed and it's verified at boot, 52 00:02:10,770 --> 00:02:13,320 so it's actually quite decent compared to some other 53 00:02:13,320 --> 00:02:14,313 networking vendors. 54 00:02:15,360 --> 00:02:16,530 In terms of tech servers, 55 00:02:16,530 --> 00:02:19,530 they have a telnet server if you enable it, 56 00:02:19,530 --> 00:02:23,550 there's SSH, there's a web server on the instance. 57 00:02:23,550 --> 00:02:26,223 They talk to each other using a protocol PAPI, 58 00:02:28,290 --> 00:02:31,440 and they also some of the new ones talk to Aruba Central, 59 00:02:31,440 --> 00:02:33,903 which is their cloud management based thing. 60 00:02:35,190 --> 00:02:37,410 So, if we wanna get started on researching this, 61 00:02:37,410 --> 00:02:38,243 what do we do? 62 00:02:38,243 --> 00:02:41,430 Well, just get an image and extract files off it, 63 00:02:41,430 --> 00:02:43,809 which is easy, thankfully. 64 00:02:43,809 --> 00:02:45,303 binwalk will do it happily. 65 00:02:46,530 --> 00:02:50,980 And it's just two rounds of LZMA and inside a CPIO archive. 66 00:02:52,470 --> 00:02:54,780 And you can see there, that's how to do it. 67 00:02:54,780 --> 00:02:56,940 There's also a bit of GPL source code on GitHub, 68 00:02:56,940 --> 00:02:59,460 which some enterprising individual has, 69 00:02:59,460 --> 00:03:01,830 I believe requested from Aruba and published online, 70 00:03:01,830 --> 00:03:04,630 which was nice of them, so you can look at that as well. 71 00:03:05,790 --> 00:03:09,660 So we also wanna get runtime access to the APs. 72 00:03:09,660 --> 00:03:11,760 So the way I went about this is, 73 00:03:11,760 --> 00:03:14,790 first find an exploit and then exploit the bug, 74 00:03:14,790 --> 00:03:18,720 and then I set up my own research environment 75 00:03:18,720 --> 00:03:20,400 on the AP. 76 00:03:20,400 --> 00:03:25,040 So pull things across, like I compiled tcpdump, gdbserver, 77 00:03:26,040 --> 00:03:27,900 and the easiest way to do that 78 00:03:27,900 --> 00:03:29,610 is using something called Buildroot, 79 00:03:29,610 --> 00:03:31,560 and Buildroot's an awesome set of scripts 80 00:03:31,560 --> 00:03:34,230 that you can basically will cross compile 81 00:03:34,230 --> 00:03:36,720 for all sorts of different architectures. 82 00:03:36,720 --> 00:03:39,060 And you can build static libraries. 83 00:03:39,060 --> 00:03:40,530 So static binaries, 84 00:03:40,530 --> 00:03:42,810 so you don't have to worry about libseek, compatibility, 85 00:03:42,810 --> 00:03:44,520 or anything like that. 86 00:03:44,520 --> 00:03:45,870 It's got a nice little interface. 87 00:03:45,870 --> 00:03:48,630 You can just go into it, tick the boxes for things you want, 88 00:03:48,630 --> 00:03:50,417 and it'll build that for you. 89 00:03:50,417 --> 00:03:52,980 So you can pull across things like tcpdump, 90 00:03:52,980 --> 00:03:56,760 so I can dump, look at what's going on in the interfaces. 91 00:03:56,760 --> 00:04:01,200 And a gdbstub, so you can attach to running processes 92 00:04:01,200 --> 00:04:03,870 on the AP and see what's going on in them. 93 00:04:03,870 --> 00:04:05,070 And that's just stub, 94 00:04:05,070 --> 00:04:07,500 so you can connect to the stub from the comfort 95 00:04:07,500 --> 00:04:11,280 of your X64 host using gdb-multiarch. 96 00:04:11,280 --> 00:04:14,640 And it will actually pull the binary across the wire 97 00:04:14,640 --> 00:04:18,120 using the gdbprotocol and all the libraries it has loaded. 98 00:04:18,120 --> 00:04:20,793 So that's makes it nice and easy. 99 00:04:22,290 --> 00:04:26,040 First bug is the, I found DHCP command injection. 100 00:04:26,040 --> 00:04:29,280 So I found this reading the docs for the AP, 101 00:04:29,280 --> 00:04:33,300 and it said, when it boots and it's not configured, 102 00:04:33,300 --> 00:04:34,860 it looks for an AirWave, 103 00:04:34,860 --> 00:04:36,480 and it does this a few different ways. 104 00:04:36,480 --> 00:04:40,080 And one of the ways it does it is by looking for, 105 00:04:40,080 --> 00:04:43,200 doing a DNS lookup and that DNS lookup uses 106 00:04:43,200 --> 00:04:45,570 the domain name suffix that you provide it 107 00:04:45,570 --> 00:04:48,360 when you hand it a DHCP lease. 108 00:04:48,360 --> 00:04:49,830 So in the DHCP lease, 109 00:04:49,830 --> 00:04:52,200 you can set dhcp-option=15 110 00:04:52,200 --> 00:04:54,240 and put a command injection in that, 111 00:04:54,240 --> 00:04:59,130 and that ultimately is run and gets you root access 112 00:04:59,130 --> 00:05:00,450 to the AP. 113 00:05:00,450 --> 00:05:03,810 So practically this bug's not that useful. 114 00:05:03,810 --> 00:05:06,450 It only really works when it's not otherwise configured, 115 00:05:06,450 --> 00:05:09,780 so it's not something you'd probably use on a job, 116 00:05:09,780 --> 00:05:11,880 but it's good for getting research access. 117 00:05:14,340 --> 00:05:17,760 Second issue I found was a command injection. 118 00:05:17,760 --> 00:05:21,570 So this worked in a somewhat convoluted way 119 00:05:21,570 --> 00:05:25,530 where you had a file write into that directory, 120 00:05:25,530 --> 00:05:27,993 the /etc/httpd/custom/image directory, 121 00:05:29,430 --> 00:05:34,430 and you could create a binary that had things like backticks 122 00:05:34,440 --> 00:05:36,720 so meta characters in the file name. 123 00:05:36,720 --> 00:05:39,000 And then when you run the show amp-audit command 124 00:05:39,000 --> 00:05:40,500 that takes the name of the file 125 00:05:40,500 --> 00:05:42,930 you've written into the directory 126 00:05:42,930 --> 00:05:45,330 and inserts it unsafely into a system call, 127 00:05:45,330 --> 00:05:47,880 so there's a command injection there. 128 00:05:47,880 --> 00:05:50,460 But there's a few restrictions on the file name, 129 00:05:50,460 --> 00:05:53,160 so obviously you can't have a slash 'cause it's a file name, 130 00:05:53,160 --> 00:05:54,930 but there's also some length restrictions. 131 00:05:54,930 --> 00:05:57,300 So it was easy enough to do backtick id, 132 00:05:57,300 --> 00:05:59,040 good enough for a proof of concept, 133 00:05:59,040 --> 00:06:01,410 but I wanna get a shell out of it. 134 00:06:01,410 --> 00:06:04,770 So that's what the decompiled code looks like, 135 00:06:04,770 --> 00:06:06,120 that's calling system. 136 00:06:06,120 --> 00:06:08,490 So, how do you actually get a shell 137 00:06:08,490 --> 00:06:11,070 when you have quite a short length restriction? 138 00:06:11,070 --> 00:06:14,013 Well, I actually ended up coming up with this monstrosity, 139 00:06:15,570 --> 00:06:17,910 which there's a lot going on in there. 140 00:06:17,910 --> 00:06:21,870 So what's happening here is the backtick 141 00:06:21,870 --> 00:06:23,400 start off the command injection. 142 00:06:23,400 --> 00:06:27,826 Then you use the sh which refers to the shell interpreter. 143 00:06:27,826 --> 00:06:29,460 IFS is the field separator, 144 00:06:29,460 --> 00:06:31,533 which you can use as a space, basically. 145 00:06:32,700 --> 00:06:36,570 On ArubaOS the $HOME environment is /. 146 00:06:36,570 --> 00:06:39,150 So I set the, create a new variable called A, 147 00:06:39,150 --> 00:06:39,983 which is /, 148 00:06:39,983 --> 00:06:44,070 which is how I refer to the / 'cause a $HOME is too long. 149 00:06:44,070 --> 00:06:47,820 And then I just wild card through some various directories 150 00:06:47,820 --> 00:06:51,720 so that after resolving the variables looks like this. 151 00:06:51,720 --> 00:06:53,910 And then after you resolve the wild cards, 152 00:06:53,910 --> 00:06:55,530 it looks like the thing at the bottom. 153 00:06:55,530 --> 00:06:59,910 So it's basically referring to itself, and will run itself. 154 00:06:59,910 --> 00:07:02,883 On a Linux host this is how it looks, 155 00:07:03,780 --> 00:07:06,090 so you can see there's the contents of that file 156 00:07:06,090 --> 00:07:07,440 is just the id command, 157 00:07:07,440 --> 00:07:10,560 and then when you emulate a command injection, 158 00:07:10,560 --> 00:07:13,260 you can see it's actually running itself. 159 00:07:13,260 --> 00:07:16,890 So the trick there is you wanna look at, 160 00:07:16,890 --> 00:07:21,890 even if you have restrictions on characters or things, 161 00:07:22,050 --> 00:07:23,850 when you're trying to exploit a command injection, 162 00:07:23,850 --> 00:07:26,040 the environment's quite a good place to look. 163 00:07:26,040 --> 00:07:30,720 There's often things like semicolons and on some boxes, 164 00:07:30,720 --> 00:07:34,053 depending on how the environment's configured. 165 00:07:35,010 --> 00:07:36,330 And I also use that in another 166 00:07:36,330 --> 00:07:37,920 command injection vulnerability 167 00:07:37,920 --> 00:07:42,270 whereby they didn't let me do backticks or anything. 168 00:07:42,270 --> 00:07:44,790 And I could do a $ and a left parentheses, 169 00:07:44,790 --> 00:07:46,230 which is like a sub shell, 170 00:07:46,230 --> 00:07:48,540 but if it was followed by a right parentheses, 171 00:07:48,540 --> 00:07:49,590 they dis allowed it. 172 00:07:49,590 --> 00:07:51,570 So what I did is just actually define that 173 00:07:51,570 --> 00:07:54,580 right parentheses as a variable before 174 00:07:54,580 --> 00:07:57,813 the $ and left parentheses and then use afterwards. 175 00:07:58,740 --> 00:08:01,440 So yeah, check out the environment variables, 176 00:08:01,440 --> 00:08:04,443 it's a good place to source characters you may need. 177 00:08:05,970 --> 00:08:07,733 I'm just gonna grab a drink of water. 178 00:08:11,400 --> 00:08:15,240 Okay, Target 2 ClearPass Policy Manager. 179 00:08:15,240 --> 00:08:19,440 So this does network access control and policy management, 180 00:08:19,440 --> 00:08:20,790 and that sort of thing. 181 00:08:20,790 --> 00:08:25,500 Comes as like a physical hardware or a virtual appliance. 182 00:08:25,500 --> 00:08:28,403 That's what it looks like, oh, the web interface looks like. 183 00:08:29,460 --> 00:08:30,690 The tech stack looks like this, 184 00:08:30,690 --> 00:08:34,560 so it's running Linux CentOS 7, and it's got Apache, 185 00:08:34,560 --> 00:08:36,330 it's got Tomcat, it's got PHP, 186 00:08:36,330 --> 00:08:38,190 it's got Golang microservices, 187 00:08:38,190 --> 00:08:41,790 it's got Python microservices, there's a lot going on. 188 00:08:41,790 --> 00:08:43,590 And you can also encrypt the disc on it, 189 00:08:43,590 --> 00:08:47,763 which is a nice feature when you deploy it. 190 00:08:49,260 --> 00:08:51,390 So getting runtime access to this, 191 00:08:51,390 --> 00:08:53,550 unfortunately it restricts us to a subshell. 192 00:08:53,550 --> 00:08:56,310 So we don't get a proper shell with a SSH to it. 193 00:08:56,310 --> 00:08:57,930 So this is quite common, 194 00:08:57,930 --> 00:09:01,470 and the way I usually deal with this is just boot 195 00:09:01,470 --> 00:09:03,900 the appliance with a live CD image. 196 00:09:03,900 --> 00:09:08,340 So I normally use gparted and then you can mount the disc 197 00:09:08,340 --> 00:09:11,550 and then just add a new user to the files and Linux, 198 00:09:11,550 --> 00:09:15,480 that you might need to access password, shadow, sudoers, 199 00:09:15,480 --> 00:09:17,250 that sort of thing, reboot it, 200 00:09:17,250 --> 00:09:18,810 and then you can log into it properly. 201 00:09:18,810 --> 00:09:21,060 And that generally works quite well 202 00:09:21,060 --> 00:09:22,710 when you're reversing appliances. 203 00:09:23,610 --> 00:09:26,610 ClearPass supports disc encryption. 204 00:09:26,610 --> 00:09:31,610 So this is how you can pull the encryption key for the disc 205 00:09:31,680 --> 00:09:32,940 because when you boot it, 206 00:09:32,940 --> 00:09:35,760 it doesn't want to be asking you for a encryption password 207 00:09:35,760 --> 00:09:37,800 because people would get annoyed by that. 208 00:09:37,800 --> 00:09:40,500 So they have to store the encryption password for the disc. 209 00:09:40,500 --> 00:09:43,230 And the way they do that is they just store it 210 00:09:43,230 --> 00:09:46,113 in the initramfs, you can pull it out like that. 211 00:09:48,360 --> 00:09:50,040 Here's the Attack surface, 212 00:09:50,040 --> 00:09:52,893 that little goose there represents the attacker, or me. 213 00:09:54,090 --> 00:09:56,040 And there's a few things you can hit directly, 214 00:09:56,040 --> 00:09:58,593 but most of it's via Apache. 215 00:10:00,270 --> 00:10:03,270 So these are the Apache configs, there's a lot of them, 216 00:10:03,270 --> 00:10:06,240 there's I think about 20 different config files 217 00:10:06,240 --> 00:10:10,230 they use to define all sorts of ways of routing 218 00:10:10,230 --> 00:10:13,650 your http requests to the backend applications. 219 00:10:13,650 --> 00:10:15,270 And on the right, there are just some snippets 220 00:10:15,270 --> 00:10:16,260 of some of those files. 221 00:10:16,260 --> 00:10:19,860 So, there's quite a lot of different ways 222 00:10:19,860 --> 00:10:22,683 of getting access to the surfaces. 223 00:10:23,880 --> 00:10:27,870 It has two Tomcat instances called backend and frontend, 224 00:10:27,870 --> 00:10:31,440 and frontend has an application in it called tips. 225 00:10:31,440 --> 00:10:34,803 And that's the main Java web application. 226 00:10:36,090 --> 00:10:39,120 So I looked at that first. 227 00:10:39,120 --> 00:10:41,760 What I do is I look at the web xml file 228 00:10:41,760 --> 00:10:45,540 and you can see what the server mapping does 229 00:10:45,540 --> 00:10:48,900 is maps like a URL pattern to a servlet class, 230 00:10:48,900 --> 00:10:53,220 and so I just go and look at that servlet class. 231 00:10:53,220 --> 00:10:55,890 It also has struts which defines other routs 232 00:10:55,890 --> 00:10:59,160 to other areas of the Java code. 233 00:10:59,160 --> 00:11:03,420 It also has something called DWR or direct web promoting, 234 00:11:03,420 --> 00:11:04,950 and that's quite interesting, 235 00:11:04,950 --> 00:11:06,360 I hadn't come across that before. 236 00:11:06,360 --> 00:11:08,820 And what that does is you configure, 237 00:11:08,820 --> 00:11:12,450 you put a class name in the dwr.xml file, 238 00:11:12,450 --> 00:11:16,880 and it then exposes every method inside that Java class, 239 00:11:18,750 --> 00:11:20,673 to being called remotely. 240 00:11:22,110 --> 00:11:24,180 So there's quite a lot of Attack surface there, 241 00:11:24,180 --> 00:11:26,490 and I think some of the vulnerabilities I found 242 00:11:26,490 --> 00:11:29,400 were not intended to be reachable, 243 00:11:29,400 --> 00:11:31,560 but because they include the whole class, 244 00:11:31,560 --> 00:11:34,413 there's various methods in there that can be reached. 245 00:11:35,550 --> 00:11:39,120 So because we have root access to the ClearPass, 246 00:11:39,120 --> 00:11:41,400 what you can do is just go and enable debug mode 247 00:11:41,400 --> 00:11:43,980 for direct web remoting, which gives you a nice 248 00:11:43,980 --> 00:11:44,940 HTML interface, 249 00:11:44,940 --> 00:11:48,330 so you can just go and click around and see all the various 250 00:11:48,330 --> 00:11:50,463 methods and such that you can call. 251 00:11:55,710 --> 00:11:58,140 So the next step is to decompile the Java code. 252 00:11:58,140 --> 00:11:59,910 And I like using Procyon for doing that 253 00:11:59,910 --> 00:12:04,910 because Procyon has a flag sl or stretch lines. 254 00:12:05,160 --> 00:12:07,800 And what that does is in the output decompiled code, 255 00:12:07,800 --> 00:12:10,320 it will match the Java files, 256 00:12:10,320 --> 00:12:14,880 it generates lines to the line numbers in the line table, 257 00:12:14,880 --> 00:12:19,380 and insert new lines where they're needed. 258 00:12:19,380 --> 00:12:20,310 And what that buys you 259 00:12:20,310 --> 00:12:22,683 is the ability to do line based debugging, 260 00:12:23,550 --> 00:12:25,980 which makes it easier when you're debugging an application, 261 00:12:25,980 --> 00:12:27,873 want to break on a specific line. 262 00:12:29,520 --> 00:12:33,540 And you can debug applications from decompiled code, 263 00:12:33,540 --> 00:12:35,220 which was actually kind of a surprise to me, 264 00:12:35,220 --> 00:12:39,210 but it works well enough if you just load that code in 265 00:12:39,210 --> 00:12:40,960 that you've decompiled into an IDE. 266 00:12:42,330 --> 00:12:46,230 And I use IntelliJ IDEA, 267 00:12:46,230 --> 00:12:50,370 and then just set up a remote debugger like this, 268 00:12:50,370 --> 00:12:52,110 and then connect to it. 269 00:12:52,110 --> 00:12:53,520 And that gets you all sorts of good things, 270 00:12:53,520 --> 00:12:56,280 like you can see the stack trace, 271 00:12:56,280 --> 00:12:59,160 you can see the variables at runtime, 272 00:12:59,160 --> 00:13:02,850 so if the static code that you're trying to read 273 00:13:02,850 --> 00:13:04,350 is utterly inscrutable, 274 00:13:04,350 --> 00:13:07,800 you can connect to it and see what's going on at runtime, 275 00:13:07,800 --> 00:13:09,240 which is quite helpful. 276 00:13:09,240 --> 00:13:11,640 Another good feature of that is you can set breakpoints 277 00:13:11,640 --> 00:13:13,140 on interesting syncs. 278 00:13:13,140 --> 00:13:16,440 So ProcessBuilder runs a command in Java. 279 00:13:16,440 --> 00:13:19,530 So what I do here is set the breakpoint 280 00:13:19,530 --> 00:13:23,370 that dumps the stack trace and prints the command, 281 00:13:23,370 --> 00:13:25,440 but it doesn't actually break the application 282 00:13:25,440 --> 00:13:29,040 so you can set this up when you're connected 283 00:13:29,040 --> 00:13:31,140 to the application, and then go to the app 284 00:13:31,140 --> 00:13:32,700 and click around it, do some stuff, 285 00:13:32,700 --> 00:13:34,590 and then come back and look at your logs, 286 00:13:34,590 --> 00:13:36,120 and you get things like this 287 00:13:36,120 --> 00:13:38,730 which just show commands that are being executed 288 00:13:38,730 --> 00:13:40,410 via ProcessBuilder, 289 00:13:40,410 --> 00:13:44,763 and what the stack trace looked like at the time. 290 00:13:49,200 --> 00:13:50,733 So first vulnerability, 291 00:13:51,780 --> 00:13:54,180 there's an Nmap argument injection that was reachable 292 00:13:54,180 --> 00:13:58,170 via a path traversal, it worked like this. 293 00:13:58,170 --> 00:14:01,560 That's the relevant Apache config file, 294 00:14:01,560 --> 00:14:05,020 so you can see it's mounting the activitydumpservice alias 295 00:14:06,150 --> 00:14:10,710 via JkMount, which mounts it into a Tomcat worker. 296 00:14:10,710 --> 00:14:14,131 So any URL that starts with activitydumpservice 297 00:14:14,131 --> 00:14:17,400 will be sent to backendtomcat, 298 00:14:17,400 --> 00:14:19,647 but you can do a traversal in there with the 299 00:14:19,647 --> 00:14:24,647 ..;/trick because Apache sees that URL at the top 300 00:14:24,660 --> 00:14:26,550 as starting with activitydumpservice, 301 00:14:26,550 --> 00:14:30,390 whereas Tomcat actually follows that traversal 302 00:14:30,390 --> 00:14:32,490 and will send you to network services, 303 00:14:32,490 --> 00:14:34,650 which is otherwise unreachable. 304 00:14:34,650 --> 00:14:37,770 So I could access this without authentication. 305 00:14:37,770 --> 00:14:40,470 And what it does is posture validation, 306 00:14:40,470 --> 00:14:44,283 which basically lets you nmap an arbitrary IP address. 307 00:14:45,900 --> 00:14:49,683 This is a snippet of the Aruba code that was in there. 308 00:14:52,020 --> 00:14:53,850 And that looks pretty vulnerable, right? 309 00:14:53,850 --> 00:14:56,730 It's taking the host IP and just constructing 310 00:14:56,730 --> 00:14:59,850 a string out of it, and passing it to runtime get exec 311 00:14:59,850 --> 00:15:02,190 where you could just command inject it, right? 312 00:15:02,190 --> 00:15:05,580 No you can't because Runtime getRuntime.exec 313 00:15:05,580 --> 00:15:08,880 doesn't actually invoke a shell, it tokenizes that, 314 00:15:08,880 --> 00:15:10,800 and then on the bottom right there, 315 00:15:10,800 --> 00:15:15,800 you can see the execve is not splitting that into 316 00:15:17,520 --> 00:15:19,110 the ls and the id command, 317 00:15:19,110 --> 00:15:22,560 it's just running, trying to ls that file 318 00:15:22,560 --> 00:15:23,700 that doesn't exist. 319 00:15:23,700 --> 00:15:27,153 So it's not vulnerable to command injection. 320 00:15:28,020 --> 00:15:33,020 If we see when we test it here, that the whoami command 321 00:15:33,990 --> 00:15:36,930 doesn't run and it doesn't work. 322 00:15:36,930 --> 00:15:39,690 But it is vulnerable to argument injection. 323 00:15:39,690 --> 00:15:41,400 What's argument injection? 324 00:15:41,400 --> 00:15:43,110 I kind of explain it like, 325 00:15:43,110 --> 00:15:46,020 command injection lets you execute arbitrary commands. 326 00:15:46,020 --> 00:15:48,320 Whereas argument injection lets you manipulate 327 00:15:49,770 --> 00:15:51,783 the arguments to a command. 328 00:15:52,650 --> 00:15:55,080 And that doesn't sound super useful, 329 00:15:55,080 --> 00:15:58,110 but it actually is quite useful. 330 00:15:58,110 --> 00:16:01,020 A lot of binaries have useful flags 331 00:16:01,020 --> 00:16:03,060 you can call that do dangerous things. 332 00:16:03,060 --> 00:16:06,510 That gtfobins is a good resource for it. 333 00:16:06,510 --> 00:16:10,230 And I also see this quite often, where I think the devs 334 00:16:10,230 --> 00:16:14,520 have fixed a command injection issue previously, 335 00:16:14,520 --> 00:16:17,310 but they haven't fixed an argument injection 336 00:16:17,310 --> 00:16:19,950 in the same area because fixing command injection, 337 00:16:19,950 --> 00:16:21,000 depending on how you do it, 338 00:16:21,000 --> 00:16:24,630 doesn't necessarily prevent argument injection. 339 00:16:24,630 --> 00:16:26,640 So I think this is a really underrated bug class 340 00:16:26,640 --> 00:16:28,200 and definitely one to watch out for 341 00:16:28,200 --> 00:16:29,650 given how often I've seen it. 342 00:16:30,840 --> 00:16:34,680 Anyway, we can do argument injection in that Nmap call. 343 00:16:34,680 --> 00:16:36,990 So you can see I'm running the help command, 344 00:16:36,990 --> 00:16:39,330 but there's also a, sorry, the help flag, 345 00:16:39,330 --> 00:16:41,040 but there's also more useful flags 346 00:16:41,040 --> 00:16:42,840 you can use for exploitation. 347 00:16:42,840 --> 00:16:44,580 So obviously you can just write 348 00:16:44,580 --> 00:16:47,700 the Nmap output into various directories. 349 00:16:47,700 --> 00:16:49,770 It also has a script http-fetch, 350 00:16:49,770 --> 00:16:51,510 which is included by default, 351 00:16:51,510 --> 00:16:56,250 that will let you pull in a file from a remote host, 352 00:16:56,250 --> 00:16:57,390 the one you're scanning 353 00:16:57,390 --> 00:16:59,430 and write it to a directory you specify. 354 00:16:59,430 --> 00:17:01,440 And in that scripts are Lua, 355 00:17:01,440 --> 00:17:04,350 so you can execute arbitrary commands through them. 356 00:17:04,350 --> 00:17:06,243 Like the bottom there is os.execute. 357 00:17:07,290 --> 00:17:09,360 So the way I exploit it is like this, 358 00:17:09,360 --> 00:17:11,907 the bit and blue is the directory traversal, 359 00:17:11,907 --> 00:17:14,040 and then the bit in red you can see at the top, 360 00:17:14,040 --> 00:17:15,000 in the first request, 361 00:17:15,000 --> 00:17:18,750 I'm fetching a script from my host 362 00:17:18,750 --> 00:17:22,200 and storing it in the temp Z folder. 363 00:17:22,200 --> 00:17:23,033 Then the second one, 364 00:17:23,033 --> 00:17:25,800 I actually just specify that as a script 365 00:17:25,800 --> 00:17:27,240 and that contains my shell, 366 00:17:27,240 --> 00:17:30,273 So it can run code like that through the argument injection. 367 00:17:31,140 --> 00:17:32,130 if we don't have egress, 368 00:17:32,130 --> 00:17:34,590 you can also get around it because on ClearPass 369 00:17:34,590 --> 00:17:37,173 it has the guest application, which is php, 370 00:17:38,130 --> 00:17:42,540 and what you can do is just write into that directory, 371 00:17:42,540 --> 00:17:45,513 which is the web root and write a php shell. 372 00:17:48,360 --> 00:17:49,980 XSS is pretty straightforward. 373 00:17:49,980 --> 00:17:52,260 I'm not gonna go into that too much detail here, 374 00:17:52,260 --> 00:17:55,801 but basically there's an area that you could reach 375 00:17:55,801 --> 00:17:58,260 unauthenticated depending on the config. 376 00:17:58,260 --> 00:18:00,300 You could see at that post request 377 00:18:00,300 --> 00:18:02,010 with XSS payload, 378 00:18:02,010 --> 00:18:04,800 didn't fire in the main application, 379 00:18:04,800 --> 00:18:07,560 but another area of the application, it did fire. 380 00:18:07,560 --> 00:18:12,330 So XSS is really in my mind an output and coding issue. 381 00:18:12,330 --> 00:18:15,240 So even if it's not firing in one area of the application, 382 00:18:15,240 --> 00:18:16,260 there are other areas, 383 00:18:16,260 --> 00:18:18,360 make sure you've checked all the areas 384 00:18:18,360 --> 00:18:22,503 to see if that same payload is, user data is elsewhere. 385 00:18:27,998 --> 00:18:29,460 Okay, Classloader manipulation. 386 00:18:29,460 --> 00:18:34,320 So, a while ago there was a classic Struts 1 vulnerability, 387 00:18:34,320 --> 00:18:38,407 and that was n2, and that was jet down to 388 00:18:38,407 --> 00:18:42,837 it using this library Apache BeanUtils and calling populate 389 00:18:42,837 --> 00:18:46,830 on a bean with used supplied data. 390 00:18:46,830 --> 00:18:48,540 And what that lets you do is call 391 00:18:48,540 --> 00:18:50,370 arbitrary getters and setters. 392 00:18:50,370 --> 00:18:53,940 But at the time they hadn't blocked you 393 00:18:53,940 --> 00:18:56,741 from calling getClass and getClassLoader, 394 00:18:56,741 --> 00:19:01,741 which lets you set arbitrary values in the class loader, 395 00:19:02,054 --> 00:19:03,840 which can be quite useful. 396 00:19:03,840 --> 00:19:08,840 So ClearPass used to use a vulnerable version of BeanUtils 397 00:19:11,430 --> 00:19:12,630 which was vulnerable to that. 398 00:19:12,630 --> 00:19:16,080 And it also had an unauthenticated HTTP endpoint 399 00:19:16,080 --> 00:19:18,753 that let you directly pass user data to it. 400 00:19:19,860 --> 00:19:23,880 So when I found this ClearPass was using Tomcat 7 401 00:19:23,880 --> 00:19:26,370 and there's no publicly non proof of concept 402 00:19:26,370 --> 00:19:30,270 for turning Classloader manipulation 403 00:19:30,270 --> 00:19:34,290 into code exec in Tomcat 7, on Linux. 404 00:19:34,290 --> 00:19:37,380 But you can do other things like overriding the docBase, 405 00:19:37,380 --> 00:19:39,870 and you can set alias. 406 00:19:39,870 --> 00:19:42,210 And what setting in alias lets you do, 407 00:19:42,210 --> 00:19:43,980 is basically aliases 408 00:19:43,980 --> 00:19:47,400 like a URL to a path on the file system, 409 00:19:47,400 --> 00:19:49,860 so that gives you an arbitrary read. 410 00:19:49,860 --> 00:19:52,017 Also, if you have the ability to upload files 411 00:19:52,017 --> 00:19:56,190 to the file system, you can set the alias to that directory 412 00:19:56,190 --> 00:19:59,553 and upload a JSP shell. 413 00:20:00,720 --> 00:20:03,063 So, okay, we have an arm-read. 414 00:20:03,930 --> 00:20:08,100 On ClearPass it's often set up in a cluster mode. 415 00:20:08,100 --> 00:20:10,290 And even when it's not, it creates this file here, 416 00:20:10,290 --> 00:20:12,330 the cluster-password.properties, 417 00:20:12,330 --> 00:20:14,280 and that contains the clear text password 418 00:20:14,280 --> 00:20:16,170 for the cluster admin user. 419 00:20:16,170 --> 00:20:18,390 And that buys you a lot, 'cause the cluster admin user 420 00:20:18,390 --> 00:20:19,923 is very highly privileged. 421 00:20:20,850 --> 00:20:22,290 When I went to exploit this, 422 00:20:22,290 --> 00:20:25,680 I found in the Apache config that actually prevented 423 00:20:25,680 --> 00:20:27,900 any URL with .properties in it. 424 00:20:27,900 --> 00:20:30,270 No doubt in relation to some other vulnerability, 425 00:20:30,270 --> 00:20:33,270 but can be simply bypassed with the semicolon. 426 00:20:33,270 --> 00:20:36,990 So, what you can do once you've read 427 00:20:36,990 --> 00:20:40,990 the cluster admin password is access the tipsapi 428 00:20:41,859 --> 00:20:43,650 and what I'm doing in the top box there 429 00:20:43,650 --> 00:20:45,120 is creating an admin user, 430 00:20:45,120 --> 00:20:47,670 which lets me log into the web interface. 431 00:20:47,670 --> 00:20:49,380 Once I can log into the web interface, 432 00:20:49,380 --> 00:20:53,130 there's a bunch of different ways of uploading files to it. 433 00:20:53,130 --> 00:20:55,170 And they go into a temp directory, 434 00:20:55,170 --> 00:20:57,150 which normally is not a problem, 435 00:20:57,150 --> 00:20:58,770 but because we can set an alias, 436 00:20:58,770 --> 00:21:03,540 we can just alias that temp directory to a reachable URL 437 00:21:03,540 --> 00:21:06,753 and then access our uploaded web shell, giving us code exec. 438 00:21:08,580 --> 00:21:12,600 Signature Check Bypass, I am going to skim over, 439 00:21:12,600 --> 00:21:14,520 because I realized I talked too fast 440 00:21:14,520 --> 00:21:16,110 when I was timing this talk, 441 00:21:16,110 --> 00:21:18,900 but the details are in this slide deck. 442 00:21:18,900 --> 00:21:20,883 So just gonna go over there. 443 00:21:23,910 --> 00:21:25,743 Right, here's the good one. 444 00:21:26,970 --> 00:21:31,020 So ClearPass has a go binary listening on local host, 445 00:21:31,020 --> 00:21:34,983 on port 7,007 and you can reach it via Apache. 446 00:21:35,880 --> 00:21:39,270 And what it does, the go binary does the authentication 447 00:21:39,270 --> 00:21:43,170 and it attempts to access an X-Forwarded-For header 448 00:21:43,170 --> 00:21:48,090 and checks if that is exactly local host, or 127.0.0.1. 449 00:21:48,090 --> 00:21:50,550 If that X-Forwarded-For header doesn't exist, 450 00:21:50,550 --> 00:21:53,370 it falls back to the remote address, 451 00:21:53,370 --> 00:21:54,780 which is always gonna be local host, 452 00:21:54,780 --> 00:21:56,883 because you're talking to it via Apache. 453 00:21:58,890 --> 00:22:01,530 Apache doesn't let us mess with the X-Forwarded-For 454 00:22:01,530 --> 00:22:03,090 local host and the request headers, 455 00:22:03,090 --> 00:22:04,680 it's been explicitly blocked. 456 00:22:04,680 --> 00:22:08,610 And also it would just include, even if I could set it, 457 00:22:08,610 --> 00:22:12,870 Apache would simply add the X-Forwarded-For header I send 458 00:22:12,870 --> 00:22:16,890 to its own one and then it wouldn't exactly match 127.0.0.1. 459 00:22:16,890 --> 00:22:19,770 So what we need is a way of removing headers. 460 00:22:19,770 --> 00:22:21,273 It turns out you can do that. 461 00:22:24,900 --> 00:22:27,120 So there's something called a Hop by Hop Header. 462 00:22:27,120 --> 00:22:29,910 And what that lets you do is tell the server 463 00:22:29,910 --> 00:22:31,675 you're talking to like, "Hey, 464 00:22:31,675 --> 00:22:35,400 this is just between me and you, don't tell it to upstream." 465 00:22:35,400 --> 00:22:40,170 So that it's defined in RRC 2616. 466 00:22:40,170 --> 00:22:43,110 And basically, yeah, it lets you remove headers 467 00:22:43,110 --> 00:22:45,873 from what it's saying. 468 00:22:46,830 --> 00:22:49,590 So an example request and response looks like this. 469 00:22:49,590 --> 00:22:53,005 At the top, you can see it's saying X-Forwarded-For 470 00:22:53,005 --> 00:22:55,250 and then down the bottom, if I add X-Forwarded-For 471 00:22:55,250 --> 00:22:58,290 in the connection header, which is how the Hop by Hop works, 472 00:22:58,290 --> 00:23:00,483 it's actually not forwarded upstream. 473 00:23:01,710 --> 00:23:02,730 As an interesting aside, 474 00:23:02,730 --> 00:23:05,133 I found this vulnerability in September, 2021. 475 00:23:06,154 --> 00:23:09,300 And when I was reproducing the vulnerability for this talk, 476 00:23:09,300 --> 00:23:10,590 I couldn't get it to work. 477 00:23:10,590 --> 00:23:12,270 And I was like, "What's going on here? 478 00:23:12,270 --> 00:23:13,952 This is interesting." 479 00:23:13,952 --> 00:23:16,680 So I Googled for it and, whoops, 480 00:23:16,680 --> 00:23:19,020 turns out there was actually an Apache vulnerability 481 00:23:19,020 --> 00:23:22,470 that I had been accidentally sitting on for several months 482 00:23:22,470 --> 00:23:25,320 and just reported it like a month ago, I think. 483 00:23:25,320 --> 00:23:27,993 Yeah, anyway, it's a patch now, 484 00:23:29,490 --> 00:23:33,900 but now we can reach the go APIs binary, what can we do? 485 00:23:33,900 --> 00:23:38,900 Well, what it supports is letting you pass in 486 00:23:39,330 --> 00:23:42,063 the URL to a ClearPass upgrade file. 487 00:23:42,960 --> 00:23:47,130 And the way ClearPass upgrade files work is when you, 488 00:23:47,130 --> 00:23:49,560 they're basically a tar file and within that tar file, 489 00:23:49,560 --> 00:23:54,420 they have a zip and a signature that sits beside it. 490 00:23:54,420 --> 00:23:58,020 And when you get it to do an upgrade, 491 00:23:58,020 --> 00:23:59,550 it pulls that tar file. 492 00:23:59,550 --> 00:24:02,405 It extracts the contents and then, 493 00:24:02,405 --> 00:24:06,570 if signature doesn't match, it doesn't delete the contents. 494 00:24:06,570 --> 00:24:08,430 It just deletes the outer tar file. 495 00:24:08,430 --> 00:24:11,850 But those things are still sitting extracted on disk. 496 00:24:11,850 --> 00:24:13,830 So there's a few different ways of exploiting this. 497 00:24:13,830 --> 00:24:17,520 And what I ended up going with is doing it twice. 498 00:24:17,520 --> 00:24:20,850 So first of all, you upload a tar file 499 00:24:20,850 --> 00:24:23,700 that just contains a symlink to the guest directory, 500 00:24:23,700 --> 00:24:26,193 which is your writeable web root. 501 00:24:27,480 --> 00:24:30,270 Then it deletes the tar, but leaves that symlink. 502 00:24:30,270 --> 00:24:32,790 And then in the next tar file, 503 00:24:32,790 --> 00:24:37,790 you do this and create a PHP shell that is in a folder 504 00:24:39,060 --> 00:24:40,023 with the same name as the symlink. 505 00:24:40,023 --> 00:24:44,490 And then when the tar extracts it on the second run, 506 00:24:44,490 --> 00:24:47,730 it writes through the symlink and into the web directory. 507 00:24:47,730 --> 00:24:49,290 So you can get an arbitrary file write 508 00:24:49,290 --> 00:24:50,640 in your own disc like that. 509 00:24:52,620 --> 00:24:54,770 That's how the requests look to exploit it. 510 00:24:56,760 --> 00:24:58,743 Right, next target is AirWave. 511 00:25:02,520 --> 00:25:05,820 So AirWave is like a network management system. 512 00:25:05,820 --> 00:25:08,370 It can be a virtual appliance or physical hardware. 513 00:25:09,210 --> 00:25:13,110 It runs a Centos 7 again, Nginx and Apache. 514 00:25:13,110 --> 00:25:15,010 And the main web apps written in Perl. 515 00:25:16,950 --> 00:25:18,990 Here's our goose based attack surface 516 00:25:18,990 --> 00:25:20,540 of what the airwave looks like. 517 00:25:21,660 --> 00:25:25,830 Yeah, so the first bug I'm gonna talk about 518 00:25:25,830 --> 00:25:30,330 is an auth bypass when AirWave is set up 519 00:25:30,330 --> 00:25:33,240 to do auth via RADIUS. 520 00:25:33,240 --> 00:25:36,690 So imagine you're Aruba and you're writing some code 521 00:25:36,690 --> 00:25:39,810 and you say, "How do we determine if the RADIUS 522 00:25:39,810 --> 00:25:42,210 authentication attempt to this AirWave web app 523 00:25:42,210 --> 00:25:43,830 was successful?" 524 00:25:43,830 --> 00:25:46,620 Should we use a reliable Perl library 525 00:25:46,620 --> 00:25:48,840 that supports RADIUS authentication? 526 00:25:48,840 --> 00:25:50,010 No. 527 00:25:50,010 --> 00:25:52,500 Should we just shell out to a binary used 528 00:25:52,500 --> 00:25:55,350 for testing configs and regex the output? 529 00:25:55,350 --> 00:25:56,183 Yes. 530 00:25:57,720 --> 00:26:02,070 So this is the code that's doing part of it. 531 00:26:02,070 --> 00:26:06,090 So it's taking the supplied username and password 532 00:26:06,090 --> 00:26:10,710 and creating a config file for the eapol test binary, 533 00:26:10,710 --> 00:26:14,163 which has the same format as wpa_supplicant. 534 00:26:15,660 --> 00:26:18,600 There's a bit of a reasonably inscrutable Perl 535 00:26:18,600 --> 00:26:22,110 that basically what it's doing is just up sending 536 00:26:22,110 --> 00:26:25,557 that config file to eapol test over standard in, 537 00:26:25,557 --> 00:26:29,640 and then calls the extract eapol output subroutine, 538 00:26:29,640 --> 00:26:31,020 which works like this. 539 00:26:31,020 --> 00:26:35,010 So what that does is basically just re-exes 540 00:26:35,010 --> 00:26:37,440 the output of eapol test and looks for the string 541 00:26:37,440 --> 00:26:40,293 entering state authenticated and then some other stuff, 542 00:26:41,220 --> 00:26:44,613 letting it know what the user's privilege levels are. 543 00:26:45,660 --> 00:26:49,350 So what does the output of eapol test actually look like? 544 00:26:49,350 --> 00:26:52,890 Well, it's a testing binary, so it's quite verbose. 545 00:26:52,890 --> 00:26:55,770 And it looks like this, and crucially, 546 00:26:55,770 --> 00:26:58,110 the username is output, 547 00:26:58,110 --> 00:26:59,970 regardless of whether the authentication 548 00:26:59,970 --> 00:27:01,920 was successful, or not. 549 00:27:01,920 --> 00:27:03,930 So because it's just re-exing 550 00:27:03,930 --> 00:27:05,880 for entering state authenticated. 551 00:27:05,880 --> 00:27:07,770 What we can do is say, "Hello. 552 00:27:07,770 --> 00:27:11,340 Yes, my username is entering state AUTHENTICATED." 553 00:27:11,340 --> 00:27:14,463 set any password and get logged in as that user. 554 00:27:17,010 --> 00:27:18,360 Interestingly, I found some comments 555 00:27:18,360 --> 00:27:20,940 where the devs were very close to finding this bug, 556 00:27:20,940 --> 00:27:22,383 but not quite. 557 00:27:23,430 --> 00:27:26,160 So that's an auth bypass and that's all well and good, 558 00:27:26,160 --> 00:27:28,980 but we wanna shell as well. 559 00:27:28,980 --> 00:27:30,720 This is some interesting code. 560 00:27:30,720 --> 00:27:32,470 Let's go back and look at it again. 561 00:27:33,750 --> 00:27:37,320 So it does escape the quotes, double quotes, 562 00:27:37,320 --> 00:27:41,490 so you can escape out of the username or can you? 563 00:27:41,490 --> 00:27:45,873 It turns out that's not the only way of escaping, 564 00:27:45,873 --> 00:27:49,410 of getting out of a config line on eapol test. 565 00:27:49,410 --> 00:27:51,570 You can also inject new lines, 566 00:27:51,570 --> 00:27:55,440 so what that lets you do is inject a new line 567 00:27:55,440 --> 00:27:58,020 and then you can put arbitrary config lines 568 00:27:58,020 --> 00:27:59,433 into this config file. 569 00:28:01,080 --> 00:28:04,560 And given it has the same format as wpa_supplicant 570 00:28:04,560 --> 00:28:06,720 I looked through it and found that it supports 571 00:28:06,720 --> 00:28:10,263 open SSL engines via the pkcs11 engine path. 572 00:28:11,970 --> 00:28:15,510 That is accepted by most common open SSL commands, 573 00:28:15,510 --> 00:28:18,480 and the engine is basically a shared library 574 00:28:18,480 --> 00:28:21,720 that is loaded and executed when run. 575 00:28:21,720 --> 00:28:25,590 So you can inject a config line that looks like this 576 00:28:25,590 --> 00:28:29,763 and set pkcs11 engine path to a file on disc. 577 00:28:31,320 --> 00:28:33,180 The config ends up looking like that 578 00:28:33,180 --> 00:28:35,470 after you've done the new line injection 579 00:28:36,600 --> 00:28:38,970 and that's how you can use it to get code execution. 580 00:28:38,970 --> 00:28:41,970 So simply upload your engine file onto disc, 581 00:28:41,970 --> 00:28:44,550 after you've exploited the auth bypass 582 00:28:44,550 --> 00:28:46,170 and then run that command, 583 00:28:46,170 --> 00:28:48,420 and it will load and run your arbitrary code. 584 00:28:49,590 --> 00:28:52,037 Right, Perl Deserialisation. 585 00:28:54,510 --> 00:28:58,800 So some endpoints in AirWave deserialise Perl objects, 586 00:28:58,800 --> 00:28:59,730 which is quite interesting. 587 00:28:59,730 --> 00:29:02,193 And they're signed with a per-install secret, 588 00:29:03,510 --> 00:29:06,960 and I didn't really come across Perl deserialisation before, 589 00:29:06,960 --> 00:29:10,410 but it's using a library called Storable. 590 00:29:10,410 --> 00:29:11,880 And when I looked into it, 591 00:29:11,880 --> 00:29:14,283 there's only a few good resources on it. 592 00:29:15,240 --> 00:29:17,310 So I read those and none of them really answered 593 00:29:17,310 --> 00:29:20,760 the question I had of how do I exploit this? 594 00:29:20,760 --> 00:29:23,163 Reading the docs it's specifically notes, 595 00:29:24,000 --> 00:29:26,520 deserialisation if you see it eval to one, 596 00:29:26,520 --> 00:29:28,020 deserialisation is done via eval, 597 00:29:28,020 --> 00:29:30,930 which is dangerous and do not accept Storable docs 598 00:29:30,930 --> 00:29:32,403 from untrusted sources. 599 00:29:34,620 --> 00:29:38,520 This is the Perl code that does the deserialisation. 600 00:29:38,520 --> 00:29:43,520 So it checks the signature and then it deserialises 601 00:29:43,590 --> 00:29:46,770 the object after first setting Storable:Eval to one. 602 00:29:46,770 --> 00:29:47,603 So I thought, "Great, 603 00:29:47,603 --> 00:29:49,320 this should be pretty easy to exploit." 604 00:29:49,320 --> 00:29:51,555 I know how deserialisation bugs work. 605 00:29:51,555 --> 00:29:56,250 You look for things like, for example, in PHP, 606 00:29:56,250 --> 00:29:58,020 you have magic methods. 607 00:29:58,020 --> 00:30:00,840 And basically they're like things that get automatically run 608 00:30:00,840 --> 00:30:04,200 at certain stages in an object's life cycle. 609 00:30:04,200 --> 00:30:06,540 So that in Perl DESTROY is run 610 00:30:06,540 --> 00:30:09,990 when a runtime object is destroyed and I found this file, 611 00:30:09,990 --> 00:30:14,460 HTTP.pm that basically checks if an array key exists. 612 00:30:14,460 --> 00:30:16,233 And if it exists, it calls it. 613 00:30:17,910 --> 00:30:19,500 And that has to be a code ref though, 614 00:30:19,500 --> 00:30:21,633 which is a sub-routine in Perl. 615 00:30:22,800 --> 00:30:25,590 So this is how you construct an exploit for it. 616 00:30:25,590 --> 00:30:30,590 I've just put a basic sleep command in there and freeze it, 617 00:30:32,250 --> 00:30:34,920 sign it with the salt, which you can, 618 00:30:34,920 --> 00:30:37,440 you have to exploit another bug to get the salt, 619 00:30:37,440 --> 00:30:42,440 but there's a zero and then send it the base_64 objects 620 00:30:42,450 --> 00:30:43,600 and you get your sleep. 621 00:30:44,490 --> 00:30:49,020 So the deserial layers works great, so I sent that to them 622 00:30:49,020 --> 00:30:51,150 then they fixed it poorly and then I bypassed the fix. 623 00:30:51,150 --> 00:30:54,270 And then they didn't fix it very well again. 624 00:30:54,270 --> 00:30:56,940 And now, I dunno, it might be fixed. 625 00:30:56,940 --> 00:30:58,890 They stopped paying for bugs in this product, 626 00:30:58,890 --> 00:30:59,940 so I stopped looking. 627 00:31:02,280 --> 00:31:04,440 Anyway, later on, I was looking at the docs again 628 00:31:04,440 --> 00:31:06,657 and it said it's done by eval. 629 00:31:06,657 --> 00:31:10,380 And I thought, "Do I really need to call a destructor?" 630 00:31:10,380 --> 00:31:12,060 That doesn't sound like how it works. 631 00:31:12,060 --> 00:31:14,940 So it turns out it is actually just Evalling it. 632 00:31:14,940 --> 00:31:16,590 And what you can do is just go and X-edit 633 00:31:16,590 --> 00:31:21,590 it your Perl, frozen Perl object and put arbitrary code in. 634 00:31:22,620 --> 00:31:25,920 And then when you thaw that with eval on, it just gets run. 635 00:31:25,920 --> 00:31:28,590 So you don't actually have to go down that destructive path 636 00:31:28,590 --> 00:31:30,363 unless eval's not set. 637 00:31:33,450 --> 00:31:35,910 Okay, last one, Glass. 638 00:31:35,910 --> 00:31:38,640 So Glass is like a single pane of glass, 639 00:31:38,640 --> 00:31:42,333 I assume is why it's called Glass, collates AirWave data. 640 00:31:43,680 --> 00:31:45,900 It's Kubernetes and it used to be CoreOS 641 00:31:45,900 --> 00:31:47,343 and now it's Ubuntu. 642 00:31:48,506 --> 00:31:49,467 It has a lot of microservices 643 00:31:49,467 --> 00:31:51,480 and some very hefty memory requirements. 644 00:31:51,480 --> 00:31:53,370 It wanted 96 gigabytes of Ram, 645 00:31:53,370 --> 00:31:55,560 which was a bit much my poor old laptop, 646 00:31:55,560 --> 00:31:58,560 but I managed to buy it down to 24 and get it running. 647 00:31:58,560 --> 00:32:00,543 The web interface just looks like that. 648 00:32:01,620 --> 00:32:03,450 Here's the goose based attack surface. 649 00:32:03,450 --> 00:32:06,510 So there's a lot of stuff going on in there, 650 00:32:06,510 --> 00:32:10,110 like Grafana, ElasticSearch. 651 00:32:10,110 --> 00:32:12,660 That's obviously why it needs so much Ram, 652 00:32:12,660 --> 00:32:14,860 there's a lot of pods running on this thing. 653 00:32:15,780 --> 00:32:19,230 So first thing I did is look at the nginx config, 654 00:32:19,230 --> 00:32:22,440 and there's quite a few and that's just proxy and requests 655 00:32:22,440 --> 00:32:24,690 to all these different pods. 656 00:32:24,690 --> 00:32:28,050 So I thought, "Okay, I'll try and find exploits 657 00:32:28,050 --> 00:32:29,550 via the web interface." 658 00:32:29,550 --> 00:32:31,920 So I log into the web interface. 659 00:32:31,920 --> 00:32:35,550 Literally the first thing I try has a command injection 660 00:32:35,550 --> 00:32:40,550 in it, so that is pretty, I got a bad sense when I saw that. 661 00:32:43,230 --> 00:32:46,080 Anyway, that's a post auth issue. 662 00:32:46,080 --> 00:32:48,060 But it turns out that you see the Glass 663 00:32:48,060 --> 00:32:49,830 at the start of the URL turns out 664 00:32:49,830 --> 00:32:52,500 that's actually just an authentication layer. 665 00:32:52,500 --> 00:32:55,110 And then that proxies the request further on 666 00:32:55,110 --> 00:32:56,493 to a different pod. 667 00:32:58,320 --> 00:33:01,920 That pod is actually also directly reachable via nginx. 668 00:33:01,920 --> 00:33:04,080 So you can simply change the URL 669 00:33:04,080 --> 00:33:08,250 and turn it into a pre-auth bug, which is good. 670 00:33:08,250 --> 00:33:11,220 So we have code executives root in a pod, 671 00:33:11,220 --> 00:33:13,410 but I kind of wanna escape the pod. 672 00:33:13,410 --> 00:33:15,420 So if you have a look at the mounts, 673 00:33:15,420 --> 00:33:17,430 there's a lot of rewrite mounts, 674 00:33:17,430 --> 00:33:20,223 and these are running as privileged as well. 675 00:33:21,930 --> 00:33:25,980 So the one I ended up exploiting was the etc/systemd Mount. 676 00:33:25,980 --> 00:33:27,870 And what you can do there is actually, 677 00:33:27,870 --> 00:33:31,800 because that's maps in the system D directory from the node, 678 00:33:34,230 --> 00:33:37,530 just create a system D service and start it 679 00:33:37,530 --> 00:33:39,510 from inside the pod and you get escaped 680 00:33:39,510 --> 00:33:43,260 from the container you're in, and a full cluster compromise 681 00:33:43,260 --> 00:33:44,463 from a pre auth bug. 682 00:33:48,930 --> 00:33:51,810 So for authentication it uses the thing called 683 00:33:51,810 --> 00:33:53,913 CAS, aperio CAS. 684 00:33:54,750 --> 00:33:57,420 Originally it was running 4.14, 685 00:33:57,420 --> 00:33:59,850 and there was a known exploit in there, 686 00:33:59,850 --> 00:34:03,453 which was a deserialisation, so I exploited that. 687 00:34:04,320 --> 00:34:06,720 At the time, there was no public proof of concepts, 688 00:34:06,720 --> 00:34:09,000 but there is now, which I've linked there. 689 00:34:09,000 --> 00:34:11,913 Since they're public, I just skip over that. 690 00:34:13,500 --> 00:34:17,190 Then they updated it after I submitted it to 4.17. 691 00:34:17,190 --> 00:34:19,680 So fixed according to the vendor. 692 00:34:19,680 --> 00:34:24,680 And it changes how it's the deserialise objects 693 00:34:25,050 --> 00:34:30,050 is encrypted and they also removed the Apache commons jars. 694 00:34:30,540 --> 00:34:32,850 So I couldn't use those for gadget chains anymore, 695 00:34:32,850 --> 00:34:34,500 but looking at the vendor fix, 696 00:34:34,500 --> 00:34:38,580 they specifically highlight if you are using the default 697 00:34:38,580 --> 00:34:40,500 encryption keys, which they were, 698 00:34:40,500 --> 00:34:42,210 and you have not generated new keys, 699 00:34:42,210 --> 00:34:45,120 you must take action to regenerate the keys. 700 00:34:45,120 --> 00:34:47,820 Do you think they degenerated the keys? 701 00:34:47,820 --> 00:34:50,283 No, they did not, they kept those keys. 702 00:34:51,270 --> 00:34:54,390 So what that means is we can just still sign 703 00:34:54,390 --> 00:34:59,390 arbitrary Java objects using this code here. 704 00:34:59,850 --> 00:35:01,470 If you wanna do that yourself 705 00:35:01,470 --> 00:35:04,650 and are there more deserialisation gadgets? 706 00:35:04,650 --> 00:35:07,320 Yes, there are, so I played a bit of gadget whack-a-mole 707 00:35:07,320 --> 00:35:10,890 where I'd submit them a bug and then they'd fix that, 708 00:35:10,890 --> 00:35:14,460 but not change the keys like I suggested. 709 00:35:14,460 --> 00:35:16,680 And then I'd find another gadget 710 00:35:16,680 --> 00:35:19,890 and eventually they fixed this so that the keys 711 00:35:19,890 --> 00:35:21,843 are randomly generated on boot. 712 00:35:22,830 --> 00:35:26,043 Right, just have a quick demo, Alt tab. 713 00:35:28,200 --> 00:35:30,333 Okay, I have to find it. 714 00:35:38,610 --> 00:35:40,923 Okay. Yep. 715 00:35:43,320 --> 00:35:46,080 So what I'm doing here is just gonna exploit 716 00:35:46,080 --> 00:35:48,690 a few of these vulnerability as I've just talked about, 717 00:35:48,690 --> 00:35:51,360 but it's nice to see them in action. 718 00:35:51,360 --> 00:35:54,000 So this is the Nmap argument injection. 719 00:35:54,000 --> 00:35:56,913 Hopefully that's that font size is readable. 720 00:35:57,870 --> 00:35:59,850 So I just kick it off scanning my host, 721 00:35:59,850 --> 00:36:03,944 which is hosting the n6.nse, which is the lower script, 722 00:36:03,944 --> 00:36:08,790 which I'm going get the clear paths to pull in and run. 723 00:36:08,790 --> 00:36:13,110 Just takes a second, should see the Nmap coming soon. 724 00:36:13,110 --> 00:36:13,943 There we are. 725 00:36:15,030 --> 00:36:20,030 So now that n6.nse shows lower script is sitting on disk, 726 00:36:20,130 --> 00:36:22,440 on the ClearPass, so then we execute 727 00:36:22,440 --> 00:36:24,270 the second argument injection, 728 00:36:24,270 --> 00:36:26,190 which just runs it as a script. 729 00:36:26,190 --> 00:36:29,070 And that's gonna send us a reverse shell, 730 00:36:29,070 --> 00:36:33,043 which should come in now, there we go. 731 00:36:33,900 --> 00:36:36,643 That's the first pre auth, right? 732 00:36:47,460 --> 00:36:52,050 This one is the AirWave username regex issue. 733 00:36:52,050 --> 00:36:54,903 Where if I try to log in with just an invalid user 734 00:36:54,903 --> 00:36:56,460 that that's not gonna work, 735 00:36:56,460 --> 00:36:58,740 but if I paste in that entering state authenticated 736 00:36:58,740 --> 00:37:02,523 username, it logs us in. 737 00:37:04,020 --> 00:37:08,340 Then I'm gonna go and exploit the open SSL engine issue. 738 00:37:08,340 --> 00:37:10,920 So I specifically pick this firmware type, 739 00:37:10,920 --> 00:37:13,110 because it doesn't validate anything in it. 740 00:37:13,110 --> 00:37:14,880 And I can just upload that engine, 741 00:37:14,880 --> 00:37:17,163 the open SSL engine file on disk. 742 00:37:26,250 --> 00:37:28,200 That's how you construct it by the way. 743 00:37:33,750 --> 00:37:38,260 So now that's uploaded to disk and then I'm gonna go and 744 00:37:39,420 --> 00:37:43,320 exploit it with that eapol config, 745 00:37:43,320 --> 00:37:48,213 a new line injection and get the shell to come in, now. 746 00:37:57,660 --> 00:38:01,320 Okay, this is the glass command injection issue. 747 00:38:01,320 --> 00:38:02,850 So we're gonna get this, 748 00:38:02,850 --> 00:38:05,970 we're gonna do it backwards and get the systemd 749 00:38:05,970 --> 00:38:09,240 pod breakout file and just by 64 it, 750 00:38:09,240 --> 00:38:11,794 because that's an easy way of transferring a file 751 00:38:11,794 --> 00:38:16,470 in a command injection and write that onto, 752 00:38:16,470 --> 00:38:20,220 on disk inside the pod via the command injection. 753 00:38:20,220 --> 00:38:23,790 And that's run, get our endcap listing. 754 00:38:23,790 --> 00:38:27,510 Then we're gonna restart system D so I can see that file. 755 00:38:27,510 --> 00:38:29,710 And then we are just gonna start the service 756 00:38:31,620 --> 00:38:33,390 and the shelves come in. 757 00:38:33,390 --> 00:38:37,563 And that's a full root on the Glass cluster. 758 00:38:41,040 --> 00:38:43,026 Yeah, you can see there's a lot of containers right now. 759 00:38:43,026 --> 00:38:44,576 (audience clapping) Thank you. 760 00:38:51,270 --> 00:38:54,363 Right. One second. 761 00:38:57,900 --> 00:39:01,953 Okay, so getting started, where are we? 762 00:39:04,440 --> 00:39:06,090 Okay, I have to use this. 763 00:39:07,800 --> 00:39:08,850 Getting started yourself. 764 00:39:08,850 --> 00:39:10,680 So I showed you how to get research access 765 00:39:10,680 --> 00:39:14,253 to the virtual appliances via just mounting a live CD, 766 00:39:15,150 --> 00:39:17,430 but how you get access to the hardware APs. 767 00:39:17,430 --> 00:39:20,460 Well, if you don't wanna find an exploit, 768 00:39:20,460 --> 00:39:21,390 let's have a look at that. 769 00:39:21,390 --> 00:39:26,390 So ArubaOS has a support command and it specifically says, 770 00:39:27,127 --> 00:39:29,340 "Do not use this command without the guidance 771 00:39:29,340 --> 00:39:30,990 of Aruba customer support." 772 00:39:30,990 --> 00:39:34,290 Yeah, but we're hackers, so I'm gonna run it anywhere. 773 00:39:34,290 --> 00:39:38,640 And it ask me for a username and then it prints out a token 774 00:39:38,640 --> 00:39:40,380 and gives me a URL. 775 00:39:40,380 --> 00:39:42,690 So, okay, we'll just go to that URL. 776 00:39:42,690 --> 00:39:45,900 It says this tool is specifically restricted to tech. 777 00:39:45,900 --> 00:39:48,810 So, well, we'll just try to code it anyway. 778 00:39:48,810 --> 00:39:51,000 No, not authorized to do that. 779 00:39:51,000 --> 00:39:53,360 Okay, gotta bust out the decompiler. 780 00:39:54,350 --> 00:39:56,640 So it turns out what it's doing is it's actually 781 00:39:56,640 --> 00:39:58,440 using Elliptic Curve Diffie Hellman, 782 00:39:59,512 --> 00:40:03,360 which gives you key agreement over an untrusted channel. 783 00:40:03,360 --> 00:40:08,360 So I initially reversed this support binary with getra 784 00:40:08,640 --> 00:40:12,360 and which took me some time because it was a little tricky. 785 00:40:12,360 --> 00:40:15,030 And then turns out that source code 786 00:40:15,030 --> 00:40:17,820 was just on the GPL release on Github. 787 00:40:17,820 --> 00:40:21,720 So I guess the lesson there is try Googling first, 788 00:40:21,720 --> 00:40:23,930 before you spend hours on a decompiler. 789 00:40:25,535 --> 00:40:26,703 So the Elliptic Curve they're using is custom, 790 00:40:29,970 --> 00:40:32,580 they've got their own Elliptic Curve. 791 00:40:32,580 --> 00:40:37,580 Those are the fields, and they have a fixed public key 792 00:40:38,130 --> 00:40:41,220 for Aruba support that's compiled into the support binary. 793 00:40:41,220 --> 00:40:42,600 So what's actually happening 794 00:40:42,600 --> 00:40:44,010 when you run that support command, 795 00:40:44,010 --> 00:40:47,280 is it generates you a public private key here 796 00:40:47,280 --> 00:40:49,200 on the hardware AP you're running. 797 00:40:49,200 --> 00:40:51,480 And then that token is actually the X coordinate 798 00:40:51,480 --> 00:40:54,630 of your public key that it's just generated. 799 00:40:54,630 --> 00:40:57,120 So you give that to the support command. 800 00:40:57,120 --> 00:40:59,160 And then what it does is calculate 801 00:40:59,160 --> 00:41:02,550 the Elliptic Curve Diffie Hellman shared secret, 802 00:41:02,550 --> 00:41:05,640 and it then uses that to derive the support password 803 00:41:05,640 --> 00:41:10,080 by doing a bit of HMAC and that sort of thing. 804 00:41:10,080 --> 00:41:12,150 So that's pretty cool. 805 00:41:12,150 --> 00:41:14,370 That's a lot better than some hard coded 806 00:41:14,370 --> 00:41:17,820 static super user string like I have seen 807 00:41:17,820 --> 00:41:19,590 in some other vendors, 808 00:41:19,590 --> 00:41:23,550 but Let's look a little bit closer at that. 809 00:41:23,550 --> 00:41:27,204 The comments say it's a 64 bit elliptic curve. 810 00:41:27,204 --> 00:41:30,363 Elliptic Curves are small, but they're not that small. 811 00:41:31,650 --> 00:41:32,970 And there's also some comments 812 00:41:32,970 --> 00:41:34,890 about skipping list validation, 813 00:41:34,890 --> 00:41:38,103 which certainly piqued my interest somewhat. 814 00:41:39,240 --> 00:41:41,220 Turns out you can crack that key. 815 00:41:41,220 --> 00:41:45,573 So a 64 bit elliptic curve roughly has 32 bits of security. 816 00:41:46,719 --> 00:41:49,590 That's well within range of a desktop computer, 817 00:41:49,590 --> 00:41:52,140 how within range with a good implementation 818 00:41:52,140 --> 00:41:54,900 about, on my desktop, 200 seconds. 819 00:41:54,900 --> 00:41:56,820 So if we pace those constants in 820 00:41:56,820 --> 00:42:00,960 and break the Aruba support, it's public key, 821 00:42:00,960 --> 00:42:02,253 takes about two minutes. 822 00:42:04,860 --> 00:42:06,150 So that's pretty cool. 823 00:42:06,150 --> 00:42:08,193 It's fast, but is that fast enough? 824 00:42:09,060 --> 00:42:13,950 Turns out with the discreet algorithm problem, 825 00:42:13,950 --> 00:42:16,800 you can solve it much quicker when the order of the curve 826 00:42:16,800 --> 00:42:20,097 can be factored using, and you do this via 827 00:42:20,097 --> 00:42:23,160 the Pohlig-Hellman algorithm, 828 00:42:23,160 --> 00:42:25,300 and then it kind of makes the complexity 829 00:42:27,000 --> 00:42:29,820 basically the largest prime factor 830 00:42:29,820 --> 00:42:32,490 of the order of the curve. 831 00:42:32,490 --> 00:42:34,590 So it's quite common for elliptic curves 832 00:42:34,590 --> 00:42:37,050 to use prime orders to prevent this. 833 00:42:37,050 --> 00:42:39,480 Did Aruba use a prime order for their curve? 834 00:42:39,480 --> 00:42:41,370 No, they did not, can be factored. 835 00:42:41,370 --> 00:42:43,563 So the largest factor is only 40 bits. 836 00:42:44,880 --> 00:42:47,730 So then we can break it in six seconds. 837 00:42:47,730 --> 00:42:49,130 And there's the private key. 838 00:42:50,640 --> 00:42:54,390 So what that buys you is the ability to implement 839 00:42:54,390 --> 00:42:57,780 the response for the challenge, response script, 840 00:42:57,780 --> 00:43:00,570 and get support access to the device, 841 00:43:00,570 --> 00:43:03,333 which gives you a full shell on the device. 842 00:43:05,310 --> 00:43:06,990 There's a script for doing it, also available 843 00:43:06,990 --> 00:43:09,510 on the media server and I'll make it public. 844 00:43:09,510 --> 00:43:12,000 So you can then now get research access 845 00:43:12,000 --> 00:43:14,313 to your own Aruba APS and a full root show. 846 00:43:15,240 --> 00:43:17,507 End of presentation, thank you. 847 00:43:17,507 --> 00:43:20,507 (audience clapping)