FlawOpen

flawopen.com/Teardowns/cve-2026-55269-android-snooplogger-heap-write

● CVE-2026-55269 · CVSS 7.8 · 高危
安全研究 · FlawOpen

CVE-2026-55269:Android Bluetooth SnoopLogger 堆缓冲区越界写入

CVE-2026-55269 是 Android Bluetooth SnoopLogger 的内存安全缺陷,可能导致本地权限提升。在特定开发者日志配置下,控制器发送的短数据包可能进入固定字符串写入路径,而缓冲区空间不足。Google 修正了反向的扩容条件,并限制了解析长度。

💡 通俗易懂的原理解析 (ELI5)

想象一名工作人员要在狭窄包裹上盖“PROHIBITED”印章。按理应先加一层包装,但反向的指示让最小的包裹跳过了这一步。修复会在盖章前为短数据包补足空间,并将记录长度限制在实际可用的包裹范围内。

核心概念与专有名词

SnoopLogger
Android Bluetooth 代码,用于过滤和记录捕获的 HCI 数据包。受影响路径需要启用文档所述的过滤日志配置。
HCI ACL 数据包
Bluetooth 主机与控制器之间的数据包。上游更改说明,在相应过滤器启用时,异常短的数据包可能触发缓冲区容量不足路径。
EXTRA_BUF_SIZE
在向过滤后的数据包写入固定“PROHIBITED”标记前增加的容量。修复确保短数据包获得这段空间。
CWE-20
输入验证不足。CISA ADP 将该问题映射到此弱点;具体缺陷是数据包缓冲处理中的大小条件写反。

框架映射

  • FlawOpen 对 MITRE CWE 的概念性映射;没有厂商或 CVE 记录将此弱点编号分配给本研究演示。 CWE-20

根本原因剖析 (Root Cause)

Android 2026 年 10 月安全公告将 CVE-2026-55269 列为影响 Android 16、16 QPR2 和 17。NVD 当前显示 CISA ADP 的 CVSS 3.1 评分为 7.8(高),而 Google 公告将 System 条目标为严重;这是不同的严重性评估。在上游 Bluetooth 提交中,SnoopLogger::FilterCapturedPacket 会进入 PBAP/MAP 过滤路径,随后 PayloadStrip 可能写入固定标记 PROHIBITED。易受攻击的条件 packet.size() + EXTRA_BUF_SIZE > DEFAULT_PACKET_SIZE 会让短数据包跳过扩容,从而容量不足。修复将运算符改为 <=,并将 length 限制为 packet.size() + PACKET_TYPE_LENGTH。提交说明恶意 Bluetooth 控制器可发送短 HCI ACL 数据包,但必须启用相应开发者选项和 SnoopLogger 过滤器。这不是可从互联网访问的 Android 服务。本文不提供利用载荷。更新何时到达设备取决于厂商。

攻击执行流程分解

步骤 1

特定日志配置处于启用状态

提交描述了启用开发者选项中的 Bluetooth SnoopLogger 过滤,并将 PBAP/MAP 配置设为 magic。不要将该路径泛化为所有 Android 设备或默认配置。

步骤 2

控制器提供异常短的数据包

恶意 Bluetooth 控制器可以向过滤捕获路径发送短 HCI ACL 数据包。本文省略数据包字节和操作性触发细节。

步骤 3

反向条件跳过必要扩容

FilterCapturedPacket 使用了 >,正确条件应为 <=。短数据包没有获得 EXTRA_BUF_SIZE,后续过滤却可能把 PROHIBITED 写入空间不足的缓冲区。

步骤 4

上游补丁恢复缓冲区边界不变量

修复为符合条件的短数据包补足空间,并将解析长度限制在可用数据范围内。厂商提供后,请安装安全补丁级别为 2026-10-01 或更高的更新。

源代码对比:漏洞与安全实现

此代码片段遵循 Google 的公开更改:反转比较条件,让短数据包获得标记所需的额外容量,并将解析长度限制为实际可用大小。提交还加入了短数据包测试。这是上游修复的精简说明,不是可直接用于设备的独立补丁;请安装厂商提供的安全补丁级别 2026-10-01 或更高版本。

源码摘录: snoop_logger.cc

存在漏洞的实现
if (packet.size() + EXTRA_BUF_SIZE > DEFAULT_PACKET_SIZE) {
  // 应为较短的数据包预留过滤标记所需空间。
  packet.resize(packet.size() + EXTRA_BUF_SIZE);
}

// 随后 PayloadStrip 写入固定标记 PROHIBITED。
加固后的安全修复
if (packet.size() + EXTRA_BUF_SIZE <= DEFAULT_PACKET_SIZE) {
  // 在过滤前填充符合条件的短数据包。
  packet.resize(packet.size() + EXTRA_BUF_SIZE);
}

// 确保解析出的长度不超过调整后的数据包长度。
length = std::min(
    length, static_cast<uint32_t>(packet.size() + PACKET_TYPE_LENGTH));

工程与系统安全加固清单

参考来源