 Okay, don't rock us again, take one million. Hi everyone, and thank you for watching my talk and thanks Defconn for inviting me and not giving up on this new con. This is the first time I speak on Defconn and I could really use a welcome ROM 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 point and so far I managed to found 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 blogatory Who Am I part. So my name is Galtz Rohr. 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 points 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 simulation. 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 JITRA script that I used for this research. My previous research, and this one, was done relatively fast. Thanks to a JITRA 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 contain the function name. For more information about this 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 a code to a popular web server called EmbedDIS. Since EmbedDIS 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 EmbedDIS 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 file name and line number in the EmbedDIS 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 EmbedDIS 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 names that I was able to extract from the source code to JITRA. Okay, so let's take this function call 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 really share all of my script in our other 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 1, 3, 3, 7. And my exploit will create reverse shell to this port. So 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. Okay, connection refuse, 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 stack. This slide and the next one were actually taken from my previous stock, 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 embed this web server. It handles HTTP request and executes handlers according to its configuration. It then sends command 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 lib EMF. This library is used by EMFD for web authentication, into 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 and if so, it calls the right function pointer. Eventually, EMFD runs some kind of shell commands. For example, if config, IP tables, route, et cetera. Since the web server contains both embed this code and Roku's code, I decided to mark Roku's function with an RKS prefix. Roku's 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 web page 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 escapeJSTR is being called. And another wonderful function named s is also being called. Yeah, s, yeah. 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 these added functions, I noticed that s, sTR, escapeJS, and getCookieValue are all using unsafe string copy. That means if I can find a web page that passes user input 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 session related values because I might not be able to manipulate them. Let's say sessionCookie 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 found two JSP pages. One was an error page which did not receive any user input, 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 wlancsconfirm.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 root gadget. Actually, I use the same gadget 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, yeah. 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 this cross-site scripting on my first research and actually it was pretty straightforward. So every adjunct request to slash admin slash underscore wla underscore cmdstat.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 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 servers. 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 embeddys or in the code Rokus as added. And now for the information leakage. So Rokus are considering the device serial number as sensitive information. In my previous research, I came across functions in Rokus CLI that rely on the device serial number to get to a busybox 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 embeddys, sorry, EMFD execute code in a really messy way. EMFD sometimes uses LibyMF, other time calls the shell script sys underscore wrapper.sh, and sometimes just run the command itself using Liby. These are all the different functions that EMFD uses to execute shell commands. As you can see, there are many Liby system function calls. 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 adjunct request to slash admin slash cmdstat.jsp. This request used 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 Liby system function just like that, unsafely. Here you can see the function decompiled called as is 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, Rutgers decided to use a function called isValidateInputString. That's supposed to validate there are no injection characters in their upload file attribute. This is an external util function found in LibEMF. 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-alpha numeric 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 new line character. Yeah, that is correct. New line character as a parameter input is not being sanitized, not in the web server nor EMF. Amazing, right? Well, shebang plus a new line, 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 a tab characters. Let's have a look on my new payload. You can see that for semicolon, I, so I replaced semicolon with shebang plus a new line 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 xpassword 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 xpassword attribute and think that my password is 12345, BCD, but that's not the case. My actual password is 12345, ABCD. 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 never mind about that. Let's have a look at slash admin slash underscore wla underscore cont.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 and Ajax Request XML that contains either SetConf action or DoConf action. The Do, sorry, either SetConf or DoCMD action. The DoCMD action in this case was very limited and I decided to focus only on SetConf. So SetConf action calls an EMFD function called checkResearchTradentialsConfigurationParameter. This function expects an admin XML element with the following attributes. And please note that this function only validates the number of elements, eight in this case. And it only validates 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 they're 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 SetConf to update different configuration file. In particular, it can update the main system.xml configuration. As we saw without logging 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 SetConf works and maybe manipulated to write these credentials. So this is how adapter SetConf function looks like. It receives the request component attribute 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 getcurchild. 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 AirSpider directory. Well, all of them except for the system XML because adapter SetConf makes sure it's excluded. But the credentials I want to override are in the system.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 attribute, 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 getcurchild function will look for the file slash system.xml, not system.xml, which is perfectly fine in POSIX since we can add as many slashes as we want. Okay, and that's about it. Adapter SetConf has replaced the admin element in system.xml, which means I was able to override the admin credentials. Now I just need to chain these two vulnerabilities together. So first the override. Here I'm overriding the admin credentials with password one, two, three, four. 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 grabbing slash var slash run slash RPM key asterisks. This was the file that I was able to leak in the first research. Fortunately, Roku's insist on saving passwords as plain text. So all he's left to do is to repeat the attack with the original credentials and avoid leaving any footprint on the device cause we are 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 change the password to defcon, why not? And 28, save mode. Awesome, okay, yes. And now I would like to post this XML. So I'm just posting it to this admin WLAconf.jsp. And this is it. I overrode the credentials. Now I'll have to authenticate again to login. So let's go with what was it? Defcon, 28, save mode. So this is just a standard login request. And I get the CSRF token and set cookie. And now for my new, oh wait, I just wanna show you guys my injection. So this is my new command injection, where I use shebang and then new line, telnet-top-top, and I'm gonna 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, great. So you just run it, okay, that's it. And now for the moment of truth, I'll log in, I'll turn 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 Geodra script that really helped me with this research. Rocus 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 Rocus 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 Rocus making their equipment more secure. I will post a second blog post with all the specific at alefsecurity.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.