【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-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->event为BT_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_code为NCI_MSG_CORE_SET_CONFIG时,调用nfc_ncif_set_config_status(),并且传入Buffer指针,此时Buffer指针指向偏移为3的位置
终于来到了补丁函数,补丁描述是越界读取
这里可以看到将*p++赋值给evt_data.set_config.status,nfc_cb.p_resp_cback对应的是nfa_dm_nfc_response_cback(),此时可控的变量一共有三个
evt_data.set_config.status
evt_data.set_config.num_param_id
evt_data.set_config.param_ids
我们来看evt_data.set_config.param_ids的定义,其中NFC_MAX_NUM_IDS为125,我们知道,uint8_t为无符号类型,大小为255,所以这里足够溢出param_ids数组
再来回顾补丁
Last updated