It’s turn for the business IP cameras by Cisco to undergo Craig Heffner’s examination security-wise, in particular the popular PVC2300 and WVC2300 models.So I said, okay, D-Link is an easy target, as I mentioned – that’s why I picked them. Let’s move on to perhaps a more reputable vendor, like Cisco. The Cisco PVC2300 (see right-hand image) is kind of a mid-range business IP camera costing about $500. It, too, has a web server and it enforces authentication by using .htpasswd files which most people are probably already familiar with. So, basically, you put an .htpasswd file, or more specifically a symlink to a centralized .htpasswd file, in every directory that you want to be password protected (see leftmost image below). Looking through the firmware, every single directory in the web interface had a .htpasswd file. Except one.
The oamp directory did not have any .htpasswd file (see middle image above). What it had was a bunch of .xml files that were actually symlinks to this oamp.cgi binary. So I said, okay, let’s look at what this oamp.cgi thing does. As it turns out, it implements kind of its own little mini API that’s totally separate from the rest of everything else running in the web interface. So it expects you, when you make a request to it, to specify an action (see rightmost image above). And this action you can specify can be one of many different things including downloadConfigurationFile, updateFirmware and many others (see leftmost image below).
But they weren’t completely stupid – we’ll get to the stupid stuff later – because what they do is before executing an action they check to make sure that you’ve also provided a valid SessionID (see middle image above). If you have not provided a valid SessionID, the only action it lets you run is the login action (see rightmost image above). I said, okay, well, this in itself is interesting because they’re implementing authentication that’s totally separate from the authentication used everywhere else in the interface. So I started looking at how they actually handle this login action.
They expect you to specify a username (see leftmost image above) and a password (see middle image above), no surprises there. They then make two calls to this PRO_GetStr function. At this point, I have no idea what PRO_GetStr does, presumably it gets a string of some sort. But I do know that on the first call to this function they pass it two strings – Oamp and L1_usr (see rightmost image above). And on the second call, they pass Oamp and L1_pwd (see leftmost image below). The value returned for L1_usr is then compared against the username that you provided (see middle image below), and the value returned for L1_pwd is compared against the password you provided (see rightmost image below). So, presumably, this L1_usr and L1_pwd, whatever their values are, are the correct login for this oamp interface.Now, the only other place I could find in the firmware that actually referenced L1_usr and L1_pwd was in the configuration file (see right-hand image). These values are hard-coded in the device’s running config under the oamp section of the configuration file. You can see that l1_usr is set to string L1_admin, and l1_pwd is set to the string L1_51. And this is a real problem because this whole oamp interface and these hard-coded accounts are completely undocumented, so no one knows they’re there except for people who bothered to look at the firmware, which of course an admin is never going to do that. And even if an admin knew that these were here, there’s no way for the admin to change this, there’s no interface for the admin to go in and change these values. And the problem with having hard-coded secret passwords in your system and backdoors is that they don’t stay secrets for long. So we can use these backdoor accounts to exercise the login action and, sure enough, we get back a session ID (see leftmost image below). Now, as long as we send the session ID along with all of our other requests, we can invoke any of the other actions supported by oamp.cgi., including downloadConfigurationFile (see middle image below). And this gets us back – what appears to be base64 encoded data.
The problem is, if you try to base64 decode this – not working. You just get a bunch of junk (see rightmost image above). The reason for that becomes readily apparent when you look at the actual encode 64 function in the binary itself. They all are doing base64 encoding but they’re using a non-standard base64 key string. Luckily, it’s very easy in Python to substitute the standard base64 key string in Python’s base64 module with a custom key string like this (see rightmost image below).
And so, with a couple lines of Python we can easily decode the config, which gives us plaintext admin creds (see leftmost image above), which lets me see your server room (see middle image above). Now, the problem with viewing server rooms is it’s really exciting for, like, 10 seconds, and then you’re like: “Holy shit, this is boring!” So I went back and started looking at some more code, because that’s more exciting.Now, the loadFirmware action is one of the other actions you can invoke, and it’s actually very interesting because instead of uploading a firmware file to the device you specify a URL, and then the device goes to that URL, downloads, presumably, the firmware, and then flashes it (see right-hand image). The problem is, that URL that you specify is shoved into a command line string that’s ultimately passed to libc system, and hopefully everyone here knows that taking unfiltered user-supplied content and passing it to system is bad (see leftmost image below). You don’t do it. So we can easily do command injection through this parameter: just putting ;reboot; somewhere in your URL reboots the machine (see middle image above). And of course we can run whatever command we want at this point. This also affects the WVC2300 (see rightmost image above), it’s basically the same camera but with antennas. And there are hundreds of these cameras already out there online (see right-hand image) in hotels, obviously server rooms, and engineering companies who design things for the International Space Station (untold).