Okay, don't ruckus again, take one million. Hi everyone, and thank you for watching my talk and thanks DEF CON for inviting me and not giving up on this year con. This is the first time I speak on DEF CON and I could really use a welcome round shot, but since I'm not in Vegas, well, I think I'm gonna save it for another time. This talk will present my recent research on Ruckus Wireless. Ruckus is a wireless solution company owned by Comscope. I've come to realize that Ruckus is pretty popular in the States. They even partnered with Black Hat for conference Wi-Fi solution. Actually, this is how I first noticed them. In the last year, I've been doing vulnerability research on Ruckus access points, and so far I managed to find several critical vulnerabilities in many of these devices. My previous research was introduced in the recent CCC convention, back when traveling places was a real thing. But before I begin, I would like to go over the obligatory who am I part. So my name is Galt Swar. I'm a research team leader at Aleph Research by HCL AppScan. I'm recording this talk from our lovely office in Herzliya, Israel. And I've been doing reversing for more than a decade. I try to focus on offensive embedded devices research. All right, I would like to begin with a quick recap. In my previous research, I demonstrated three ways to run code on Ruckus unleashed and zone director devices. All vulnerability were found on the device web interface. My first RCE was credential leakage with SSH jailbreak. My second RCE was unauthenticated stack buffer overflow. And the last RCE was command injection vulnerability, which was reachable without authentication by writing a new page. In this talk, same as in my previous one, I will be using Ruckus R510 unleashed. Ruckus has an unleashed version for every access point they provide. Unleashed access points don't rely on Wi-Fi controllers. Well, all access point in the list you can see here share the same vulnerable code base. And I also noticed that some vulnerabilities works on zone director product line, which is the Wi-Fi controllers. Okay, so what's new? Well, this research began right after I got Ruckus patch for my first research. I noticed that they did not fix my vulnerability correctly. So I decided to try and re-enable it. Besides that, my first research was 100% based on device emulation. Now that I bought an actual device, I can try to see if I missed something that I couldn't emulate. Well, but before I begin with the new vulnerabilities, I would like to talk about a new Jidra script that I used for this research. My previous research and this one was done relatively fast. Thanks to a Jidra script, I wrote that fetches function name from log strings Ruckus has left in their binaries. Here you can see some of them from one of the binaries. This script helped me rename function by parsing these log lines that contained the function name. For more information about the script and its generic version, please check my previous talk or our GitHub. All in all, this script was super useful for binary compiled with Ruckus code, but not all binaries were like that. It's a common thing for embedded devices vendor to use open source project in their devices. Ruckus web server is a good example for that. Ruckus added new functionality by adding code to a popular web server called Embed This. Since Embed This sources are public, I didn't really need to reverse the entire web server binary. It was easier for me just to review the source code. But what about the parts that Ruckus added? I would like to be able to mark these parts in JITRA, so I'll know I'll have to reverse them. So for this, I wrote an additional JITRA script. My new script tries to extract as many function names as it can from the Embed This sources. I use different methods to extract this information, things like string matching and function call trace. But the thing that helped me the most were debugging functions that contain the exact C filename and line number in the Embed This sources. Here we can see that for this unnamed function from the web server binary, we get that this function appears in server.c file around the line number 138. So if we go to this line in the Embed This sources, we'll be able to extract many function names from the sources. This is the function in JITRA after conversion. These are all function name that I was able to extract from the source code to JITRA. Okay, so let's take this function coin graph, for example. This function is called macreateWebServer, and it's being called from the main. And it also calls other functions. Well, on the right-hand side, we can see that all of the function names I was able to fetch from the sources by using the script I just introduced. On the bottom left-hand side, we can see the function names I was able to fetch by using the script from my previous research, the one that uses the log strings. And as you can see, there are still unnamed function left, but still the majority of functions are now named. So this is an excellent example of how these two scripts help me retrieve plenty of information and save me so much time and effort on reversing. I'm also in the progress of writing a generic version for this script that won't rely on specific debug information. I will share all of my script in our Aleph Research GitHub account, so feel free to check it out. And while you're there, you can also check other tools that we got there. All right, cool. So now we're ready for some exploits. This is my first RCE. In this attack, I found another stack overflow that was reachable with unauthenticated web request. And I would like to start with a demo. Well, this is clearly not a live demo, but I will still try to do it in a live demo style. So yeah, let's see how it goes. Okay, so for that, I need my demo screen and my listener screen. Okay, so this is the terminal that I'm gonna listen to port 1337. And my exploit will create reverse shell to this port. Let's just start listening. And now, okay. And now let's have a look on my stack overflow. So this is my overflow. Wait, let me open it in a different way. Okay, so this is my overflow, as you can see here. And I am creating this reverse shell by using Netcat. And let's just go ahead and send this. So I will be posting this file to this address. And okay, hopefully everything will work. Connection refused, it's a good indication. Let's see what's going on with my listener. Okay, so connection received, looking good. As you can see, I managed to run ls and my user is admin. And this user is part of the root group. Yeah, so this is it. This is my demo. Okay, before I get into the vulnerability, I would like to do a quick recap on my previous talk. This slide and the next one were actually taken from my previous talk, but I'll go over them just to create the right context. There are three important binaries in the web interface. The first one is slash bin slash webs. This is the actual embeddice web server. It handles HTTP requests and executes handlers according to its configuration. It then sends commands through a Unix domain socket to emfd. Slash bin slash emfd is an executable that contains the web interface logic. It maps function from web pages to their own function, to its own function. It then implements web interface commands such as backup, network configuration, retrieve system information and much more. And the last one is libemf. This library is used by emfd for web authentication, input validation and some code execution. And now let's look at this in a diagram. So webs listen to HTTP slash HTTPS. If it receives a JSA page request, it uses EGS handler to pass a function name to emfd. Emfd then checks if the function name is mapped. So it calls the right function pointer. Eventually emfd runs some kind of shell commands, for example, ifconfig, IP tables, routes, et cetera. Since the web server contains both Embedish code and Ruckus code, I decided to mark Ruckus function with an RKS prefix. Ruckus has added a new function that registers new ESP functions. ESP again is the handler that runs if the web server receive a JSP request. So here we can see that 12 functions are being registered. Each function registration needs a function name string and a function pointer. Now let's understand how we can reach this function with an HTTP request. Okay, so for example, when sending an HTTP request to slash admin slash webpage slash Wi-Fi network slash wlan sysconfirm.jsp. Please remember this page because it's a very long one. The web server invokes an EGS handler. On this page, we can see that EGS script has a special tag right at the beginning, right? And EGS function are being called from it. Webs maps every string it received to a function pointer and then runs it. So here we can see that a function called escape JSTR is being called. And another wonderful function named S is also being called. Yeah, S, yeah. A great, a really great example of a shitty naming convention. But the naming convention is not the only lousy thing about this function. When I reviewed this edit functions, I noticed that S, STR, escape JS and get cookie value are all using unsafe string copy. That means if I can find a webpage that passes user inputs to one of these function, I will be able to smash the web server stuck. All right, so to search for an input that leads to one of these functions, I decided to use the good old grab command. So I would like to search if there are any calls to one of these function with a non-static value. It also should not be a session related values because I might not be able to manipulate them. Let's say session cookie or something like that that is being generated behind the scene. So here I used a regex that made sure S don't get any value inside a double or single quote. I managed to find two JSP pages. One was an error page, which did not receive any user inputs, the second one. And the first one was that page with a very long name that I don't really want to say it again. So I just have a look on that page. Okay, so we saw that S function receive a non-static value called content. And luckily the content variable is set directly by a user parameter called content key. So I just needed to send the right request to wlan sysconfirm.jsp and that's it, I smashed the stack. As for exploitation, R510 uses both NX and ASLR. To overcome NX, I decided to use rope gadget. Actually, I use the same gadgets as for my previous stack overflow. So these are two gadgets that run system with a pointer to my payload. And in this case, I'm using NC to create a reverse shell to my machine. As for ASLR, same thing as my previous stack overflow, I can just brute force my way and overcome its nine bit of randomness. All right. So before I continue with my second attack, I would like to share other vulnerabilities I found in this research that I think worth mentioning. So I also found a cross-site scripting, a denial of service and information leakage that may lead to another jailbreak. All of them were found in either the web server or EMFD. So let's talk about the XSS. I discovered that, I discovered this cross-site scripting on my first research and actually it was pretty straightforward. So every Ajax request to slash admin slash underscore WLA underscore CMD stats dot JSP has to contain an updater attribute. This attribute is simply reflected without any sanitation, as any validation, sorry. So all I had to do is to send this payload and it just runs the, you know, the alert message. XSS in embedded devices is not that big of a deal, but I decided to report it anyway. All right, so let's go over the denial of service. So while I was researching, I came across this request that simply crashed the server. I must say I did not invest too much time understanding this bug. This is a web server related bug, of course, that caused either by an old version of embeddice or in the code Ruckus has added. All right, and now for the information leakage. So Ruckus are considering the device serial number as sensitive information. In my previous research, I came across functions in Ruckus CLI that rely on the device serial number to get to a busy box shell, to jailbreak. In this research, I noticed that upnp.jsp page is reachable without any authentication. And this page gives away many useful information on the device that can be used for fingerprinting, let's say. But the best part is that I can get the device serial number and probably jailbreak. Okay, so now is the time for my second RCE. In this attack, I found a way to reuse the command injection vulnerability from my previous research. I then had to find a new way to bypass authentication by overriding admin credentials. So let's first understand how the command injection used to work in my previous research. So embed this, I'm sorry, EMFD execute code in a really messy way. EMFD sometimes uses libemf, other time calls the shell script sys underscore wrapper.sh and sometimes just run the command itself using libc. These are all the different function that EMFD uses to execute shell commands. As you can see, there are many libc system function code. So I had to find a page that uses this system function without validation. And I found four functions that call system and were vulnerable to command injection. And I will be showing the injection on the last one, which is CMD import AVP port. To reach the vulnerable function, I had to send an Ajax request to slash admin slash cmdstat.jsp. This request use an EMFD command called import AVP port. And when EMFD received this request, it uses a function called CMD import AVP port. And this function just uses libc system function just like that, unsafely. Here you can see the function decompiled code as it used to be in my previous research. So for my previous research, all I had to do is to pass a command injection in the upload file attribute. As you can see, it just executed without any validation. But the problem was that I had to be authenticated to reach this function. I had to use a valid cookie. Okay, so to fix this, Ruckus decided to use a function called is validate input string. That's supposed to validate there are no injection characters in the upload file attributes. This is an external util function found in lib EMF. And it's being used widely for input validation. So let's have a look at this validation function. Here are all the forbidden characters for a given input. Well, at first, this validation seems pretty solid. However, some very important characters are missing from that list. So something I like to do when reviewing a validator is to create a set of all the printable non-alphanumeric characters that can pass this validator. And well, this is the moment I would ask you guys if you think of a payload using this set of characters. But thanks to coronavirus, I can't really do this shtick. So nevermind. And anyway, after some trial and error, I realize a shebang sign, which is pound followed by exclamation mark is a valid input. So I can also use slash and I can also use slash. So I can use shebang slash bin slash sh. So this is good, but not good enough. I can't just append this payload to a command run by system. And well, this is because shebang should be in a line of its own, right? It's usually the header. Luckily, I could also use a newline character. Yeah, that is correct. A newline character as a parameter input is not being sanitized, not in the web server, nor EMF. Amazing, right? Well, shebang plus a newline, it equals sweet, sweet exploit love. Yeah. Okay, so that was good news. I can now replace my injection with shebang, but there was one thing left to solve. Space characters is also not a valid input. So I simply replaced them with tab characters. Let's have a look on my new payload. You can see that for semicolon, so I replaced semicolon with shebang plus a newline and spaces were replaced by tab. And that's it. This is how I was able to reuse my command injection vulnerability. The last thing I had to do to complete this exploit is bypass authentication again. Okay, so now I would like to explain how the admin credentials are stored in the device. So system.xml is the device general configuration file. It contains the admin credential as well as other important configuration. Here you can see that the admin element and its password is stored in the x-password attribute. While working on this exploit, I noticed that Ruckus has decided to use the most secure mechanism for storing sensitive passwords, as you can see here. So you might look at this x-password attribute and think that my password is 12345BCB, but that's not the case. My actual password is 12345ABCD. Yes, yes, yes. Ruckus are obfuscating the password by adding one to each character. Gosh, gosh, I just don't understand why won't they use a simple hash function. Don't get it. But nevermind about that. Let's have a look at slash admin, slash underscore WLA underscore conf dot JSP page. We can see that this page calls for two functions in EMFD, login without access check and AJAX conf. Please keep in mind that we must pass the first function to get to AJAX conf, which is the vulnerable function. So without login access check, expects an AJAX request XML that contains either set conf action or do conf action. The do, sorry, either set conf or do CMD action. The do CMD action in this case was very limited and I decided to focus only on set conf. So set conf action calls an EMFD function called check research credentials configuration parameter. This function expects an admin XML element with the following attributes. And please note that this function only validate the number of elements, eight in this case, and it only validate that the attributes names matches the one we see here. That means it won't check the value only that a certain request contains eight elements that matches with this name. And it doesn't check for any permissions whatsoever. Okay, so here we can see a valid AJAX request with an admin element. So this request has all the right attributes as you can see eight and then the right, and it can reach the vulnerable AJAX conf function. Okay, so let's move to AJAX conf. This is a very big function that does all sorts of things. One of them is to use adapter set conf to update different configuration file. In particular, it can update the main system dot XML configuration. Okay, as we saw, without login access, forces me to use a specific XML element. But thankfully, this is the admin credentials XML element. So now let's understand how adapter set conf works and may be manipulated to write these credentials. So this is how adapter set conf function looks like. It receives the request component attributes and the AJAX request itself. I realized that if the component equals to system, then it can only update a specific XML element, which is not the admin element. So I can just override the admin credentials with this request. However, if the component attribute is not equal to system, it uses a function called repo get curr child. And this function gets a component name and looks for an XML configuration file with that name. So that means I can access any XML file in the air spider directory. Well, all of them except for the system XML because adapter set conf make sure it's excluded. But the credentials I want to override are in the system dot XML, which sucks, right? So this is where slash come to our rescue. I noticed that if I add a slash at the beginning of the component attributes, it's no longer a system component. It's now a slash system component. So now I can pass this system attribute check and now get a repo get curr child function will look for the file slash system dot XML, not system dot XML, which is perfectly fine in POSIX since we can add as many slashes as we want. Okay, and that's about it. Adapter set conf has replaced the admin element in system dot XML, which means I was able to override the admin credentials. Okay, now I just need to chain these two vulnerabilities together. So first the override, here I'm overriding the admin credentials with password 1234. Then run the command injection to pop a shell on the device. Well, since I consider myself a polite person, after getting a shell, I can obtain the original credentials by grepping slash var slash run slash RPM key asterisks. This was the file that I was able to leak in the first research. Fortunately, Ruckus insist on saving passwords as plain text. So all is left to do is to repeat the attack with the original credentials and avoid leaving any footprint on the device. Cause we're not that rude, right? Okay. So this is the time for my final demo. Again, I'll try to do it live-ish. Okay, so for that I need my terminal again. Okay, so first I would like to override the credentials. So let me just show you the payload. So this is the request. And let's just, you know, change the passwords to DEF CON. Why not? And 28 safe mode. Awesome. Okay. Yes. And now I would like to post this XML. So I'm just posting it to this admin wla-conf-jsp. And this is it. I overrode the credentials. Now I'll have to authenticate again to log in. So let's go with, what was it? DEF CON 28 safe mode. So this is just a standard login request. And I get the CSRF token and a set cookie. And now for my new, oh wait, I just want to show you guys my injection. So this is my new command injection where I use shebang and then new line, telnet top tab, and I'm going to open a port in 7331 on the device. Yes. Okay. So this is it. Let me just update the credentials real quick. This is the first one and that's the cookie. Okay. Okay. Great. So let's just run it. Okay, that's it. And now for the moment of truth, I'll log in, I'll tell it to 7331. And as you can see here, I'm the root and this is it. Okay. So in conclusion, today I demonstrated two pre-auth RCEs. The first one was pre-auth stack buffer overflow. And the second was command injection with credentials overwrite. I will also share my new and improved Jidra script that really helped me with this research. Ruckus Networks was informed about these vulnerabilities. I requested six CVEs and they confirmed them. So in total, these two research concluded in 17 CVEs that resulted in five different RCEs. And as I said in my previous talk, if there are any Ruckus users who are watching this, you should stop what you're doing and check that you're running the latest firmware update. If not, you may be a victim to some very serious stuff. Okay, so that's it. These two research were tons of fun. I'm really glad that I helped Ruckus making their equipment more secure. I will post a second blog post with all the specific at alephsecurity.com. Feel free to check our blog for my previous research and other amazing research done by our group. That's it. Thank you very much for your attention. Stay safe and healthy. Woohoo!