智能门锁与 BLE 设备安全 Part 3: 耶鲁智能门锁的简单测试(上)
2021-03-29 14:56:00 Author: paper.seebug.org(查看原文) 阅读量:141 收藏

作者:Yimi Hu & Light @ PwnMonkeyLabs
原文链接:https://mp.weixin.qq.com/s/8t8s9UOVeVht9yqkVnaG0g

1.简介

我们在前面两篇文章中简单介绍了BLE协议栈,并对一款智能灯泡进行了分析。本篇中,我们选择Yale品牌的一款智能门锁进行安全测试,一起来研究一下这款锁是否存在安全问题。

我们测试的智能门锁如图1.1所示,这款门锁有一个可拆卸的蓝牙模块,该模块配合Yale厂商提供的一款名为Yale Bluetooth Key的app,可以实现蓝牙开锁功能。

图片

图1.1 智能门锁

首先我们需要介绍一下这款智能门锁的使用方式。和上一篇的智能灯泡类似,正常情况下,使用门锁前需要先在手机app中绑定门锁,如图1-2所示

图片

图1-2 绑定门锁

绑定之后,如果门锁在手机的蓝牙通信范围内,app就会自动向门锁发起BLE连接,连接成功后,即可点击开门按钮打开门锁,如图1-3所示。

图片

图1-3 连接及解锁

2.分析过程

2.1 App初步分析

既然智能门锁也可以由app控制,那么我们参考上一篇的研究思路,首先查看app日志,尝试获取BLE通信的内容。然而当我们用Android Killer查看日志时,发现Yale Bluetooth Key这款app没有输出任何日志。通过对APK进行简单的逆向分析,我们找到了关于输出日志的部分代码,如图2-1所示:

图片

图2-1 App Log代码

ILog类负责输出日志,但是这个类中所有的Log函数均为空,要解决这个问题有两个方法:一是修改app的smali代码并重新打包;二是用Hook的方式直接打印这些Log函数的参数。本篇我们采用了第一种方法,第二种方法将后续文章中介绍。

可以使用Android Killer完成修改smali代码并重打包等工作。将app反编译之后,找到ILog.smali,在需要修改代码的地方点击鼠标右键即可插入代码,如图2-2所示,这里我们在插入Log代码的同时,也在AndroidManifest文件里添加了android:debuggable标签,在《耶鲁智能门锁的简单测试(下)》会提到它的用处。

图片

图2-2 修改app代码

2.2 通信数据分析

修复了日志输出代码之后,我们就可以看到BLE通信内容了。当门锁在手机附近时,app会自动向门锁发起连接,连接过程的日志如图2-3:

图片

图2-3 手机连接门锁时的日志

根据日志中的关键字“_72_AUTHENTICATION_EVENT”和“send 72ACK”进行代码回溯,找到关键代码如图2-4所示:

图片

图2-4 Authentication数据包相关代码

结合我们在本专题第一篇文章中介绍的Android系统BLE接口的相关知识。图2-4的处理流程是:

a. 当回调函数onCharacteristicChanged或onCharacteristicRead被调用时,会发出一个名为“com.irevo.bluetoothkey.regnosleep.ACTION_DATA_AVAILABLE”的广播,其中携带着接收到的BLE消息内容。

b. 相应的广播接收器接收到这条广播后,将其中的BLE消息内容取出,交由函数handleLockStatus处理,这里输出了图2-3的第一条日志。

c. handleLockStatus函数中输出了图2-3的第二条日志,BLE消息由encodeCounter函数处理完成之后,交给send72Response函数。

d. send72Response将encodeCounter的处理结果封装为ACK帧,也就是图2-3的第三条日志的主要内容。在send72Response函数的最后调用了writeCharacteristic将ACK帧发送给门锁。

可以看到,这是一次完整的BLE通信的收发处理流程,结合日志中的AUTHENTICATION关键字,我们推测这是门锁与手机建立BLE连接时的身份认证过程。这一过程非常简单,门锁向手机发送一组数据,我们暂且称之为Authentication Request,Request经encodeCounter函数处理后得到Payload,Payload在send72Response函数中封装成Authentication Response发送给门锁,如果手机通过了身份认证,就可以发送控制指令控制门锁的打开与关闭了。

接下来,我们重点分析手机如何处理Request生成Payload。encodeCounter函数的参数counterData就是门锁发来的Authentication Request,图2-5展示了 counterData的处理方式:counterData被分割成若干个字节,每个字节都与key1~key6中的某一个相加,相加的结果放在c1r1~c3r4中。具体过程请看图2-5。

图片

图2-5 Authentication Request的处理

c1r1~c3r4最后重新拼接成字节流形式,作为encodeCounter的返回值,也就是手机返回给门锁的Payload,如图2-6所示。

图片

图2-6 Authentication Response拼接

已知Payload是由Authentication Request与key1~key6相加得到的,Request是门锁发送来的,那么key1~key6的来源是什么呢?如图2-7所示,encodeCounter函数首先读取了this.keyModel.productInfo变量,然后将productInfo变量逐字节存储到 key1~key6这些变量中。

图片

图2-7 Authentication Key的处理

key1~key6来源于productInfo,那productInfo是哪里来的呢?我们继续回溯,可以发现productInfo是在门锁与手机进行绑定时,由门锁发送给手机的,在完成绑定后,将productInfo存储在数据库里,每次使用时直接读取数据库即可。回溯过程可以参考图2-8。

图2-8 productInfo的处理

上图中,箭头方向表示数据的流动方向。经过多次实验可以发现,门锁绑定不同手机时发送的productInfo是相同的,这应该是门锁出厂时就烧录在flash里的一组固定密钥。

经过分析,我们可以确定以上身份认证机制中存在这样一个问题:门锁对手机进行身份认证的算法是加法运算,如果我们能嗅探到Authentication的Request和Response两个数据包,就能直接通过减法运算得到productInfo,从而通过门锁的身份认证,控制门锁。

3.小结

本篇是我们对Yale门锁研究的上篇,在上篇中,我们主要对Yale门锁的app进行了分析,最终发现在门锁与手机的BLE通信机制中存在一些问题。在接下来的下篇中,我们会引入一个USB dongle用于对BLE通信进行嗅探,并利用本篇中发现的问题,通过嗅探而来的数据,计算得到productInfo,最终实现在任意手机上进行未授权开锁。


Paper 本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/1529/



文章来源: https://paper.seebug.org/1529/
如有侵权请联系:admin#unsafe.sh