Blog: Vulnerability Advisory
Pwning the Nokelock API
I’ve been talking at some Infosec meet ups about a certain padlock, called the Nokelock. I need to differentiate this right now as there is a product called nokē, this is not about that. This is about a set of Chinese made padlocks called Nokelock from a company called Nokelock.
Most of the cheap Bluetooth padlocks on Amazon will be Nokelocks; they do a number of different formats in a number of different body types, sometimes with other unlocking devices, such as a fingerprint sensors. There are other brand names they get repackaged as, such as Micalock.
I’ve spent a lot of time trying to reverse engineer the BLE protocol for these as well as calling in our API deity and finding some interesting vulnerabilities. For which we tried to report for nearly six months, through multiple different mediums and got nowt but silence.
Before we get to the actual vulnerabilities, lets start this with a statement of what I can do if you own a Nokelock (or a clone) and use it:
- I can open your lock via BLE, so within a range of 10 m. I do not need to know who owns the account; I can do this just from the lock.
- I can pull all your information from the Nokelock database, this includes your email address and password hash.
- I can pull the GPS co-ordinates of your locks.
- I can de-register your lock and assign it to another account so you cannot open it.
Anybody still using a Nokelock?
Right, time to get into the mirky details…
All of the Nokelock locks follow the same BLE protocol. The protocol is implemented in an obfuscated Android app.
Like most BLE devices it uses one characteristics for communications: a TX characteristic which is written to and an RX data is passed via notify messages. The characteristic has the UUID of 000036f5-0000-1000-8000-00805f9b34fb; and has always been at handle 0x03 on every lock I’ve looked at.
Each packet passed either through TX or RX is 16 octets and follows the same basic pattern:
The above packet is the GET_BATTERY command which returns the current state of the battery. Here:
- 02010101 is a static command which means get the battery status
- 6e6eaebe is a token which can be obtained from the device
- 6c01231876670b42 is random padding to prevent replayability
The whole packet is then encrypted using AES and a static per device key to prevent trivial sniffing of the data.
There are a number of different packets that be used to communicate with the device to get battery status, change settings and unlock the device. To unlock the device, the process needs to get a token from the device, then call unlock with the token.
The get token command is 06010101, which then responds with 060207 and a four-octet token. Then an unlock command (050106303030303030) can be sent, this looks something like:
Client to Lock: GET_TOKEN
Lock to Client: TOKEN_RESPONSE
Client to Lock: UNLOCK
It’s a wee bit more complex than I’ve shown above as the whole packet is encrypted with AES encryption. Fortunately (for an exploit, less so if you use one of these), the key can be obtained from the API by two methods. All the API requests need a valid API token, which can be obtained by simply creating a user with a throw away email address.
Each padlock comes with a QR code, this can be placed in a post request to /newNokeLock/lock/getDeviceInfo:
The response is to dump all data about that lock, include the encryption key:
Note that this not only contains the encryption key, but it also contains the BLE advertising name, in this case O-W***, which can be searched using wigle.net.
If you don’t have the QR code, then you can search with the device’s MAC address. As the MAC address is used to communicate to the device over BLE, this can be sniffed whenever the BLE module has power (e.g. if you press a button on the device). This requires a call to the /newNokelock/lock/queryDevice endpoint:
This returns similar information as getDeviceInfo:
Note that both return an entry called lockPwd, set to 000000, if you look at the UNLOCK packet above you will notice six octets with a value of 0x30, i.e. ASCII “0”. This hints that there may have been a method of assigning a password to the lock, although the app code never used it and just sent six “0”s and there was no way that I could find of changing it.
So, if you tie these together you can encrypt the packet and unlock any device with one API call and a quick BLE conversation. A script that scans for these padlocks and unlocks all that it finds is on our github page here. This has a tendency to be a bit flaky, this isn’t the lock, this is just the way I programmed it in the script.
So, let’s get on to the fun bit: the API. We found a number of vulnerabilities in the API, for which we tried to disclose to the vendor, from January 2019, through many mechanisms, including email, phone and WeChat. We even tried to get a Mandarin speaker to talk to them
We had no response.
Unencrypted API Calls
So… First off, we have the endpoint for all traffic, a quick screen cap will show this up:
Yep, all traffic, including the user’s traffic is sent via the unencrypted HTTP protocol. Bearing in mind how easy and cheap it is to set up a TLS certificate nowadays this is just not acceptable.
IDOR in all API methods
It was noticed that the Nokelock API endpoint does not apply authorisation to its API. This could allow an attacker to read information about a user or lock, including email address, password hash and the GPS location of a lock.
It could also allow an attacker to amend these details, allowing the attacker to take control of the lock to unlock it or prevent the owner from using the lock.
A token is required to perform these actions, but the token is only checked to see whether it is valid, i.e. it only checks that the account is authenticated, not whether it is authorised. It is simple to create an account to gain access.
To prevent breaching the Computer Misuse Act, actions were only performed on accounts that were owned by the consultant.
Unsalted MD5 Hashes Used for Passwords
One API call returns the user’s password hash. This was noticed to be stored as an unsalted MD5 hash.
This is a cryptographically weak hash type that can be run through very quickly. As the hash is unsalted this makes it very possible to crack passwords if the database is breached or extracted through an IDOR attack, as described above.
It’s an old riff, but “Buyer Beware”; cheap products with flaky apps are often cheap because things have been cut back on the design and manufacture. This may also mean that appropriate testing on the product has not been performed and there may be security vulnerabilities.
Even though the idea of a Bluetooth padlock is a great one, I cannot advise anyone to use a Nokelock (or clone) and expect their stuff to be safe.
I’m ready to be pleasantly surprised if Nokelock try to fix the lock, but I cannot find any easy way of doing a firmware upgrade in the app.
We’ve been notified that Kerry Enfinger, Ph.D., from White Hat Defenses, had performed a similar reverse engineer of a Nokelock clone, called the Klic Lock, at the same time we were working on the Nokelock. He also obtained a CVE number (of CVE-2019-11334).
His code, can be found at https://github.com/whitehatdefenses/KlicUnLock.