Blog: Vulnerability Advisory

The not so ultra lock

David Lodge 27 Jun 2019

This post couldn’t have been written without @evstykas and @cybergibbons.

I became aware of the Ultraloq from U-tec a few months ago. For a room door lock it has a range of what look like really good features:

Ultraloq UL3 smart lever lock is designed to be “Real Keyless”. You are free to use fingerprint, code or key to unlock. You have full control of all guests’ access and you can simply share a code to let visitors in when you are not there.

…but can it deter or even repel a determined attacker?

TL;DR

From the mobile app API we can recover personal data from the users account, often enough to locate the house and lock.

From the API we can reset the lock PIN, locking the user out, or allowing us to unlock their door.

We can physically visit a lock and trivially unlock it over Bluetooth.

The physical lock is easy to pick as well.

BTW this isn’t all my own work, @cybergibbons and @evstykas contributed too.

Obtainable BLE encryption key

The BLE packet is encrypted to prevent easy sniffing and replay of a control packet.

The key is constructed of two parts:

  1. A token obtained from the lock
  2. A static salt

These parts are concatenated together to produce a 16 octet byte array, the appropriate size for an AES key.

The static salt can be obtained from the app and is equivalent to the string;

Anviz.ut

The token can be obtained by querying the BLE characteristic with a UUID of 00007220-0000-1000-8000-00805f9b34fb and a handle of 0x22. This can be obtained by just reading the characteristic:

As the code for the lock is a 6 digit integer, this makes it possible to attempt a brute force attack against the lock through the BLE interface.

API auth? Nope

API has no authentication at all. The data is obfuscated by being base64 twice but decoding it exposes that the server side has no authentication or authorization logic. This leads to an attacker being able to get data and impersonate all the users. This leads to a full compromise of all the locks that are connected to the cloud service.

This attack affects all endpoints of the “ultraloq” mobile app.

Example requests and responses:

GET USER INFO

POST /index.php/user/get_userinfo_ex HTTP/1.1
Content-Length: 107
Content-Type: application/x-www-form-urlencoded
Host: app.service.u-tec.com
Connection: close
User-Agent: thinkandroid/1.1 (http://www.thinkandroid.cn)
Accept-Encoding: gzip, deflate

data=ZXlKd1lYSmhiWE1pT25zaWRYTmxjbWxrSWphMDRiNGIxZGJlZjI3Mzhlb2lNelkyTWpJaWZYMD0K%0A&token=8453661149ac73b2

We can decode the data parameter with the double base64 way too:

ZXlKd1lYSmhiWE1pT25zaWRYTmxjbWxrSWphMDRiNGIxZGJlZjI3Mzhlb2lNelkyTWpJaWZYMD0K%0A ->
{"params":{"userid"36622"}}

We can see that the userid is an integer that we can enumerate on.

GET USER LOCKS

POST /index.php/user/get_userinfo_ex HTTP/1.1
Content-Length: 107
Content-Type: application/x-www-form-urlencoded
Host: app.service.u-tec.com
Connection: close
User-Agent: thinkandroid/1.1 (http://www.thinkandroid.cn)
Accept-Encoding: gzip, deflate

data=ZXlKd1lYSmhiWE1pT25zaWRYTmxjbWxrSWphMDRiNGIxZGJlZjI3Mzhlb2lNelkyTWpJaWZYMD0K%0A&token=8453661149ac73b2

We can decode the data parameter with the double base64 way too:

ZXlKd1lYSmhiWE1pT25zaWRYTmxjbWxrSWphMDRiNGIxZGJlZjI3Mzhlb2lNelkyTWpJaWZYMD0K%0A ->
{"params":{"userid"36622"}}

This means that we can potentially enumerate all locks of all users. In the response body of this request we can retrieve the BLE encryption key and potentially all the users pins. We can also change those values. The easiest way to a full compromise is intercept the login process and change the userid of the logged in user. After that the app will function as the user with the userId that we have provided has logged in , providing full control over all of their locks.

Can I pick it? Yes you can

The device allows for a thin pick to be inserted in to the body and used to shim the internal mechanism to open the lock manually.

Figure 1- picking the lock

The Ultraloq has a back-up key lock in the base of the device – in case the electronic side fails. And that lock is not a good one – an amateur can reliably open them quickly and easily, both with single pin picking and raking. It’s certainly not up to the standards we would expect to see on an external door.

It’s also possible to insert a thin tool (a modified lock pick) down the side of this lock and manually actuate the latch. A simple bypass that should be protected against.

Good luck fixing these with a firmware update.

 

Unencrypted storage

If access can be gained to the back (“secure side”) of the device, then it can be taken apart in a matter of minutes and access can be gained to an external SPI flash chip. This chip can be read fully in less than a minute using a simple Raspberry Pi and a SOIC-8 clip.

Figure 2- SPI Flash chip (ignore the wires)

Once dump, the flash memory was found to mostly be blank (set to a default value of 0xff), but some data areas were found:

Address Data Contained
0x10000 User data and their PINs
0x20000 User data and their raw fingerprint data

The data at 0x10000 follows a similar format to that used in the BLE packet. Each entry consists of 16 bytes:

00 00 00 F0 User number, stored as a 4 octet little endian value (in this case 240)
3F 42 0F PIN, stored as a 3 octet little endian value (in this case 999999)
60 00 00 00 00 Unknown (appears to be user’s role)
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF Blank data
D9 DF C1 21 Unknown (likely to be a checksum)

The data at 0x20000 is unknown, but follows an obvious pattern with three chunks of data occupying 0x400 octets of data.

Conclusion

While U-tec did eventually fix the API, they have still not addressed the BLE issue to prevent brute forcing, and nor have they warned customers of the risk of bypassing the mechanical back up lock.

Not great U-tec, not great.

Disclosure timeline

2019-04-09 – First contact with U-tec to report vulnerabilities

2019-04-09 – Quick reply from U-tec requesting clarification

2019-04-10 – PTP supply clarification

2019-04-12 – PTP supply further clarification on request

2019-04-15 –  Email from U-tec saying “…we will fix that issue quickly”

2019-04-16 –  PTP ask again that the API be taken down

2019-04-22 – Reply to say that U-tec will have the issue fixed by w/c 29th April, and a request for extension to disclosure

2019-04-24 – Request for clarification of the location issue

2019-04-29 – PTP ask for an update

2019-05-01 – API flaw fixed, PTP ask when BLE issues will be fixed

2019-05-13 – PTP again ask when BLE issues will be fixed

2019-05-28 – U-tec request another month to fix BLE issue

2019-06-18 – PTP request an update and for U-tec to provide a comment for the disclosure blog post. No reply to date