了解固件源码但无法接触设备密钥的攻击者能做什么。
固件是公开的,因此数据包格式、长度和算法(X25519、HMAC-SHA256、HKDF)都为人所知。BLE 走开放空口,广播和 GATT 写入都可被监听。 固件里和空口上都不存在任何密钥。
密钥存放在哪里:
owner_secret (32 字节)——只存在于控制器的 NVS 和主人的手机里。配对时通过 ECDH X25519 派生,绝不以明文经过空口。guest_key ——在访客手机里。它经由安全的 WSS 通道随捆绑包从服务器下发,绝不走 BLE。| Attack | Defence |
|---|---|
| 伪造 FIRE | HMAC-SHA256。没有 owner_secret 或 guest_key,这就是 2128 次暴力破解——不可行。 |
| 伪造 TIME 写入 | 同样的 HMAC,覆盖 bleId + epochMs. |
| 重放监听到的广播 | 计数器单调递增;重复或回退时 HMAC 对不上。 |
| 重放监听到的 fire | nonce 环会作废用过的 nonce。 |
| 把控制器的时钟往回拨 | 棘轮:任何 TIME < 棘轮值都会被拒绝。棘轮存于 NVS,断电也不丢失。 |
| 使用过期的捆绑包 | 控制器运行过之后,棘轮至少等于最后一次真实时间。过期捆绑包的 validUntil 低于棘轮,fire 会因超期被拒。 |
| 把时钟拨快一年,把所有访客挡在门外 | 每次访客 TIME 写入最多 +24 小时。主人不设上限——主人是可信的。 |
| 在第一位主人之上再配对成第二位主人 | 配对后控制器把 owner_secret 存入 NVS,不恢复出厂设置就绝不再进入配对模式。 |
Requires: 一份有效未过期的访客捆绑包。
Action: 每次进入范围就写入一个向前跳 24 小时的 TIME。
Limit: 每次会话 +24 小时;若上次同步不足一小时,还需要一次新的 fire。十次造访后棘轮就提前了十天,其他合法访客的令牌看起来就过期了。
另一面: 攻击者自己的令牌也按同一个伪造时间判定,因此提前失效。
怎么办: 主人过来写入真实时间。棘轮不会回退,所以不动,但新的访客令牌会带着当前的 validUntil 签发,此后对所有人都有效。恢复只需在服务器上刷新有效期。
Severity: 在主人到来之前的暂时性拒绝服务。不算严重。
Requires: 在主人启动配对后的 90 秒窗口内,人身处控制器的射程之中。
Action: 在配对握手中替换成攻击者自己的 X25519 公钥。
Result: 控制器与攻击者而非主人完成配对。主人以为配对成功,却无法用手机打开任何东西。
当前防护: 只有时间窗口和主人的在场——主人看到配对未确认,会重来一次。
Hardening: 增加一个简单的验证码——控制器屏幕或串口上的四位数字——由主人在应用中确认。目前还没有这样的验证码。
Severity: 窗口很窄,既要靠近又要恰好落在那 90 秒内。实践中很难做到。
Requires: 能接触到控制器,并长按按钮。
Action: NVS 被擦除,owner_secret 被删除,控制器回到配对模式。
Result: 攻击者可把控制器配对到自己名下,主人失去访问权。
Defence: 把控制器装在受保护的位置——箱内、盖下。
Severity: 这跟把门口对讲机拆下来一样——不是密码学问题。
Requires: 物理接触并转储闪存,且安全启动与闪存加密处于关闭状态——目前正是如此。
Action: 读取存有 owner_secret 的 NVS。
Result: 设备及全部访客令牌完全失守。
Defence: 启用 ESP32 的安全启动与闪存加密(efuse,不可逆)。目前未启用。
Severity: 家用可以接受。重要场所需要安全启动。
Requires: 处于 BLE 射程内。
Action: 连上就不断开。NimBLE 只支持有限数量的并发连接。
Result: 只要攻击者占着名额,合法客户端就连不上。
当前防护: 只有 NimBLE 自身的超时。
Hardening: 加一个空闲超时:客户端 5 秒内没有完成有效的 FIRE 就断开连接。
Severity: 攻击者在附近期间的暂时性拒绝服务。
Action: 用垃圾写入轰炸控制器。
Result: 控制器将其丢弃并记入串口。其状态毫无变化,攻击者一走一切照旧。
有三处看着像防护,其实不是。与其让人依赖它们,不如把话说明白。
广播中的状态字节 带一个 16 位标签。它只够抵御空口上的偶然损坏,仅此而已: 有心伪造者几秒就能把 16 位穷举一遍。该字节只驱动卡片上的“开/关”指示,不授予任何权限, 所以标签保持短小——每多一个字节,都要在每次唤醒时消耗电量。
“仅限应用”的密钥 依赖编译进 APK 的一个密钥。谁把文件解包,谁就拿到密钥并能伪造证明。 它只是抬高了随手用网页客户端的门槛,仅此而已。这类密钥真正的管控是把它绑定到某台设备的 指纹上——这项校验在服务器上执行,不依赖应用能否守住秘密。
访客密钥的有效期 在 BLE 上由控制器自己保证:令牌带有期限,控制器也有时钟。 其他类型的对象则根本没有期限——密钥一直有效,直到主人吊销。应用并没有说相反的话;但若 将来界面上也为这些类型加上时间限制,那就必须在服务器上执行,而不是画在卡片上。
面向工业使用的标准加固:
对当下的使用场景这些都不算关键,但重要场所值得这样加固。