【蓝牙】CVE-2018-9359 process_l2cap_cmd_L2CAP_CMD_INFO_REQ未判断缓冲区边界造成信息泄露

补丁

  • https://android.googlesource.com/platform/system/bt/+/b66fc16410ff96e9119f8eb282e67960e79075c8

补丁修改的地方比较多,通过描述可以看到是在process_l2cap_cmd()里的一个越界读漏洞,补的都是同样的代码,说明这块代码缺少检查,这里只截取部分补丁代码

DO NOT MERGE Fix OOB read in process_l2cap_cmd

Bug: 74202041
Bug: 74196706
Bug: 74201143
Test: manual
Change-Id: Ic25f7f3777d0375f76cc91e4d129b1636f1c388d
(cherry picked from commit ff15adf5150527db1012b9f7777066522835e2db)
diff --git a/stack/l2cap/l2c_main.cc b/stack/l2cap/l2c_main.cc
index 83d1737..7c1ef48 100644
--- a/stack/l2cap/l2c_main.cc
+++ b/stack/l2cap/l2c_main.cc
@@ -320,8 +320,16 @@
 
     switch (cmd_code) {
       case L2CAP_CMD_REJECT:
+        if (p + 2 > p_next_cmd) {
+          android_errorWriteLog(0x534e4554, "74202041");
+          return;
+        }
         STREAM_TO_UINT16(rej_reason, p);
         if (rej_reason == L2CAP_CMD_REJ_MTU_EXCEEDED) {
+          if (p + 2 > p_next_cmd) {
+            android_errorWriteLog(0x534e4554, "74202041");
+            return;
+          }
           STREAM_TO_UINT16(rej_mtu, p);
           /* What to do with the MTU reject ? We have negotiated an MTU. For now
            */
@@ -332,6 +340,10 @@
                               p_lcb->handle, rej_mtu);
         }
         if (rej_reason == L2CAP_CMD_REJ_INVALID_CID) {
+          if (p + 4 > p_next_cmd) {
+            android_errorWriteLog(0x534e4554, "74202041");
+            return;
+          }
           STREAM_TO_UINT16(rcid, p);
           STREAM_TO_UINT16(lcid, p);
 ...

我们挑第一个补丁点来分析,对p + 2进行计算判断

找到代码对应的函数process_l2cap_cmd(),代码比较长,但是我们只需要关注关键的地方就行了,比如变量p的赋值,p来自上层函数

当接收到ACL数据包,HCI接口就会调用l2c_rcv_acl_data()来处理,再往上就不需要跟了,因为这里已经取出了p

补充一下STREAM_TO_UINT8()的实现如下,其它函数同理,p会往后移动

所以再回到process_l2cap_cmd(),仔细读一下代码,看所有的漏洞点,其实就是取了4字节长度的信令长度之后,又在switch/case里进行了取值,而此时未进行判断取值的位置是否超出缓冲区范围

PoC

其中SIGNALLING_CID的值为0x0001

以下是完整补丁,就是在所有在switch/case内部进行取值的地方加上判断

Last updated