Hacking Smart Devices for Fun and Profit

This paper was presented at DEF CON 28 (2020) IoT Village by Barak Sternberg

Executive Summary

  • Smart (IoT) devices are everywhere: connecting lights, AC, cameras and even heat-sensors.
  • They present a weak spot in which hackers can exploit to learn about internal network-configuration, change arbitrary controllers, and cause severe hardware & software damage.
  • In our scenario, thousands of HDL smart devices could have been exploited & remotely controlled in the wild.
  • 4 unique vulnerabilities have been found and presented here for the first time.
  • This unique attack scenario demonstrates the high-security impact of deploying IoT devices over any organization, especially when using dedicated IoT hardware and proprietary components which are interconnected and even remotely managed.
  • We followed the disclosure process and HDL Automation have fixed these vulnerabilities.

The author would like to thank HDL for their resolution and HDL Automation representative in Israel, Mr. Ofer Peleg for his operational guidance & support.

Introduction

“HDL Automation” is an international tech company, whose core business is in the field of smart home, buildings, hotels and other intelligent control systems. HDL have more than 10,000+ unique projects around the globe (Dubai, Ukraine, Peru and more). HDL projects include smart controllers for lights, windows, cameras, and other sensor activation.

Today, we offer a unique dive into the world of smart devices and automation. We focus on some of the core-servers which were used for configuring projects around the world and especially can also be used for remote projects’ configurations. We show how a hacker could remotely control/change arbitrary smart control systems and  their configurations. I would like to express my full gratitude & appreciation towards HDL as a security-aware company for their responsiveness & cooperation in quick disclosure and for fixing these vulnerabilities.

The Background Research: My Old Smart House

Our story begins In 2010, while my parents renovated our home. They were actually thrilled about the idea of installing a smart home controlling systems. So we did.

Unfortunately, as the software for configuring these devices was very expensive, they preferred to call only once for technicians for installing the devices without buying the software. Fast forward to 2019, now as the enthusiastic researcher that I am, I thought: “Why do we need to buy software?!” – Let’s do it ourselves!

I went over buying Adapter of Serial (RS485) to IP-Ethernet. Connected it to our main smart controller (It was a DyNet / Dynalite 2 controller, so I’ve used some partial datasheet which I found online). An example datasheet can be seen here:

The Channels (CH1,CH2,..) are usually connected to other circuits (e.g., relay that power-up the lights and other components).

The uP is the microprocessor which can probably be configured with controller commands (i.e: controlling lights/other devices with “shortcuts”. For example, defining scene #1 inside the processor as the logical name for triggering CH1 & CH2 and so on..).

The point of serial connection which I was focused on was D+/D- into my Serial-Server RS485 connection.

The problem was, well, I didn’t know what to serially send. Utilizing some old github repo documenting some of the relevant commands, I started sending commands. Here’s an example of sending a command to the controller:

# Sending RS485 serial data to Dynalite controllers.
from socket import *
s = create_connection(('10.10.100.254', 8899)) # Connecting to serial-server

p = DynetPacket()
p.toMsg(sync=0x1c, area=i, command=j, data=[255,0,255], join=255)
# p._msg contained the relevant raw-bytes of data to serially send.
s.send(p._msg) 

As our smart house was separated by areas (but not more than two of these), it made me think that it should be 0/1. Also, I changed the command to some known constant according to the github, which was related to relay/dimmer controllers. Unfortunately, nothing happened.

At this point, I thought, well, maybe we didn’t sent the correct packets (maybe areas are under different numbers & their commands are undocumented). Giving in to my father’s (Chief Electronics Officer at my parents home) and my own excitement, I then tried to brute-force several commands, for example:

for i in xrange(80):
  for j in xrange(126):
    if j in [102, 21, 125, 48, 49, 58, 30, 31, 32, 23, 24, 16, 17, 7, 8, 9]:
      continue
    p = DynetPacket()
    p.toMsg(sync=0x1c, area=i, command=j, data=[255,0,int(10 * 25)], join=255)
    s.send(''.join([chr(x) for x in p._msg])) #
    p.toMsg(sync=0x5c, area=i, command=j, data=[255,0,int(10 * 25)], join=255)
    s.send(''.join([chr(x) for x in p._msg]))

Well, this made ALL of our lights/windows (real-ones not the OS) open & close at the same time! Cool!

Well, it wasn’t a surprise that after my mom woke up at 6am from an activation of all lights in the house (auto-timer probably fired-up), we had to buy a new smart home system: HDL BusPro (Hooray!). This leads to our main course of research: the HDL smart devices.

The HDL System

Excited to see how our new smart home works, now with an Android app included as well, I encountered several public datasheets and presentations. Finally, I got an overview of the system.

The HDL system is composed of three basic components:

  1. HDL Dimmer or Relay Modules
  2. HDL IP-Serial Adapter
  3. HDL core-server.

First-time System Configuration

There are two relevant pieces of software in configuring and controlling HDL projects; the first is the desktop app, “HDL BusPro”, used mainly for configuration of buttons/controllers, and the second is the Android mobile app, “HDL On”, which is the main user interface for controlling your smart devices (you can also configure some of the other details in there as well). In short:

  1. Technician Laptop, “HDL BusPro” Software -> configuring the smart controllers in local-network (buttons, scenes, areas and more, usually it just configures the HDL IP-Serial adapter*).
  2. Technician smartphone, “HDL ON” App -> register a new user under some user email. A new “debug” user is also auto-generated for extra app configuration.
  3. Technician smartphone, “HDL ON” App -> login with the “debug” user.
  4. Technician Laptop, “HDL BusPro” Software -> Transmitting configuration to his smartphone in the local-network.
  5. Technician smartphone, “HDL ON” App -> Finish configuring devices, names and other details, and uploading configuration to a remote server. This server will be used for other users who want to control the smart home.
  6. Resident user smartphone, “HDL ON” App -> login with the original user (not the debug one). Download the uploaded configuration from the remote server. Now the user is ready to use and  fully control the  smart home.

*When the technician use the HDL-BusPro 2 software (desktop software) on your local network: The HDL IP Gateway (2) has a default gateway and ip configured with its own TCP/IP stack configured, so you can just directly connect to it using your PC and configure the HDL IP Gateway settings for controlling all other modules, e.g., relay/dimmer modules (3). The configuration includes which buttons operates which lights and how they work This configuration is further uploaded to other devices as remote controllers, e.g., to your smartphone.

The HDL ON App

    1. The login screen looks as follows:

    1. After login, all smart devices can be controlled with a single click within the app. The following shows possible controlled devices (left-picture) & lights-control interface (right-picture):

The smart home system can be also configured in either Local mode or Remote mode. It also appeared that when I connected with “HDL ON” to configure and control my smart home, it was actually connecting to a remote server (probably to get my current configuration).

Account Takeover #1: “Forget your password”

As I was enthusiastic about this server, I started with “Forgot Password” and clicked on it. I got this email:

This lead me to this URL:

https://*******.HDL****.com/****Zh**HdlCloudApi/Content/htmls/Forgetpassword.html?userRose=0&time=637248362584130174&email=[email protected]&lang=English

Cool, Let’s try  to replace the user email with another, for example: “[email protected]”.

Enter the link again with this:

https://*******.HDL****.com/****Zh**HdlCloudApi/Content/htmls/Forgetpassword.html?userRose=0&time=637248362584130174&email=[email protected]&lang=English

And it changed the password successfully! Cool!

What’s next? Let’s talk about “debug” users!

Account Takeover #2: Let’s Talk About “debug” Users

When you create a username, your account is defined by your email, e.g., [email protected]. As I said, it also auto-generates a debug user with the email of [email protected].

But does this email even exist? Well, of course not necessarily. This leads to account takeover #2:

  1. Victim opens account [email protected], and debug account: [email protected]
  2. Attacker registers a new email address at  [email protected].
  3. Attacker calls “Forgot Password” for the debug user, i.e: [email protected].
  4. Attacker changes the password of the debug account and can now control any smart devices and configuration inside the home itself.

Getting Devices OR 1=1

When a user accesses the following server, they can also use it to observe and explore other data and configurations as well.Here, I have observed some cool SQL-injection:

API endpoint #1: /api/DeviceByRegionList

How I triggered it? In the website interface, I clicked on the “devices section”, which allows access to a search area. You can send a query for searching devices by DeviceName/DeviceType among other parameters.   The following parameters (it will be a POST request with this as a message) gave me the first vulnerable endpoint:

{"RegionID":"734655", "DeviceName":"1' and 1=(select (database() like '%hdl%')) and '1'='1","DeviceType":"LightDimming"}

As you can observe, this also helped me to identify the server database  name. I did some blind sql injection over possible names (where getting results or getting none was confirmation for the “like” query inside) and finally extracted the DB name.

Extracting more data? Trying to get some more data failed, It seems like SQL injection was successful, but after many attempts I observed that data is parsed back when returned from the SQL query, e.g., parsed by the ASP, failed and returned 500 error response. As the returned data seemed to contain around 10 columns in some order (this is somehow the columns i’ve seen in the responses) the parsed order of the parameters and their types should have been exact for the ASP parser to let it through as a user response (i.e., string in the correct places, number in the correct ranges, etc).

This was quite a problem as there was around 10 columns with different values/ranges and others. Even if we assume we know all of the values, we still don’t know the order of the columns returned, and permutating over 10 options (> 3 million possibilities) seems like an extremely slowand hard way to find out.

API endpoint #2: /api/GetRoomBindingDevice

In order to trigger this, one would have clicked in the website interface on the “rooms” section and then on the search by binding-devices. The query contains, regionid (probably a region where the device is located) and of course the deviceName to search for (and also some other parameters). The returned value is a table with the filtered query results ordered by user-Id, regionid, DeviceName, etc.

Bypass ASP query results verification: In this scenario, I got back only 4 columns, so permutating over all possible permutations (4! = 24) – indeed was a great choice. This is my type of SQLi!

For example, returning all tables in the database:

{"Id":"4079","DeviceName":"1' union select 21057,20248,table_name,'1' from information_schema.tables; -- "}

Example response data:

{"SceneOBJId":XXXXX,"DeviceType":"XXXXX","DeviceName":"******area******","UserID":1},

{"SceneOBJId":XXXXX,"DeviceType":"XXXXX","DeviceName":"****device****","UserID":1},

{"SceneOBJId":XXXXX,"DeviceType":"XXXXX","DeviceName":"*****device**backup****","UserID":XXXXX},

{"SceneOBJId":XXXXX,"DeviceType":"XXXXX","DeviceName":"****firmware****","UserID":1},

{"SceneOBJId":XXXXX,"DeviceType":"XXXXX","DeviceName":"*****gateway****info****","UserID":1},

{"SceneOBJId":XXXXX,"DeviceType":"XXXXX","DeviceName":"****home*****info****","UserID":1},

{"SceneOBJId":XXXXX,"DeviceType":"XXXXX","DeviceName":"*****user****info***","UserID":1},

{"SceneOBJId":XXXXX,"DeviceType":"XXXXX","DeviceName":"*******user*****","UserID":1},

From this point onwards, extracting email, clients list, user list and probably passwords and others is a  quite straighforward.

More Observations

  • Gateway info can be extracted and leak internal network data (subnet and HDL controller parameters).
  • Firmware table? Can we change / make the firmware of our controller change if we change this column as well? Quite interesting…
  • Device Backup table – Maybe all configurations / configurations url are stored in there probably? Seems like a great place to change other victims configuration.
  • The passwords used to probably contain MD5(password), which is interesting.

(Un)fortunately, we didn’t have  chance to fully explore it as HDL responded quickly and fixed these security holes fast.

One thing is for sure, combining all the vulnerabilities found, hacking into other users’ remote smart home configuration and controlling internal devices (e.g., raising the AC temperature in the Server-Room to 30+ celsius 😈) is quite possible.

Generating “Cookies”: From SQL injection to Full User Authentication

Let’s look at how authentication is verified. It’s like cookies but in the headers instead: when a user is authenticated an authorization header is set. For example:

Authorization: YmFyYW...…..xxxx

After playing with it a bit, it seems like this header is: Base64(USER_EMAIL + “:” + MD5(USER_PASSWORD))

If we assume  MD5(USER_PASSWORD) is saved in the database, then from SQLi to full authentication can be as easy as:

  1. Attacker has a username with email=USER_EMAIL
  2. Attacker extracts username MD5(USER_PASSWORD) with the SQL Injection.
  3. Attacker generates their own Authorization header using the above formula.
  4. Attacker put this as its Auth header – and voila! We’re logged in!

Unfortunately, it wasn’t the case (or maybe changed after my security report).

Nonetheless, a practical takeover on all accounts can be as easy as:

  1. Extract all user emails using the SQL injection.
  2. Do ForgotPassword – for all the users, change the password to a known one.
  3. Login with this password / Generate your own authorization header to authenticate.

Wait, but this is not stealth! As the current user cannot authenticate now, right?

Stealth-mode Hacking

Well, we can do it another way: remember we have debug users. Used only for the configuration, they are capable of controlling and configuring all smart devices.

What an attacker can do is change the password only for the debug users.hat way, a full compromise of the system can be taken,but no one will notice in the short-term (as configuration is usually done only once and then users all switch to the normal users).

Security Implications

In this demo, we’ve been able to show that it is possible to hack a remote server which is used as a proxy for configuring office/home/airport smart devices. This presents serious vulnerabilities, especially because we were able to extract internal secrets (passwords) and network configuration, as well as control the smart device’s behavior. DOSing such devices to knock them offline is another possible attack vector, although not one we explored.

Info-leaks and Secrets Exposure

  • Internal network IP’s & subnet (HDL adapter).
  • Passwords can be obtained – (MD5-hash seemed to be used back then).
  • Emails & Full company names can be extracted (saved on the remote server as well).
  • Watching security cameras and other sensors as well (if configured correctly there as well).
  • Adding internal non-exposed IP HDL gateways –
    • Attacker can use the application to add new residence which in response enables the user the feature of configuring a new device for remote-connection.
    • If online exposed – attacker can auto-search and add these devices with the application GUI.
    • Even if not online-exposed – if you have some HDL devices unexposed in the internal network – a sophisticated attacker can add and use them using app gui (it needs to know HDL mac, but as the mac first couple of bytes usually contains company header this can be done with just brute-forcing the possibilities).
  • What sensors/cameras/ACs/lights the company have. Which type of security cameras and sensors can be very impactful as a physical attacker can also disable/know where cameras are placed using the remote app. This can be a way of preparing before a physical attack or breaking into some location or place.
  • Firmware versions / other smart devices configuration files data – All internal configurations, data on local devices, how they connect to internal HDL gateway seems to be possible to be extracted using the app as well.

Physical Damage / DOS

  • Removing/encrypting all configurations can be devastating for a big organization (and then maybe (and hopefully not and never) “blackmail” the organization paying for return the configuration back).
  • Changing passwords to all accounts to be blocked only known by attacker and removing configuration (encrypting it beforehand so attacker can also use this as a kind of blackmail).
  • Using AC to affect critical locations:
    • Servers room are at high risk, in that an attacker could increase the environment to a high temperature.
    • Start AC/electricity in wanted times & “waste” organization / household electricity.
  • A “hidden-trigger” attack:
    • Faking a light button to also close the AC in the other rooms as well in there.
  • Disabling & controlling other critical Sensors:
    • Disabling and/or watching security cameras.
    • Disabling sensors for leak/temperature/voltage/over-heat, etc.

RCE Potential Over Internal Networks

This is a potential outcome (but not fully investigated) of a configuration file change and/or sql firmware tables changes and such.

In short, the impact can be further extended if we could control the configuration files for internal smart devices (e.g., the backup-table in the SQLi) – and use it to exploit / make more requests to the internal network.

Examples

  1. Change the configuration file-url to http://127.0.0.1/internal_server -> may cause exposure of internal company servers to hacker requests.
  2. Configuration Exploit –  where the configuration will exploit other new vulnerabilities on the HDL ON android app – it exposes this android app as a great new internal attack surface for some remote cool attackers. This may lead to full internal network access as well.

Regarding HDL IP Gateway firmware, if the “firmware” table can also trigger and contain an update URL inside that server (which can be highly possible as well as the Gateways are going to use it as well for example in remote-mode connection) – then maybe we can update Gateway firmwares as well.

About the Impact in Local Mode

In the Local mode configuration, when in the local-network with the smart-devices, one can control and connect to these devices. Most of the security impacts, especially leaks of secrets and internal data, still stays in-place.

Even so, in some organization an attacker can utilize the hacked credentials, change the configuration of these devices using account takeover over the “debug” user, and then whenever the user updates the system configuration (for the HDL ON app) it will be given new malicious configuration which can be very helpful to an attacker trying to change internal config or gain more private data.