In August I decided to check out the cool new Internet Of Things. I bought a WiFi-enabled colorful LED lightbulb. It was a cheap Chinese one that costs almost nothing on Alibaba, but I paid probably around $50 on Amazon. It’s built by a company called Zengge. It turned out that my new lightbulb was a router, an HTTP server, an HTTP proxy, and a lot more. None of the vulnerabilities have been fixed as of the writing of this blog post. To help with testing out these vulnerabilities I created a Go library and command line tool. It can do a lot of what the Android app can do, but it can be used in scripts and by web servers. I strongly encourage someone to let people control their lights over the Internet and do a live stream of it.
Timeline
Reported – September 1, 2015
First response – September 1, 2015
Acknowledged the issue – September 1, 2015
First attempt at fix – September 14, 2015
First attempt defeated – 3 hours later
Second attempt step 1 (new version released) – ~ October 13, 2015
Checked up on them, still not done, giving 1 month notice – November 18, 2015
Published – December 19, 2015
How it works
The lightbulb is normally controlled with an Android app. It joins your WiFi network and can be controlled locally or over the Internet. Control over the Internet is disabled by default. That’s one thing they did right. There are three ports: TCP 80, TCP 5577 and UDP 48899. 80 serves a broken page. 5577 controls the ligthbulb. 48899 controls the router.
The router port allows you to do anything. You can flash the firmware, use it as a proxy, read the WiFi password, make it join a different network, etc. This port is normally exposed only to the internal network. The commands are of the form AT+
followed by the name of the command and optional arguments.
When you set up the lightbulb for control over the Internet it uses no encryption, but all it allows you to do is control the light, so it’s not that bad.
More information can be found in the README for the Go library.
Summary of Vulnerabilities
Threat model
This system has the same threat model as the WeMo baby monitor by Belkin. It assumes that all devices on the local network can be trusted.
I believe that this threat model is insufficient for the following reasons:
- People let others onto their network often. This is especially true for offices, restaurants, coffee shops, etc.
- Malware on any machine behind the network can use its privileged position to attack the rest of the network.
- My favorite law of computer security is “If it should never be on the Internet, someone has put it on the Internet”.
The following summarizes my findings:
Attacker | Control Lights | Replace Firmware | HTTP proxy | Read SSID + PASS |
---|---|---|---|---|
Local* network | Y | Y | Y | Y |
MITM on the Internet | Y | N | N | N |
Anyone on the Internet** | Y | N | N | N |
* The “local network” is anyone on the Internet if you expose the device to the Internet.
** This is the one attack that Zengge is trying to fix.
Local network attacks
The AT
commands are accessible from the network with the hard-coded password HF-A11ASSISTHREAD
. They can be used by simply sending UDP packets on port 48899.
Flashing
The AT+UPURL
command allows anyone with access to flash it.
AT+UPURL=url,filename
Reading the WIFI password
The AT
commands allow anyone with access to read the WIFI password.
AT+WSSSID AT+WSKEY
Use as a proxy
The AT+HTTPDT
command and other related HTTP commands can be use to make the lightbulb make requests on the attacker’s behalf, acting similarly to an HTTP proxy. This can give the attacker the ability to potentially make requests from behind whatever firewall or NAT the lightbulb is within.
Remote control
By design anyone who has ever been on the same network as the bulb gets access to the remote control feature. They just have to remember the MAC address of the lightbulb. This is a separate weakness from the “Remote control over the Internet” section. This weakness makes it impossible to revoke an attacker’s access to your lightbulb once they know the MAC address.
WiFi attacks
The AT+MDCH
feature configures whether or not the bulb will go back into wifi AP mode if it fails to connect to an access point in STA mode. It has a few options:
- off
- on – 1 minute
- auto – 10 minutes
- 3-120 – minutes to reset
The default is 10 minutes. This means that if you can take down the wifi it connects to for 10 minutes, you can force the bulb to enter AP mode. In most cases (unless the user configured it otherwise) the AP will be open and an attacker can connect and execute any of the local attacks.
Dangers of exposing the bulb to the Internet
If the lightbulb is exposed to the Internet, an attacker from anywhere in the world can get access to the user’s internal network vy performing the proxy attack described above. They can also geolocate them by using the MAC address of the router and looking it up in Wigle or some other wardriving database. Since they have the wifi username and password they can go to the location and connect to the same access point as the lightbulb. If these attacks are not sufficient, the attacker can flash the lightbulb with their own software that allows additional attacks.
Getting access to a user’s internal network opens the door to a large number of possible attacks. Describing them is beyond the scope of this document.
I tried scanning the Internet for Zengge lightbulbs with exposed management ports exposed and I found at last two. I don’t have a good Internet connection and I didn’t scan every IP, so there are probably way more than two out there. The information disclosed by the lightbulb allowed my to geolocate the owner of the IP address and know their WiFi SSID and password.
Remote control over the Internet attacks
There is no authentication that proves that someone is allowed to control a lightbulb. If you know the MAC address and the bulb is configured to listen to commands over the internet, you can control it.
The MAC address prefix that the lightbulbs use is ACCF23
, which is registered to hi-flying. The last 3 bytes of the mac address identify a unique device. These are 16777216 possibilities, so it would take on the order of a year to scan the entire namespace. However, the MAC addresses are very close to each other because they are assigned sequentially, so in practice you can limit your scan to only valid MAC addresses if you know one of the MAC addresses.
The first non-manufacturer byte of the mac address for a lot of the lightbulbs is 5F. Once you know that, you can easily do a scan of the 65536 addresses in a matter of hours.
This means that it takes very little time and effort to gain control over almost all lightbulbs with the “remote” feature enabled.
I tried this attack and got access to 541 lightbulbs. This was a few months ago, so there are probably even more now.
This attack is prevented in the Hue lightbulb by automatically discovering devices using the source ip. This is further strengthened by having a button on the bridge that users have to press to allow their device to become discoverable.
The commands from the phone to the server are “signed” using AES256. This is similar to Hue’s use of AES for encrypting connections from their bridge to their website instead of using public key cryptography. In this case it was much easier to get the AES key because it was in the Android app.
Local friend’s device takeover
When the phone queries the “Remote Settings” it receives a list of authorized devices for the currently light bulb. The api call is “GetAuthUserDevice”. This list contains the device id of every phone that is authorized. This is a problem because an attacker can use the device id to “log in” as the device. This makes the following attack possible:
- A has a light bulb LA
- B is friends with A and has light bulb LB at home
- B comes to A’s house and A lets B control LA
Now we have:
A, B -> LA
B -> LB
- A queries the list of devices that can control LA and gets B’s device id
- A can log in as B and control LB.
Failed fixes
Zengge responded to me, acknowledged the “Remote control over the Internet” attack and started trying to fix it. Their first attempt to fix it was to rotate their shared secret and obfuscate it in their app. They sent me the obfuscated app and within 3 hours I was able to get the new secret out of it. This discouraged them from trying to obfuscate it and they started working on a real fix.
They released a new version of the app that modifies the registration process slightly. It makes the app wait for the lightbulb to connect to their server first, then when the app connects to the server the server can make sure that the request is coming from the same IP. That makes this particular attack fail because the attacker doesn’t have the ability to make connections from the same IP address as the victim.
It has been two months since they’ve released the new app and almost four months since I reported the vulnerabilities. They have not enabled the check on the server side yet, so all of the attacks I described still work. Considering the fact that the impact of this vulnerability is not very serious – controlling strangers’ lightbulbs – I decided to just release my findings.
[…] Ataki na żarówki WiFi Zengge […]
Hi! Could you clarify something for me? You wrote that you found two lightbulbs on internet and than you got access to 541 more lightbulbs by their MAC addresses – so you found them by scanning local networks you had direct access to?
The two attacks are different. Exposing lightbulbs to the public Internet gives access to flash the firmware and/or do anything you want. I found 2 such lightbulbs on the Internet from my quick and incomplete scan. The other attack described under “Remote control over the Internet attacks” that gave me access to 541 lightbulbs was the MAC address guessing attack. This did not require any scanning. This way one can control only the lightbulb features, but not execute arbitrary code.
Sorry if that was confusing.
Thank you for reply. What I don’t understand is what guessed MAC address can give you, if you are not on the same IP network as lightbulb – you can’t find public IP from MAC, right?
Yes. The only thing it gives you is the ability to control the lightbulb features. You can change color, turn it on/off, etc.
Ahh, finally I got it – both lightbulb and you connect to the manufacturer server and you give it guessed MAC address of “attacked” bulb; it does not listen on Internet with “features” port open. OK, thank you.
Any chance we can get http://www.matrixssl.org/ to run on the FreeRTOS HF-LPB100 embedded in the bulb?
I haven’t tried the SDK yet. I don’t see any reason this wouldn’t work. Let me know how it goes if you try it.
[…] article, entitled “The many attacks on the Zengge WiFi lightbulbs,” published 20th Dec 2015 by Viktor Stanchev, details his analysis of a commonly sold […]
Hi,
I am searching for the good syntax to apply your commands in a batch file, i have to use it in an interface which only access to batch files or html pages, can you help me ?
Thanks !
I imagine you can use some combination of echo, xxd -r -p and netcat -u?
Hi,
In fact i succeded to compile your .exe command and it works fine for power on and off, get-state.
But i don’t get the syntax for set-color, and percentage of luminosity. I tried with #hex and all i could.
Unfortunately i can’t change the white warm/cold and the intensity. Any idea ?
Best regards.
Fabien.
Sorry, I never implemented that feature. It should be easy to add. You can parse a string like
xx%
and then turn that into white percent. The protocol level work is already done. Pull requests welcome ;)Hi,
I am not a coder, so i tried… but xx% gives an undefined error…
So i tried this : {
Use: “set-%light”,
Short: “change the intensity of lightbulb”,
RunE: func(cmd cobra.Command, args []string) error {
xxErr := fmt.Errorf(“please provide a percentage”)
if len(args) < 1 {
return xxErr
}
xxlight := control.ParsexxString(args[0])
if xx == nil {
return xxErr
}
controller.Setxx(xx)
return nil
},
},
But i don’t know how to define the controller :
go build zengge.go
command-line-arguments
.\zengge.go:228: undefined: control.ParsexxString
.\zengge.go:229: undefined: xx
.\zengge.go:232: controller.Setxx undefined (type *control.Controller has no field or method Setxx)
.\zengge.go:232: undefined: xx
Can you help me ?
Hi,
I have what I think may be one of these bulbs as the recommended app for it is the Magic Home app. I bought it from LED Hut about a year ago.
Most of your post has gone straight over my head so I’m just after a bit of advice. I presume l should just remove the bulb and bin it? Is there any risk that my home router has been compromised and is so should i give it a factory reset?
Any advice would be gratefully received!
Cheers,
Andy
For what it’s worth, I still use it. First of all there’s only so much damage a compromised lightbulb on your network can do. If your router doesn’t use a default password, all your communications are encrypted and secured and you are not running any vulnerable services on your local network, there’s nothing to worry about. Second, these attacks are not remote code execution except if you expose the lightbulb on the internet, so in the most common configuration where your lightbulb is behind a NAT router, it’s not possible. You have to think about security in terms of layers. Unless you are a high value target, it’s unlikely for this lightbulb to be of much value to an attacker. The attacks I describe are more amusing than threatening.
Thanks Viktor for the reassurance. I was a little concerned because I had enable the remote control feature of the bulb. And, having read the recent reports about the IoTs being used in botnets, I began to imagine my humble light bulb was part of a great conspiracy to take the Internet down! My router is protected by a unique password and the bulb is safely NATed behind it so I guess the world is a safer place :-)
Cheers again,
Andy
What exactly do you mean by “exposing to the internet”? Mine is connected to my router and that’s connected to the internet, does that count as exposing?
No, what that means is if you set up port forwarding from your router or somehow give the lightbulb its own public ip address that others can connect to.
Oh, but why would someone do that?
I don’t know. People seems to manage to put pretty much everything on the Internet somehow sooner or later. As I think I mentioned in the blog post, I did find multiple of these lightbulbs on the Internet.
Hi Viktor,
Congrats and thank you for your work. It is well detailed and documented. Unfortunately it is over my coding level. What I am trying to do is to send a simple on/off command directly to the bulb, without using a server. I have automated my house with Tasker and usually use the plugin send/expect to command my other devices. Do you think that it is possible to do so with the Zengge light?
Great work. I have the magichue LED controller that seems to be accessible via the same site/app.
I’m actually looking for the API to control it- do you know if it’s the same?
It’s probably similar, but not the same. When I was reverse engineering their android app, I saw that they had multiple similar protocols in it.