This article is in no way affiliated, sponsored, or endorsed with/by MesaLabs. All graphics are being displayed under fair use for the purposes of this article.
During a recent assessment, multiple vulnerabilities of varied bug types were discovered in the MesaLabs AmegaView Continous Monitoring System, including command injection (CVE-2021-27447, CVE-2021-27449), improper authentication (CVE-2021-27451), authentication bypass (CVE-2021-27453), and privilege escalation (CVE-2021-27445). In this blog post, we will describe each of the vulnerabilities and how they were discovered.
While operating we often encounter devices that make up what we colloquially refer to as the “internet of things”, or simply IoT. These are various network-enabled devices outside of the usual workstation, server, switches, routers, and printers. IoT devices are often overlooked by network defenders since they often come with custom applications and are more difficult to adequately monitor. As, red teamers we pay particular attention to these systems because they can provide reliable persistence on the network and are generally less secure.
The first thing that caught my eye about the AmegaView login page was it required a passkey for authentication rather than the usual username and password. My initial inclination was to gather more information about the passkey to determine if I could brute force it. So I started where we all do, I checked the web page source.
The source code revealed a couple of details about the passkey. The “size” and “max length” of the password field are set to 10. We would still need more information to realistically brute force the passkey as 10 characters is too long. However, the source code disclosed two more crucial pieces of information, the existence of the “/www” directory and the “/index.cgi?J=TIME_EDIT” endpoint.
Navigating to the “/www” directory in a web browser produces a directory listing which includes two perl files, among others. We also find we can navigate to /index.cgi?J=TIME_EDIT without authentication.
The perl file “amegalib.pl” divulges quite a bit of information. It defines how the passkey is generated, and contains a function that executes privileged OS commands that is reachable from the “/index.cgi?J=TIME_EDIT” endpoint. It also details the mechanism for authentication which includes two hardcoded cookie values, one for regular users and one for “super” users.
With so many vulns, where do we begin? First, I took the function that generates the passcode and simply ran it. The perl script produces what is typically a 4-6 digit number that is loosely based on the current time of the system. Using this passkey we can log into the system as a “super” user. Once logged in, the options available to a “super” user include the ability to upload new firmware, change certain system options, and the ability to run a “ping-out” test.
Clicking on the link to the “Ping-Out Test” brings us to a page that seems right out of a CTF. We are presented with an input field that expects an IP address to ping. Entering a IP address, we see that the server seems to be running the ping command 5 times and printing the output. We quickly discover that arbitrary commands can be appended to the IP address using a pipe “|” character to give us command execution.
With proven command execution, the next step was to spawn a netcat reverse shell and began enumerating the file system in search of more vulnerabilities.
Having discovered a way to execute commands as an unprivileged user, the next goal was to try to find a way to escalate to root on the underlying system. We noticed a promising function in the “amegalib.pl” file called “run_SUcommand”. Since the current user had the ability to write files to the web root, I just created a CGI file that called the “run_SUcommand” function from the “amegalib.pl” file. After confirming that worked, I used netcat again to spawn a shell as root. After looking through the source code, I found this function is reachable as an authenticated user from the previously mentioned endpoint “/index.cgi?J=TIME_EDIT”. The vulnerable code is shown below.
The “set_datetime” function displayed above concatenates data supplied by the user and then passes it to the “run_SUcommand” function. Arbitrary code execution as the root user can be achieved by sending a specially crafted time update request with the desired shell commands as shown below.