【NFC】CVE-2018-9584 nfc_ncif_set_config_status未检测长度越界读写

漏洞原理总结:NFC漏洞,在函数nfc_ncif_set_config_status()里直接将缓冲区数据作为长度进行拷贝操作,造成uint8_t类型溢出定义长度125位的数组

官方描述:In nfc_ncif_set_config_status of nfc_ncif.cc, there is a possible out of bounds write due to a missing bounds check. This could lead to local escalation of privilege with no additional execution privileges needed. User interaction is not needed for exploitation.

官方描述翻译:函数nfc_ncif.cc - nfc_ncif_set_config_status()里,因为缺少边界检查,存在一个越界写,这可以造成提权并且无需额外的执行权限,利用这个漏洞也不需要用户交互

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

CVE-2018-9584

A-114047681

EoP

7.0、7.1.1、7.1.2、8.0、8.1、9

补丁

  • https://android.googlesource.com/platform/system/nfc/+/5f0f0cc6a10f710dea7e1ddd4ba19acb877a7081

看起来是很常规的未检测Buffer长度就进行读写数据的漏洞

Prevent Out of bounds read/write in nfc_ncif_set_config_status

Test: Nfc Enable/Disable; Android Beam; Tag reading
Bug: 114047681
Merged-In: Iaba48380879373a4807a9d50634f4f40be97ef81
Change-Id: Iaba48380879373a4807a9d50634f4f40be97ef81
(cherry picked from commit 74cf5266c1bb9ee064cbc7e2544909d5d001e429)
(cherry picked from commit f3b6b4e1502771d94418cd2bc02591eb4379db34)
diff --git a/src/nfc/nfc/nfc_ncif.cc b/src/nfc/nfc/nfc_ncif.cc
index 4fb767f..93666e0 100644
--- a/src/nfc/nfc/nfc_ncif.cc
+++ b/src/nfc/nfc/nfc_ncif.cc
@@ -479,18 +479,33 @@
 ** Returns          void
 **
 *******************************************************************************/
-void nfc_ncif_set_config_status(uint8_t* p,
-                                __attribute__((unused)) uint8_t len) {
+void nfc_ncif_set_config_status(uint8_t* p, uint8_t len) {
   tNFC_RESPONSE evt_data;
   if (nfc_cb.p_resp_cback) {
-    evt_data.set_config.status = (tNFC_STATUS)*p++;
-    evt_data.set_config.num_param_id = NFC_STATUS_OK;
-    if (evt_data.set_config.status != NFC_STATUS_OK) {
-      evt_data.set_config.num_param_id = *p++;
-      STREAM_TO_ARRAY(evt_data.set_config.param_ids, p,
-                      evt_data.set_config.num_param_id);
+    evt_data.set_config.num_param_id = 0;
+    if (len == 0) {
+      LOG(ERROR) << StringPrintf("Insufficient RSP length");
+      evt_data.set_config.status = NFC_STATUS_SYNTAX_ERROR;
+      (*nfc_cb.p_resp_cback)(NFC_SET_CONFIG_REVT, &evt_data);
+      return;
     }
-
+    evt_data.set_config.status = (tNFC_STATUS)*p++;
+    if (evt_data.set_config.status != NFC_STATUS_OK && len > 1) {
+      evt_data.set_config.num_param_id = *p++;
+      if (evt_data.set_config.num_param_id > NFC_MAX_NUM_IDS) {
+        android_errorWriteLog(0x534e4554, "114047681");
+        LOG(ERROR) << StringPrintf("OOB write num_param_id %d",
+                                   evt_data.set_config.num_param_id);
+        evt_data.set_config.num_param_id = 0;
+      } else if (evt_data.set_config.num_param_id <= len - 2) {
+        STREAM_TO_ARRAY(evt_data.set_config.param_ids, p,
+                        evt_data.set_config.num_param_id);
+      } else {
+        LOG(ERROR) << StringPrintf("Insufficient RSP length %d,num_param_id %d",
+                                   len, evt_data.set_config.num_param_id);
+        evt_data.set_config.num_param_id = 0;
+      }
+    }
     (*nfc_cb.p_resp_cback)(NFC_SET_CONFIG_REVT, &evt_data);
   }
 }

从最开始走起,进入p_msg->eventBT_EVT_TO_NFC_NCI的分支,调用nfc_ncif_process_event()

通过对Buffer取第一字节并判断,进入NCI_GID_CORE分支,调用nci_proc_core_rsp()

使用NCI_MSG_PRS_HDR1获取p[1]位置的数据,赋值为op_code,之后获取一个字节p[2]作为len,当op_codeNCI_MSG_CORE_SET_CONFIG时,调用nfc_ncif_set_config_status(),并且传入Buffer指针,此时Buffer指针指向偏移为3的位置

终于来到了补丁函数,补丁描述是越界读取

这里可以看到将*p++赋值给evt_data.set_config.statusnfc_cb.p_resp_cback对应的是nfa_dm_nfc_response_cback(),此时可控的变量一共有三个

  1. evt_data.set_config.status

  2. evt_data.set_config.num_param_id

  3. evt_data.set_config.param_ids

我们来看evt_data.set_config.param_ids的定义,其中NFC_MAX_NUM_IDS125,我们知道,uint8_t为无符号类型,大小为255,所以这里足够溢出param_ids数组

再来回顾补丁

Last updated