TL;博士
FingerTec是一家提供考勤、门禁硬件和解决方案的公司。MWR发现了其访问控制生物识别设备中的漏洞,这些漏洞可被滥用以实现以下目的:
- 创建后门管理用户帐户
- 提取设备上所有用户的列表,包括pin和RFID号码
- 强制通信密钥(消息身份验证密钥)-如果已设置
- 执行自定义命令
- 短时间开门
所有这些都可以由对手通过TCP/IP网络直接与设备通信来实现。通信使用未加密的UDP数据报发送,使用未记录的专有消息传递协议。
对手可以利用这些问题进入受此类系统保护的建筑物的限制区域和/或影响任何审计跟踪的完整性。
介绍
对于大多数传统的访问控制系统,读卡器(无论它们是RFID、生物识别、PIN pad等)都通过串行连接连接到集中系统中的主控制器。然而,控制器完成所有的处理,控制解锁和锁定门,并保持审计跟踪。
FingerTec系统工作方式不同,逻辑和处理由设备执行。当用户在FingerTec设备上被验证和授权访问时,一个信号被直接发送到电源,然后电源打开门。FingerTec设备从中央服务器下载授权用户数据库并将其存储在本地。
2016年1月12日(Packet Storm),我发布了一条公告,披露了设备的硬编码默认根密码。这是在我对它的攻击面进行初步研究时发现的。同时我还对用户数据库(user.dat)格式进行了反向工程。数据库包含用户名、id、pin和RFID号码。当时我无法逆转网络通信中使用的专有UDP协议。
从那时起,我有时间重新审视这项研究,这篇博客文章详细介绍了所采取的方法、取得的成就以及发现的问题。
了解消息传递协议
为了应对理解协议的挑战,我开始有系统地执行功能,以便触发可以记录在完整数据包捕获中的网络通信。
发现服务器试图通过TCP端口4370与控制器设备连接。然而,在评估的设备上,此服务没有监听,因此连接可能会失败。然后恢复到使用UDP与设备通信,将数据报发送到端口4370。服务器总是发送相同的8字节初始化数据包:
设备的响应是相似的,但每次都不同。在比较了几个不同的包捕获之后,我发现包的前8个字节是命令头,之后发生的任何事情都是数据或参数。
从服务器接收到初始化消息后,设备将使用响应代码、校验和、会话ID和序列号进行回复。下面是一些例子。
我花了很长时间才发现第二组数字是一个校验和。我很幸运,发现有人在GitHub上发布了ZK软件API的源代码,GitHub还可疑地通过UDP 4370端口进行通信。读了一遍之后,我确定这是FingerTec设备使用的相同协议,它包含了如何计算校验和的源代码。
我编写了一个概念证明(PoC)工具,它允许我生成基本通信,以便开始映射各种命令。然而,数据包捕获并不容易使用。原始的UDP数据是丑陋的,这使得很难识别对于庞大的数据包群的任何意义。捕获还包含多个同时会话。从视觉上看,这使得跟踪数据包顺序变得困难。为了使我的生活更简单,我编写了一个Python脚本来解析PCAP文件,按会话对数据包进行排序,然后以可读性更强的格式打印所有内容。然后,绘制一些基本命令就容易多了。
使用软件将用户复制到设备时获得以下捕获:
在之前对数据库格式进行了反向工程之后,我对大块二进制数据很熟悉。这些是二进制数据中的数据库行。
布局如下:
如果忽略第三行,因为它的格式不正确,则数据的布局如下:
- 前两个字节是内部ID(小endian)。这通常与用户ID相同,但并不总是如此。例如,D207解包到2002。如果设置为00 00,则表示用户被禁用。
- 这是ASCII中的PIN。如果没有密码,您将得到00 ff ff 5b条目。如果不使用针的所有5个字节,则使用填充字节(00)。
- 这是ASCII中的用户名。如果用户名小于8字节,则使用字符串终止符(00)。字符串最多可以是8个字节。
- 这是一个4字节的小尾数整数,表示RFID号。
- 不知道这是什么。
- 这是一个4字节的小尾数整数,表示用户ID。
- 介于1和2之间的未标记框是特权级别,07表示管理用户,00表示未特权用户。
重放完全相同的数据包序列会再次创建相同的用户。可以修改用户名和PIN值并重新发送消息,以插入新用户(未经身份验证)。
下图显示了从设备请求用户列表时生成的捕获。服务器接收包含用户名、用户id、pin和RFID号码的完整用户数据库。
如上所示,在前4个字节的数据之后,消息是整个数据库的逐字节转储。我们对协议的理解以及设计发送到此类网络中设备的消息的能力意味着我们能够:
- 在设备中创建用户
- 发现设备中所有用户的所有详细信息
这些问题已向供应商披露。在披露期间,通信MWR被告知FingerTec对设备上的大多数软件堆栈没有任何控制权。该设备是由一家名为ZKTeco的公司为FingerTec生产和品牌化的。因此,发现的问题并不是与FingerTec隔离的,而是可能影响所有基于ZKTeco和ZKTeco的TCP/IP设备。
还发现这些设备确实支持身份验证。虽然设备手册建议不要设置代码,但软件手册建议设置5位数字。
这称为通讯键。它可以设置为0到999999之间的数字。当设置为0以外的任何值时,每个请求都会得到一个2005的响应代码,该代码转换为“需要身份验证”。
分析了一个包含多个使用Comm密钥成功认证的包捕获。发现每个认证响应的认证码都是唯一的。由于Comm密钥是相同的(数字“2”),因此两者之间的唯一区别是会话密钥。
在四处搜索并没有找到任何关于实际代码是如何生成的信息之后,在尝试了各种32位校验和/哈希函数以及各种“2”+session_key的排列没有成功之后,需要一种新的方法。服务器软件已加载到x86dbg中,并试图标识负责散列Comm密钥的函数。
在执行目标函数时,动态加载和卸载了许多dll。发现DLL“comms.DLL”是一个很好的开始位置。经过多次运行和不同断点的设置和分析,确定了生成密码的函数。
函数执行以下操作:
- 按位反转通讯键整数。因此0b11001100101010101111100000000变为0b00000001111110101010100110011(第1080-108E行)
- 添加会话ID(第1090行和第1094行)
- 将结果与0x4F534B5A(第1098-10AC行)进行异或运算
- 将前两个字节与后两个字节交换(第10B1-10BB行)
- 调用系统调用GetTickCount,它根据系统启动和运行的时间返回一个整数。然后将字节1、2和4与GetTickCount结果的最后一个字节进行异或运算。
- 最后,该滴答数移到字节3中。
最终结果是实际的密码:
Wireshark证实了这一点:
第5步和第6步只是为了给散列添加一点随机性,并且是完全可选的。你不能做第5步,用00替换位置3,它也能正常工作。
散列机制非常弱是因为键空间非常有限。它最多有3个字节的密码空间,可以达到2^24,或者最大可能有16777216个密码。除此之外,软件允许的最大数量为999999。那就意味着要列举10^6个或大约100万个密码。也没有暴力保护或速率限制。
了解使用中的算法和专有协议可以让我们自动执行密钥空间的暴力操作。工具具有以下功能:
- 创建后门管理用户帐户
- 提取设备上所有用户的列表,包括pin和RFID号码
- 暴力强制通信密钥-如果设置了
- 执行自定义命令
- 短时间开门
按顺序进行,需要不到3天的时间来耗尽AC900的所有可用键空间,因此平均的暴力尝试应该是其中的一半。多线程暴力强制锁定设备。R2s的威力要大一点,使用暴力的速度应该快一点,但是在其他的研究途径中,这些设备已经被堵住了,所以我们无法测试。
影响范围
据Shodan说,这些设备中有4000多台在互联网上曝光。这些设备主要集中在美国和中国,但在世界其他地区有着广泛的应用。
据ZKTeco称:
“每天约有180个国家/地区的2.2亿多人使用ZKTeco产品。ZKTeco已成为安全和生物识别行业公认、备受尊重和追捧的品牌。”
建议
- 不要在公共互联网上托管任何物联网设备。
- 使用这些设备可以使用的最大通信密钥。
- 如果您的网络上有这些设备,请确保它们是完全分段的,并且只能从管理服务器访问。他们不需要能够与公共互联网或你的内联网上的任何其他东西交谈。
- 更改根密码。
披露
披露时间表如下:
- 2016年7月8日-首次披露
- 2016年7月20日-使用密码信息更新咨询
- 2016年8月2日-联系ZKTeco
- 2016年8月28日-修复后发布给FingerTec开发者
注意,修复的性质没有透露给MWR,一个带有实现的修复的设备还没有被分析。因此,到目前为止,修复的有效性还不得而知。