[00:05.350 --> 00:09.510] Okay, don't ruckus again, take one million. [00:11.210 --> 00:14.610] Hi everyone, and thank you for watching my talk [00:15.110 --> 00:17.550] and thanks DEF CON for inviting me [00:17.550 --> 00:20.290] and not giving up on this year con. [00:20.510 --> 00:22.690] This is the first time I speak on DEF CON [00:22.690 --> 00:26.310] and I could really use a welcome round shot, [00:26.310 --> 00:28.230] but since I'm not in Vegas, [00:28.230 --> 00:31.550] well, I think I'm gonna save it for another time. [00:33.670 --> 00:36.990] This talk will present my recent research [00:36.990 --> 00:39.510] on Ruckus Wireless. [00:39.510 --> 00:44.610] Ruckus is a wireless solution company owned by Comscope. [00:44.610 --> 00:46.550] I've come to realize that Ruckus [00:46.550 --> 00:49.230] is pretty popular in the States. [00:49.230 --> 00:51.290] They even partnered with Black Hat [00:51.290 --> 00:54.210] for conference Wi-Fi solution. [00:54.410 --> 00:58.330] Actually, this is how I first noticed them. [00:58.330 --> 01:01.510] In the last year, I've been doing vulnerability research [01:01.510 --> 01:03.990] on Ruckus access points, [01:03.990 --> 01:07.470] and so far I managed to find several critical vulnerabilities [01:08.070 --> 01:09.990] in many of these devices. [01:11.070 --> 01:13.770] My previous research was introduced [01:13.770 --> 01:16.430] in the recent CCC convention, [01:16.430 --> 01:19.850] back when traveling places was a real thing. [01:21.130 --> 01:22.330] But before I begin, [01:22.330 --> 01:25.970] I would like to go over the obligatory who am I part. [01:25.970 --> 01:27.670] So my name is Galt Swar. [01:28.010 --> 01:31.210] I'm a research team leader at Aleph Research [01:31.210 --> 01:33.770] by HCL AppScan. [01:34.130 --> 01:36.830] I'm recording this talk from our lovely office [01:36.830 --> 01:39.410] in Herzliya, Israel. [01:39.510 --> 01:43.750] And I've been doing reversing for more than a decade. [01:43.750 --> 01:48.030] I try to focus on offensive embedded devices research. [01:49.250 --> 01:53.350] All right, I would like to begin with a quick recap. [01:53.350 --> 01:54.830] In my previous research, [01:54.830 --> 01:57.670] I demonstrated three ways to run code [01:57.670 --> 02:02.090] on Ruckus unleashed and zone director devices. [02:02.090 --> 02:05.920] All vulnerability were found on the device web interface. [02:07.010 --> 02:14.270] My first RCE was credential leakage with SSH jailbreak. [02:14.390 --> 02:19.750] My second RCE was unauthenticated stack buffer overflow. [02:20.710 --> 02:25.250] And the last RCE was command injection vulnerability, [02:25.250 --> 02:27.310] which was reachable without authentication [02:27.310 --> 02:29.590] by writing a new page. [02:33.230 --> 02:37.090] In this talk, same as in my previous one, [02:37.090 --> 02:42.090] I will be using Ruckus R510 unleashed. [02:42.110 --> 02:44.250] Ruckus has an unleashed version [02:44.250 --> 02:47.190] for every access point they provide. [02:47.190 --> 02:52.450] Unleashed access points don't rely on Wi-Fi controllers. [02:53.030 --> 02:57.270] Well, all access point in the list you can see here [02:57.270 --> 03:00.030] share the same vulnerable code base. [03:00.230 --> 03:02.550] And I also noticed that some vulnerabilities [03:02.550 --> 03:05.950] works on zone director product line, [03:05.950 --> 03:08.530] which is the Wi-Fi controllers. [03:10.550 --> 03:12.310] Okay, so what's new? [03:12.310 --> 03:16.870] Well, this research began right after I got Ruckus patch [03:16.870 --> 03:18.930] for my first research. [03:19.230 --> 03:24.230] I noticed that they did not fix my vulnerability correctly. [03:24.230 --> 03:27.270] So I decided to try and re-enable it. [03:27.930 --> 03:31.850] Besides that, my first research was 100% [03:31.850 --> 03:34.530] based on device emulation. [03:34.670 --> 03:36.950] Now that I bought an actual device, [03:36.950 --> 03:39.190] I can try to see if I missed something [03:40.110 --> 03:42.090] that I couldn't emulate. [03:43.250 --> 03:45.990] Well, but before I begin with the new vulnerabilities, [03:45.990 --> 03:49.030] I would like to talk about a new Jidra script [03:49.030 --> 03:51.910] that I used for this research. [03:54.630 --> 03:59.130] My previous research and this one was done relatively fast. [03:59.130 --> 04:00.970] Thanks to a Jidra script, [04:00.970 --> 04:05.670] I wrote that fetches function name from log strings [04:05.670 --> 04:08.430] Ruckus has left in their binaries. [04:08.430 --> 04:13.010] Here you can see some of them from one of the binaries. [04:14.990 --> 04:17.850] This script helped me rename function [04:17.850 --> 04:22.830] by parsing these log lines that contained the function name. [04:22.830 --> 04:24.690] For more information about the script [04:24.690 --> 04:27.430] and its generic version, [04:27.430 --> 04:31.950] please check my previous talk or our GitHub. [04:32.390 --> 04:34.810] All in all, this script was super useful [04:34.810 --> 04:40.490] for binary compiled with Ruckus code, [04:40.490 --> 04:43.520] but not all binaries were like that. [04:46.160 --> 04:48.870] It's a common thing for embedded devices vendor [04:48.870 --> 04:53.170] to use open source project in their devices. [04:53.350 --> 04:56.000] Ruckus web server is a good example for that. [04:57.610 --> 05:01.110] Ruckus added new functionality by adding code [05:01.110 --> 05:05.150] to a popular web server called Embed This. [05:06.250 --> 05:09.670] Since Embed This sources are public, [05:09.670 --> 05:13.930] I didn't really need to reverse the entire web server binary. [05:13.930 --> 05:17.570] It was easier for me just to review the source code. [05:18.750 --> 05:21.850] But what about the parts that Ruckus added? [05:21.850 --> 05:25.530] I would like to be able to mark these parts in JITRA, [05:25.530 --> 05:27.970] so I'll know I'll have to reverse them. [05:28.530 --> 05:31.830] So for this, I wrote an additional JITRA script. [05:34.090 --> 05:37.810] My new script tries to extract as many function names [05:37.810 --> 05:41.170] as it can from the Embed This sources. [05:41.600 --> 05:45.270] I use different methods to extract this information, [05:45.270 --> 05:50.030] things like string matching and function call trace. [05:50.510 --> 05:52.270] But the thing that helped me the most [05:52.270 --> 05:57.830] were debugging functions that contain the exact C filename [05:57.830 --> 06:02.150] and line number in the Embed This sources. [06:03.080 --> 06:06.470] Here we can see that for this unnamed function [06:06.470 --> 06:09.550] from the web server binary, [06:09.550 --> 06:15.110] we get that this function appears in server.c file [06:15.110 --> 06:18.830] around the line number 138. [06:20.770 --> 06:25.050] So if we go to this line in the Embed This sources, [06:25.050 --> 06:27.590] we'll be able to extract many function names [06:27.590 --> 06:29.150] from the sources. [06:29.990 --> 06:34.470] This is the function in JITRA after conversion. [06:37.540 --> 06:41.120] These are all function name that I was able to extract [06:41.120 --> 06:44.040] from the source code to JITRA. [06:46.380 --> 06:51.240] Okay, so let's take this function coin graph, for example. [06:51.360 --> 06:56.440] This function is called macreateWebServer, [06:56.440 --> 07:00.140] and it's being called from the main. [07:00.300 --> 07:03.180] And it also calls other functions. [07:04.100 --> 07:06.800] Well, on the right-hand side, [07:06.800 --> 07:09.340] we can see that all of the function names [07:09.340 --> 07:12.320] I was able to fetch from the sources [07:12.320 --> 07:15.440] by using the script I just introduced. [07:17.320 --> 07:19.620] On the bottom left-hand side, [07:19.620 --> 07:22.740] we can see the function names I was able to fetch [07:22.740 --> 07:26.340] by using the script from my previous research, [07:26.340 --> 07:30.080] the one that uses the log strings. [07:30.980 --> 07:34.700] And as you can see, there are still unnamed function left, [07:34.700 --> 07:38.240] but still the majority of functions are now named. [07:38.580 --> 07:40.520] So this is an excellent example [07:40.520 --> 07:44.220] of how these two scripts help me retrieve [07:44.220 --> 07:47.400] plenty of information and save me so much time [07:47.400 --> 07:50.040] and effort on reversing. [07:53.670 --> 07:56.850] I'm also in the progress of writing a generic version [07:56.850 --> 08:00.590] for this script that won't rely [08:00.590 --> 08:03.150] on specific debug information. [08:03.390 --> 08:05.070] I will share all of my script [08:05.070 --> 08:07.890] in our Aleph Research GitHub account, [08:07.890 --> 08:11.450] so feel free to check it out. [08:11.450 --> 08:12.690] And while you're there, [08:12.690 --> 08:17.050] you can also check other tools that we got there. [08:18.690 --> 08:20.270] All right, cool. [08:20.270 --> 08:22.630] So now we're ready for some exploits. [08:22.630 --> 08:24.670] This is my first RCE. [08:24.670 --> 08:29.130] In this attack, I found another stack overflow [08:30.330 --> 08:35.150] that was reachable with unauthenticated web request. [08:37.730 --> 08:40.470] And I would like to start with a demo. [08:40.470 --> 08:43.730] Well, this is clearly not a live demo, [08:43.730 --> 08:48.990] but I will still try to do it in a live demo style. [08:49.190 --> 08:54.410] So yeah, let's see how it goes. [08:55.490 --> 09:02.490] Okay, so for that, I need my demo screen [09:05.190 --> 09:07.150] and my listener screen. [09:09.070 --> 09:11.950] Okay, so this is the terminal [09:11.950 --> 09:19.090] that I'm gonna listen to port 1337. [09:19.190 --> 09:24.090] And my exploit will create reverse shell to this port. [09:25.090 --> 09:29.010] Let's just start listening. [09:29.870 --> 09:35.050] And now, okay. [09:35.870 --> 09:44.290] And now let's have a look on my stack overflow. [09:44.450 --> 09:46.810] So this is my overflow. [09:46.810 --> 09:50.850] Wait, let me open it in a different way. [09:50.850 --> 09:54.070] Okay, so this is my overflow, as you can see here. [09:54.770 --> 10:03.210] And I am creating this reverse shell by using Netcat. [10:03.530 --> 10:08.050] And let's just go ahead and send this. [10:08.050 --> 10:15.070] So I will be posting this file to this address. [10:17.410 --> 10:22.170] And okay, hopefully everything will work. [10:22.170 --> 10:26.570] Connection refused, it's a good indication. [10:26.570 --> 10:29.320] Let's see what's going on with my listener. [10:30.190 --> 10:33.840] Okay, so connection received, looking good. [10:34.700 --> 10:39.250] As you can see, I managed to run ls [10:39.780 --> 10:45.460] and my user is admin. [10:45.830 --> 10:52.150] And this user is part of the root group. [10:52.850 --> 10:54.670] Yeah, so this is it. [10:54.670 --> 10:58.890] This is my demo. [11:06.200 --> 11:09.360] Okay, before I get into the vulnerability, [11:09.360 --> 11:13.560] I would like to do a quick recap on my previous talk. [11:13.760 --> 11:17.340] This slide and the next one were actually taken [11:17.340 --> 11:20.480] from my previous talk, but I'll go over them [11:20.480 --> 11:22.660] just to create the right context. [11:23.290 --> 11:28.440] There are three important binaries in the web interface. [11:28.440 --> 11:32.200] The first one is slash bin slash webs. [11:32.200 --> 11:35.860] This is the actual embeddice web server. [11:35.860 --> 11:40.140] It handles HTTP requests and executes handlers [11:40.140 --> 11:42.090] according to its configuration. [11:42.680 --> 11:46.020] It then sends commands through a Unix domain socket [11:46.020 --> 11:48.150] to emfd. [11:48.740 --> 11:52.100] Slash bin slash emfd is an executable [11:52.100 --> 11:55.060] that contains the web interface logic. [11:55.060 --> 12:00.280] It maps function from web pages to their own function, [12:00.280 --> 12:01.940] to its own function. [12:02.150 --> 12:05.120] It then implements web interface commands [12:05.120 --> 12:09.180] such as backup, network configuration, [12:09.800 --> 12:13.180] retrieve system information and much more. [12:13.180 --> 12:15.980] And the last one is libemf. [12:15.980 --> 12:21.580] This library is used by emfd for web authentication, [12:21.580 --> 12:25.520] input validation and some code execution. [12:26.940 --> 12:30.780] And now let's look at this in a diagram. [12:31.060 --> 12:35.300] So webs listen to HTTP slash HTTPS. [12:35.300 --> 12:39.280] If it receives a JSA page request, [12:39.740 --> 12:46.020] it uses EGS handler to pass a function name to emfd. [12:46.360 --> 12:50.700] Emfd then checks if the function name is mapped. [12:50.700 --> 12:53.200] So it calls the right function pointer. [12:56.100 --> 13:00.400] Eventually emfd runs some kind of shell commands, [13:00.400 --> 13:05.500] for example, ifconfig, IP tables, routes, et cetera. [13:08.820 --> 13:12.500] Since the web server contains both Embedish code [13:12.500 --> 13:15.180] and Ruckus code, [13:15.180 --> 13:22.080] I decided to mark Ruckus function with an RKS prefix. [13:22.160 --> 13:25.120] Ruckus has added a new function [13:25.120 --> 13:30.300] that registers new ESP functions. [13:30.320 --> 13:33.520] ESP again is the handler that runs [13:33.520 --> 13:37.420] if the web server receive a JSP request. [13:38.780 --> 13:43.020] So here we can see that 12 functions are being registered. [13:43.340 --> 13:46.920] Each function registration needs a function name string [13:46.920 --> 13:48.900] and a function pointer. [13:48.900 --> 13:52.080] Now let's understand how we can reach this function [13:52.500 --> 13:54.440] with an HTTP request. [13:57.020 --> 13:59.080] Okay, so for example, [13:59.080 --> 14:01.580] when sending an HTTP request to [14:01.580 --> 14:05.960] slash admin slash webpage slash Wi-Fi network [14:05.960 --> 14:10.860] slash wlan sysconfirm.jsp. [14:10.860 --> 14:14.260] Please remember this page because it's a very long one. [14:15.680 --> 14:19.740] The web server invokes an EGS handler. [14:20.140 --> 14:24.780] On this page, we can see that EGS script has a special tag [14:25.760 --> 14:27.940] right at the beginning, right? [14:27.940 --> 14:31.840] And EGS function are being called from it. [14:33.920 --> 14:36.080] Webs maps every string it received [14:36.080 --> 14:39.180] to a function pointer and then runs it. [14:39.880 --> 14:42.920] So here we can see that a function called [14:42.920 --> 14:47.040] escape JSTR is being called. [14:48.500 --> 14:54.700] And another wonderful function named S is also being called. [14:54.780 --> 14:56.280] Yeah, S, yeah. [14:56.440 --> 14:58.540] A great, a really great example [14:58.540 --> 15:01.000] of a shitty naming convention. [15:01.940 --> 15:04.680] But the naming convention is not the only lousy thing [15:04.680 --> 15:06.420] about this function. [15:06.780 --> 15:10.600] When I reviewed this edit functions, [15:10.600 --> 15:16.480] I noticed that S, STR, escape JS and get cookie value [15:16.940 --> 15:20.100] are all using unsafe string copy. [15:21.300 --> 15:23.800] That means if I can find a webpage [15:23.800 --> 15:28.240] that passes user inputs to one of these function, [15:28.240 --> 15:32.080] I will be able to smash the web server stuck. [15:34.820 --> 15:38.740] All right, so to search for an input [15:38.740 --> 15:41.600] that leads to one of these functions, [15:41.600 --> 15:45.160] I decided to use the good old grab command. [15:45.160 --> 15:48.920] So I would like to search if there are any calls [15:48.920 --> 15:53.100] to one of these function with a non-static value. [15:53.460 --> 15:57.280] It also should not be a session related values [15:57.280 --> 16:00.820] because I might not be able to manipulate them. [16:00.820 --> 16:03.260] Let's say session cookie or something like that [16:03.260 --> 16:07.040] that is being generated behind the scene. [16:08.740 --> 16:12.680] So here I used a regex that made sure S [16:12.680 --> 16:18.160] don't get any value inside a double or single quote. [16:18.480 --> 16:22.020] I managed to find two JSP pages. [16:22.020 --> 16:24.680] One was an error page, [16:24.680 --> 16:28.540] which did not receive any user inputs, the second one. [16:28.540 --> 16:34.180] And the first one was that page with a very long name [16:34.180 --> 16:36.300] that I don't really want to say it again. [16:36.300 --> 16:39.780] So I just have a look on that page. [16:41.100 --> 16:47.580] Okay, so we saw that S function receive [16:47.860 --> 16:51.140] a non-static value called content. [16:52.020 --> 16:55.620] And luckily the content variable is set directly [16:55.620 --> 16:59.960] by a user parameter called content key. [17:02.400 --> 17:05.160] So I just needed to send the right request [17:05.160 --> 17:11.840] to wlan sysconfirm.jsp and that's it, I smashed the stack. [17:13.260 --> 17:20.260] As for exploitation, R510 uses both NX and ASLR. [17:21.180 --> 17:25.280] To overcome NX, I decided to use rope gadget. [17:25.280 --> 17:27.500] Actually, I use the same gadgets [17:28.580 --> 17:32.240] as for my previous stack overflow. [17:33.300 --> 17:36.940] So these are two gadgets that run system [17:38.230 --> 17:40.560] with a pointer to my payload. [17:40.620 --> 17:43.920] And in this case, I'm using NC [17:43.920 --> 17:46.800] to create a reverse shell to my machine. [17:47.060 --> 17:52.740] As for ASLR, same thing as my previous stack overflow, [17:52.740 --> 17:54.880] I can just brute force my way [17:54.880 --> 17:58.180] and overcome its nine bit of randomness. [17:59.260 --> 18:00.460] All right. [18:03.780 --> 18:07.380] So before I continue with my second attack, [18:07.380 --> 18:09.480] I would like to share other vulnerabilities [18:09.480 --> 18:15.920] I found in this research that I think worth mentioning. [18:16.960 --> 18:20.900] So I also found a cross-site scripting, [18:21.060 --> 18:23.600] a denial of service and information leakage [18:24.270 --> 18:28.060] that may lead to another jailbreak. [18:28.200 --> 18:32.000] All of them were found in either the web server [18:32.000 --> 18:34.300] or EMFD. [18:35.840 --> 18:39.000] So let's talk about the XSS. [18:39.060 --> 18:43.060] I discovered that, I discovered this cross-site scripting [18:43.060 --> 18:44.560] on my first research [18:44.980 --> 18:47.780] and actually it was pretty straightforward. [18:48.560 --> 18:53.460] So every Ajax request to slash admin slash [18:53.460 --> 18:58.960] underscore WLA underscore CMD stats dot JSP [18:59.800 --> 19:04.240] has to contain an updater attribute. [19:05.060 --> 19:08.880] This attribute is simply reflected without any sanitation, [19:10.460 --> 19:12.660] as any validation, sorry. [19:13.240 --> 19:17.300] So all I had to do is to send this payload [19:17.300 --> 19:21.720] and it just runs the, you know, the alert message. [19:24.280 --> 19:27.980] XSS in embedded devices is not that big of a deal, [19:27.980 --> 19:30.380] but I decided to report it anyway. [19:31.500 --> 19:35.880] All right, so let's go over the denial of service. [19:36.240 --> 19:40.280] So while I was researching, I came across this request [19:40.720 --> 19:43.400] that simply crashed the server. [19:43.540 --> 19:46.560] I must say I did not invest too much time [19:46.560 --> 19:48.480] understanding this bug. [19:48.900 --> 19:52.840] This is a web server related bug, of course, [19:52.840 --> 19:56.800] that caused either by an old version of embeddice [19:56.800 --> 20:00.740] or in the code Ruckus has added. [20:04.260 --> 20:07.440] All right, and now for the information leakage. [20:07.440 --> 20:11.320] So Ruckus are considering the device serial number [20:11.320 --> 20:14.140] as sensitive information. [20:14.140 --> 20:16.920] In my previous research, I came across functions [20:16.920 --> 20:22.500] in Ruckus CLI that rely on the device serial number [20:22.720 --> 20:26.760] to get to a busy box shell, to jailbreak. [20:26.760 --> 20:31.180] In this research, I noticed that upnp.jsp page [20:31.180 --> 20:34.660] is reachable without any authentication. [20:35.820 --> 20:38.740] And this page gives away many useful information [20:38.740 --> 20:42.100] on the device that can be used for fingerprinting, [20:42.100 --> 20:43.180] let's say. [20:43.740 --> 20:46.980] But the best part is that I can get the device [20:46.980 --> 20:50.660] serial number and probably jailbreak. [20:52.580 --> 20:58.280] Okay, so now is the time for my second RCE. [20:58.340 --> 21:01.800] In this attack, I found a way to reuse [21:01.800 --> 21:03.300] the command injection vulnerability [21:03.880 --> 21:05.860] from my previous research. [21:05.860 --> 21:09.420] I then had to find a new way to bypass authentication [21:09.840 --> 21:12.820] by overriding admin credentials. [21:15.860 --> 21:19.060] So let's first understand how the command injection [21:19.060 --> 21:22.140] used to work in my previous research. [21:22.420 --> 21:26.860] So embed this, I'm sorry, EMFD execute code [21:26.860 --> 21:28.700] in a really messy way. [21:28.700 --> 21:33.640] EMFD sometimes uses libemf, other time calls [21:33.640 --> 21:38.040] the shell script sys underscore wrapper.sh [21:38.700 --> 21:42.680] and sometimes just run the command itself using libc. [21:43.640 --> 21:47.120] These are all the different function that EMFD [21:47.120 --> 21:49.660] uses to execute shell commands. [21:51.340 --> 21:56.220] As you can see, there are many libc system function code. [21:56.220 --> 22:00.380] So I had to find a page that uses this system function [22:00.800 --> 22:02.440] without validation. [22:04.580 --> 22:08.840] And I found four functions that call system [22:08.840 --> 22:11.780] and were vulnerable to command injection. [22:12.060 --> 22:15.400] And I will be showing the injection on the last one, [22:15.400 --> 22:19.160] which is CMD import AVP port. [22:20.920 --> 22:23.600] To reach the vulnerable function, [22:23.600 --> 22:27.680] I had to send an Ajax request to slash admin [22:27.680 --> 22:31.680] slash cmdstat.jsp. [22:33.700 --> 22:42.060] This request use an EMFD command called import AVP port. [22:42.900 --> 22:46.120] And when EMFD received this request, [22:46.120 --> 22:51.420] it uses a function called CMD import AVP port. [22:51.420 --> 22:55.200] And this function just uses libc system function [22:55.200 --> 22:57.240] just like that, unsafely. [22:58.620 --> 23:01.740] Here you can see the function decompiled code [23:01.740 --> 23:05.000] as it used to be in my previous research. [23:05.360 --> 23:07.620] So for my previous research, [23:08.360 --> 23:11.580] all I had to do is to pass a command injection [23:11.580 --> 23:14.380] in the upload file attribute. [23:14.380 --> 23:18.600] As you can see, it just executed without any validation. [23:20.560 --> 23:23.600] But the problem was that I had to be authenticated [23:23.960 --> 23:25.820] to reach this function. [23:25.820 --> 23:28.100] I had to use a valid cookie. [23:32.290 --> 23:35.490] Okay, so to fix this, [23:35.490 --> 23:37.950] Ruckus decided to use a function called [23:38.370 --> 23:40.990] is validate input string. [23:41.190 --> 23:42.710] That's supposed to validate [23:42.710 --> 23:44.890] there are no injection characters [23:44.890 --> 23:47.860] in the upload file attributes. [23:49.370 --> 23:55.030] This is an external util function found in lib EMF. [23:55.030 --> 23:58.840] And it's being used widely for input validation. [24:04.060 --> 24:07.890] So let's have a look at this validation function. [24:10.010 --> 24:14.840] Here are all the forbidden characters for a given input. [24:14.840 --> 24:18.780] Well, at first, this validation seems pretty solid. [24:18.800 --> 24:20.780] However, some very important characters [24:20.780 --> 24:23.520] are missing from that list. [24:25.280 --> 24:28.760] So something I like to do when reviewing a validator [24:28.760 --> 24:32.380] is to create a set of all the printable [24:32.380 --> 24:36.800] non-alphanumeric characters that can pass this validator. [24:37.400 --> 24:40.840] And well, this is the moment I would ask you guys [24:40.840 --> 24:47.300] if you think of a payload using this set of characters. [24:47.300 --> 24:50.620] But thanks to coronavirus, I can't really do this shtick. [24:50.620 --> 24:52.240] So nevermind. [24:52.400 --> 24:56.760] And anyway, after some trial and error, [24:56.760 --> 24:59.600] I realize a shebang sign, [24:59.600 --> 25:02.640] which is pound followed by exclamation mark [25:02.640 --> 25:04.120] is a valid input. [25:04.120 --> 25:09.900] So I can also use slash and I can also use slash. [25:11.020 --> 25:15.980] So I can use shebang slash bin slash sh. [25:16.720 --> 25:19.720] So this is good, but not good enough. [25:19.720 --> 25:24.580] I can't just append this payload to a command run by system. [25:25.040 --> 25:28.360] And well, this is because shebang should be [25:28.360 --> 25:30.120] in a line of its own, right? [25:30.120 --> 25:32.040] It's usually the header. [25:33.260 --> 25:37.020] Luckily, I could also use a newline character. [25:37.020 --> 25:39.580] Yeah, that is correct. [25:39.580 --> 25:41.840] A newline character as a parameter input [25:41.840 --> 25:47.160] is not being sanitized, not in the web server, nor EMF. [25:47.160 --> 25:48.820] Amazing, right? [25:49.060 --> 25:53.960] Well, shebang plus a newline, [25:53.960 --> 25:57.280] it equals sweet, sweet exploit love. [25:58.380 --> 25:59.300] Yeah. [25:59.300 --> 26:03.180] Okay, so that was good news. [26:03.780 --> 26:08.140] I can now replace my injection with shebang, [26:08.140 --> 26:12.740] but there was one thing left to solve. [26:13.800 --> 26:17.880] Space characters is also not a valid input. [26:17.880 --> 26:22.860] So I simply replaced them with tab characters. [26:23.860 --> 26:27.000] Let's have a look on my new payload. [26:29.120 --> 26:32.380] You can see that for semicolon, [26:33.200 --> 26:38.120] so I replaced semicolon with shebang plus a newline [26:40.180 --> 26:43.700] and spaces were replaced by tab. [26:45.020 --> 26:46.260] And that's it. [26:46.260 --> 26:50.100] This is how I was able to reuse [26:50.100 --> 26:52.500] my command injection vulnerability. [26:52.500 --> 26:55.860] The last thing I had to do to complete this exploit [26:56.240 --> 26:58.880] is bypass authentication again. [27:01.320 --> 27:04.920] Okay, so now I would like to explain [27:04.920 --> 27:08.980] how the admin credentials are stored in the device. [27:10.420 --> 27:16.260] So system.xml is the device general configuration file. [27:16.260 --> 27:18.100] It contains the admin credential [27:18.100 --> 27:21.400] as well as other important configuration. [27:22.500 --> 27:26.280] Here you can see that the admin element [27:26.280 --> 27:31.740] and its password is stored in the x-password attribute. [27:32.340 --> 27:34.000] While working on this exploit, [27:34.000 --> 27:36.280] I noticed that Ruckus has decided [27:36.600 --> 27:39.680] to use the most secure mechanism [27:39.680 --> 27:43.560] for storing sensitive passwords, as you can see here. [27:43.560 --> 27:46.520] So you might look at this x-password attribute [27:46.520 --> 27:52.120] and think that my password is 12345BCB, [27:52.280 --> 27:54.400] but that's not the case. [27:54.400 --> 28:00.200] My actual password is 12345ABCD. [28:00.200 --> 28:02.600] Yes, yes, yes. [28:02.600 --> 28:05.360] Ruckus are obfuscating the password [28:05.360 --> 28:08.210] by adding one to each character. [28:08.980 --> 28:12.660] Gosh, gosh, I just don't understand [28:12.660 --> 28:16.080] why won't they use a simple hash function. [28:16.080 --> 28:17.280] Don't get it. [28:17.280 --> 28:20.100] But nevermind about that. [28:20.980 --> 28:23.480] Let's have a look at slash admin, [28:23.480 --> 28:30.880] slash underscore WLA underscore conf dot JSP page. [28:31.080 --> 28:36.840] We can see that this page calls for two functions in EMFD, [28:37.100 --> 28:42.040] login without access check and AJAX conf. [28:42.520 --> 28:45.960] Please keep in mind that we must pass the first function [28:45.960 --> 28:50.080] to get to AJAX conf, which is the vulnerable function. [28:51.960 --> 28:55.080] So without login access check, [28:55.080 --> 28:58.380] expects an AJAX request XML [28:58.880 --> 29:06.560] that contains either set conf action or do conf action. [29:06.780 --> 29:12.620] The do, sorry, either set conf or do CMD action. [29:12.620 --> 29:16.380] The do CMD action in this case was very limited [29:16.920 --> 29:21.440] and I decided to focus only on set conf. [29:23.620 --> 29:27.940] So set conf action calls an EMFD function [29:27.940 --> 29:33.100] called check research credentials configuration parameter. [29:34.660 --> 29:39.320] This function expects an admin XML element [29:39.320 --> 29:41.640] with the following attributes. [29:43.560 --> 29:48.280] And please note that this function only validate [29:48.590 --> 29:52.380] the number of elements, eight in this case, [29:52.380 --> 29:56.660] and it only validate that the attributes names [29:56.660 --> 29:59.520] matches the one we see here. [29:59.520 --> 30:01.620] That means it won't check the value [30:01.620 --> 30:05.780] only that a certain request contains eight elements [30:05.780 --> 30:08.460] that matches with this name. [30:08.840 --> 30:15.480] And it doesn't check for any permissions whatsoever. [30:16.720 --> 30:20.300] Okay, so here we can see a valid AJAX request [30:20.300 --> 30:22.820] with an admin element. [30:24.200 --> 30:26.800] So this request has all the right attributes [30:26.800 --> 30:29.900] as you can see eight and then the right, [30:29.900 --> 30:34.240] and it can reach the vulnerable AJAX conf function. [30:35.240 --> 30:39.320] Okay, so let's move to AJAX conf. [30:39.790 --> 30:44.120] This is a very big function that does all sorts of things. [30:44.120 --> 30:49.080] One of them is to use adapter set conf [30:49.310 --> 30:52.050] to update different configuration file. [30:53.410 --> 30:55.280] In particular, it can update [30:55.280 --> 30:59.780] the main system dot XML configuration. [30:59.780 --> 31:05.120] Okay, as we saw, without login access, [31:05.120 --> 31:09.440] forces me to use a specific XML element. [31:10.020 --> 31:15.440] But thankfully, this is the admin credentials XML element. [31:15.440 --> 31:19.760] So now let's understand how adapter set conf works [31:19.760 --> 31:24.360] and may be manipulated to write these credentials. [31:25.360 --> 31:32.080] So this is how adapter set conf function looks like. [31:32.680 --> 31:36.820] It receives the request component attributes [31:37.400 --> 31:42.060] and the AJAX request itself. [31:43.100 --> 31:49.200] I realized that if the component equals to system, [31:49.200 --> 31:53.140] then it can only update a specific XML element, [31:53.140 --> 31:55.860] which is not the admin element. [31:55.860 --> 31:59.320] So I can just override the admin credentials [31:59.320 --> 32:00.980] with this request. [32:03.920 --> 32:08.620] However, if the component attribute is not equal to system, [32:08.620 --> 32:13.360] it uses a function called repo get curr child. [32:14.340 --> 32:17.540] And this function gets a component name [32:17.540 --> 32:23.120] and looks for an XML configuration file with that name. [32:24.140 --> 32:28.020] So that means I can access any XML file [32:28.020 --> 32:30.540] in the air spider directory. [32:30.540 --> 32:34.540] Well, all of them except for the system XML [32:34.540 --> 32:39.960] because adapter set conf make sure it's excluded. [32:40.260 --> 32:42.380] But the credentials I want to override [32:42.380 --> 32:47.460] are in the system dot XML, which sucks, right? [32:48.520 --> 32:52.840] So this is where slash come to our rescue. [32:53.300 --> 32:56.380] I noticed that if I add a slash [32:56.580 --> 33:00.020] at the beginning of the component attributes, [33:00.020 --> 33:02.900] it's no longer a system component. [33:02.900 --> 33:07.120] It's now a slash system component. [33:07.780 --> 33:11.760] So now I can pass this system attribute check [33:12.620 --> 33:17.340] and now get a repo get curr child function [33:17.340 --> 33:21.400] will look for the file slash system dot XML, [33:21.400 --> 33:26.280] not system dot XML, which is perfectly fine in POSIX [33:26.280 --> 33:29.780] since we can add as many slashes as we want. [33:33.390 --> 33:36.330] Okay, and that's about it. [33:36.330 --> 33:40.010] Adapter set conf has replaced the admin element [33:40.010 --> 33:44.010] in system dot XML, which means I was able [33:44.010 --> 33:46.790] to override the admin credentials. [33:46.790 --> 33:51.390] Okay, now I just need to chain [33:51.390 --> 33:53.810] these two vulnerabilities together. [33:54.890 --> 33:58.390] So first the override, here I'm overriding [33:58.870 --> 34:02.330] the admin credentials with password 1234. [34:05.450 --> 34:10.810] Then run the command injection to pop a shell on the device. [34:12.150 --> 34:15.910] Well, since I consider myself a polite person, [34:15.910 --> 34:19.310] after getting a shell, I can obtain the original credentials [34:19.310 --> 34:25.910] by grepping slash var slash run slash RPM key asterisks. [34:26.750 --> 34:30.950] This was the file that I was able to leak [34:30.950 --> 34:33.250] in the first research. [34:33.250 --> 34:36.430] Fortunately, Ruckus insist on saving passwords [34:36.430 --> 34:38.230] as plain text. [34:38.230 --> 34:41.650] So all is left to do is to repeat the attack [34:41.650 --> 34:44.750] with the original credentials and avoid leaving [34:45.090 --> 34:47.010] any footprint on the device. [34:47.010 --> 34:49.730] Cause we're not that rude, right? [34:50.930 --> 34:51.990] Okay. [34:58.030 --> 35:02.030] So this is the time for my final demo. [35:02.030 --> 35:05.130] Again, I'll try to do it live-ish. [35:06.650 --> 35:10.910] Okay, so for that I need my terminal again. [35:11.850 --> 35:16.690] Okay, so first I would like to override the credentials. [35:16.690 --> 35:22.090] So let me just show you the payload. [35:22.090 --> 35:25.610] So this is the request. [35:25.750 --> 35:32.210] And let's just, you know, change the passwords to DEF CON. [35:32.210 --> 35:33.170] Why not? [35:33.170 --> 35:36.050] And 28 safe mode. [35:36.710 --> 35:37.810] Awesome. [35:39.770 --> 35:40.810] Okay. [35:40.810 --> 35:42.090] Yes. [35:42.090 --> 35:46.810] And now I would like to post this XML. [35:46.810 --> 35:55.070] So I'm just posting it to this admin wla-conf-jsp. [35:56.650 --> 35:57.650] And this is it. [35:57.650 --> 36:00.350] I overrode the credentials. [36:00.350 --> 36:03.930] Now I'll have to authenticate again to log in. [36:07.250 --> 36:12.070] So let's go with, what was it? [36:12.090 --> 36:16.110] DEF CON 28 safe mode. [36:16.110 --> 36:20.090] So this is just a standard login request. [36:20.410 --> 36:24.350] And I get the CSRF token and a set cookie. [36:25.010 --> 36:27.950] And now for my new, [36:29.550 --> 36:33.070] oh wait, I just want to show you guys my injection. [36:33.070 --> 36:34.850] So this is my new command injection [36:35.410 --> 36:40.130] where I use shebang and then new line, [36:40.130 --> 36:41.470] telnet top tab, [36:41.470 --> 36:47.450] and I'm going to open a port in 7331 on the device. [36:48.030 --> 36:49.630] Yes. [36:50.250 --> 36:51.210] Okay. [36:51.390 --> 36:52.590] So this is it. [36:52.590 --> 36:57.350] Let me just update the credentials real quick. [36:59.650 --> 37:05.190] This is the first one and that's the cookie. [37:05.870 --> 37:07.470] Okay. [37:09.650 --> 37:10.290] Okay. [37:10.290 --> 37:10.930] Great. [37:11.190 --> 37:15.610] So let's just run it. [37:17.230 --> 37:19.070] Okay, that's it. [37:19.070 --> 37:21.990] And now for the moment of truth, [37:21.990 --> 37:27.050] I'll log in, I'll tell it to 7331. [37:27.230 --> 37:33.950] And as you can see here, I'm the root and this is it. [37:34.910 --> 37:36.170] Okay. [37:43.540 --> 37:50.780] So in conclusion, today I demonstrated two pre-auth RCEs. [37:50.780 --> 37:55.220] The first one was pre-auth stack buffer overflow. [37:55.220 --> 37:57.320] And the second was command injection [37:57.320 --> 37:59.700] with credentials overwrite. [38:01.380 --> 38:06.140] I will also share my new and improved Jidra script [38:06.140 --> 38:08.920] that really helped me with this research. [38:09.760 --> 38:14.500] Ruckus Networks was informed about these vulnerabilities. [38:14.500 --> 38:18.000] I requested six CVEs and they confirmed them. [38:19.320 --> 38:26.440] So in total, these two research concluded in 17 CVEs [38:26.440 --> 38:30.240] that resulted in five different RCEs. [38:32.600 --> 38:35.060] And as I said in my previous talk, [38:35.060 --> 38:38.420] if there are any Ruckus users who are watching this, [38:38.420 --> 38:39.740] you should stop what you're doing [38:39.740 --> 38:44.320] and check that you're running the latest firmware update. [38:44.320 --> 38:50.260] If not, you may be a victim to some very serious stuff. [38:51.520 --> 38:54.480] Okay, so that's it. [38:54.480 --> 38:58.020] These two research were tons of fun. [38:58.160 --> 39:00.380] I'm really glad that I helped Ruckus [39:00.380 --> 39:02.940] making their equipment more secure. [39:02.940 --> 39:06.660] I will post a second blog post with all the specific [39:06.660 --> 39:09.940] at alephsecurity.com. [39:09.940 --> 39:13.400] Feel free to check our blog for my previous research [39:13.400 --> 39:18.200] and other amazing research done by our group. [39:19.960 --> 39:20.720] That's it. [39:20.720 --> 39:22.920] Thank you very much for your attention. [39:22.920 --> 39:24.760] Stay safe and healthy. [39:27.080 --> 39:28.260] Woohoo!