【蓝牙】CVE-2019-2209 未检测PIN码长度导致越界读造成信息泄露

补丁

  • https://android.googlesource.com/platform/packages/apps/Bluetooth/+/5a426f6ed5620a39388aa78ed1d01c465f47958c

CVE
参考编号
类型
严重程度
已更新的 AOSP 版本

CVE-2019-2209

A-139287605

ID

8.0、8.1、9、10

补丁描述使用PIN码前先进行长度检查,所以我们猜测PIN码长度是一个关键的地方

AdapterService: Check the PIN code length before using

The length is assigned by the framework. We should be better to check
again before using, and dropped any unexcepted input.

Bug: 139287605
Test: PoC, atest -t BluetoothInstrumentationTests:com.android.bluetooth.btservice
Change-Id: Ie2dd01e0b192e7ed1fe4b464618ddfa415dbf15c
(cherry picked from commit d6c84aa34962333448e0ed8e4ddbc9de8b73c5ac)
diff --git a/src/com/android/bluetooth/btservice/AdapterService.java b/src/com/android/bluetooth/btservice/AdapterService.java
index 508eacf..53cf723 100644
--- a/src/com/android/bluetooth/btservice/AdapterService.java
+++ b/src/com/android/bluetooth/btservice/AdapterService.java
@@ -2233,6 +2233,12 @@
             return false;
         }
 
+        if (pinCode.length != len) {
+            android.util.EventLog.writeEvent(0x534e4554, "139287605", -1,
+                    "PIN code length mismatch");
+            return false;
+        }
+
         StatsLog.write(StatsLog.BLUETOOTH_BOND_STATE_CHANGED,
                 obfuscateAddress(device), 0, device.getType(),
                 BluetoothDevice.BOND_BONDING,
@@ -2249,6 +2255,12 @@
             return false;
         }
 
+        if (passkey.length != len) {
+            android.util.EventLog.writeEvent(0x534e4554, "139287605", -1,
+                    "Passkey length mismatch");
+            return false;
+        }
+
         StatsLog.write(StatsLog.BLUETOOTH_BOND_STATE_CHANGED,
                 obfuscateAddress(device), 0, device.getType(),
                 BluetoothDevice.BOND_BONDING,

Android官方文档

  • https://developer.android.google.cn/reference/android/bluetooth/BluetoothDevice.html#setPin(byte[])

一般来说我们进行蓝牙连接,需要先输入一个PIN码,但是现在有的设备为了配对方便,会进行自动配对,自动配对使用的是反射调用setPin()

跟入源码,调用系统函数IBluetooth.setPin()

找到系统蓝牙组件源码,这里面先进行调用者的检查,然后调用AdapterService.setPin()

到达补丁函数,我并没有看出来这里的pinCode.lengthlen能不相等,因为len是由参数传入,回溯回去可以看到是pin.length,并且没有其它地方能够改变这个值,所以在什么情况下这两个值能不相等呢?

这里的AdapterServiceBinder定义如下,它使用的是AIDL,定义为IBluetooth接口,也就是说,这个Service里的方法可以通过Binder进行调用,所以这里的四个参数我们可控,就可以造成pinCode.lengthlen不相等

我们继续往下看代码,通过定义可以看到pinReplyNative()是Native函数

pinReplyNative()的Native实现如下,细节注释都写在代码里了

继续调用函数,此处将第四个参数pin_code转为bt_pin_code_t*类型,这里影响不大,做了个检查继续调用btif_dm_pin_reply()

先判断pin_len的长度是否大于PIN_CODE_LEN,通过宏定义可以看到PIN_CODE_LEN的长度为16,同时我们也可以推出len的值我们不可以改变,也就是说,补丁进行对比的两个值,有问题的是pinCode

在CVE官网有一段关于该漏洞的描述

所以我们跟入BTA_DmPinReply(),定义了一个tBTA_DM_API_PIN_REPLY*类型指针,accept一开始传进来就是true,调用memcpy()拷贝数据,p_msg->p_pin的长度是PIN_CODE_LEN,也就是16,上面已经看过源码了,如果pin_len为4,但是p_pin为16,所以就会多拷贝

我们来使用代码模拟一下进行调试

输出数据如下,可以看到打出了未初始化的数据

Reference

  • https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-2209

Last updated