Attacking Z-Way Controlled Home Automation Devices

I recently purchased a RaZberry board for one of my Raspberry Pis in order to begin my path towards home automation. I chose the RaZberry board, rather than a traditional Z-Wave controller, mainly due to its integration with the Raspberry Pi. This allowed me programmatic access to both the Z-Wave protocol as well as GPIO devices, which was important for some existing alarm sensors I have in my home. Z-Way is the communication protocol which abstracts Z-Wave specifics into an easy-to-use REST API. The Z-Way project even includes some basic web interfaces to get started, including a gateway management interface.

Shortly after installing the software and adding some devices, I began reviewing the web requests while managing my devices. Z-Way uses Angular to expose an API, which appeared to be consumed by both their web interfaces as well as their Android app. Below is an example request to turn my light switch on:

And below is the boring, yet important, response:

Immediately, I notice a serious concern: the Angular API requires absolutely no authentication. After searching around, I found the following FAQ on the vendor’s website:

Is there HTTP authentication in the HTTP/JSON API?

No, there is no authentication, your local network is supposed to be safe environment and protected from outside world using Wi-Fi passwords and firewalls. If you want to protect Z-Way using a password, you can always use projects like ngnix and other reverse proxy servers.

It was interesting to find that the vendor was aware of the issue, yet relinquished themselves of dealing with it. Understandably, most of the customers of this hardware are probably more technically inclined than the average user. Still, I felt it was a serious security risk that was, and still is, mostly unknown to customers.

While a user’s LAN is supposed to be somewhat safe, this doesn’t mean remote attacks are impossible. As I started to consider the possible attack methods against the API that could originate from outside the LAN, I remembered the response above. Note that the default CORS header on the Z-Way web server permits any origin domain by responding with  Access-Control-Allow-Origin: * . This makes a cross-origin attack fairly straightforward.

The below proof-of-concept shows how simple it would be for an attacker to embed malicious Javascript in his page in order to crawl through subnet hosts and attempt to trigger a Z-Wave operation. Since these requests are asynchronous, the victim would have no indication that they were being performed.

First, the script loops through the subnet hosts and attempts to POST to the API. It then determines whether the host was valid by looking for a returned status code other than zero. It’s unlikely that device 99 would exist on the victim’s controller, so the script then iterates through device IDs, in this case attempting to turn a light switch on. The risk is obviously greater when dealing with door locks, garage openers, or other sensitive devices.

Here is what a test run looks like on my network after a host has been identified:

The attack can get broader by trying more default subnets, or it can get more precise if the victim’s browser supports WebRTC. In the latter case, STUN requests can be made to determine the victim’s private LAN IP which can then be used to closely estimate the subnet range.

Securing a Razberry by requiring authentication is a little involved, but probably not difficult for most of its users. Another improvement would be to specify the allowed origin explicitly in the CORS policy. While this weakness in the Z-Way package is fairly targeted, it demonstrates the risk of liberal CORS implementations and how they can be exploited by attackers.

Share this: Facebooktwittergoogle_pluslinkedin
  • This is why we’re ultimately going to need a security broker for all this stuff:

  • Serguei Poltorak

    Thanks for showing us that there is a vulnerability even if we feel local network to be protected. Indeed, this is an issue and we are working on it.

    The “Access-Control-Allow-Origin: *” header is needed since we need web apps loaded from one host to connect to another host providing Z-Way API. Without this header the web app would be restricted by the browser.

    But I would like to mention that our latest API implies authentication and supports user management. So, hopefully this will not be a problem anymore. We plan to release new version this month.

    Z-Wave.Me R&D Team.

    • Randy Westergren

      Thanks for looking into it and addressing the vulnerability. I look forward to the update.

      As I mentioned in my post, “Access-Control-Allow-Origin: *” could be better improved by specifying the host instead of using a wildcard, e.g. “Access-Control-Allow-Origin: http://my-zway-server

      • Serguei Poltorak

        Unfortunately we don’t know in advance from which host the client will send us requests from. Many users uses their own Apache to store their web apps.

      • Albert J. Wong

        This is old, but I thought I’d point out that changing the CORS header here wouldn’t be super helpful anyways. If the threat model is assuming untrusted LAN, then CORS isn’t going to help protect the server. Even without that, the API falls under the simple request definition of CORS ( meaning there’s no preflight so while the browser would block rogue JS from reading the server result, the CORS change would in no way protect the server. Given that * is a solid choice for an API endpoint.

        • Randy Westergren

          Great point, you’re right: CORS allows identifying successful responses but the actual command API requests could be performed regardless (CSRF).