【NFC】CVE-2019-9358 ce_t3t_data_cback越界读写
这个漏洞因为不能直接触发,所以谷歌只在Android 10上面进行了修复而且没有公开补丁
漏洞原理总结:在函数ce_t3t_data_cback()
中直接获取传入数据作为长度进行数组拷贝造成越界写,可EoP
CVE
参考编号
类型
严重程度
CVE-2019-9358
A-120156401
EoP
中
这个漏洞暂时没有找到补丁,漏洞细节可以看注释
/*******************************************************************************
**
** Function ce_t3t_data_cback
**
** Description This callback function receives the data from NFCC.
**
** Returns none
**
*******************************************************************************/
void ce_t3t_data_cback(tNFC_DATA_CEVT* p_data) {
tCE_CB* p_ce_cb = &ce_cb;
tCE_T3T_MEM* p_cb = &p_ce_cb->mem.t3t;
NFC_HDR* p_msg = p_data->p_data;
tCE_DATA ce_data;
uint8_t cmd_id, bl0, entry_len, i;
uint8_t* p_nfcid2 = nullptr;
uint8_t* p = (uint8_t*)(p_msg + 1) + p_msg->offset;
uint8_t cmd_nfcid2[NCI_RF_F_UID_LEN];
uint16_t block_list_start_offset, remaining;
bool msg_processed = false;
bool block_list_ok;
uint8_t sod;
uint8_t cmd_type;
/* If activate system code is not NDEF, or if no local NDEF contents was set,
* then pass data up to the app */
if ((p_cb->system_code != T3T_SYSTEM_CODE_NDEF) ||
(!p_cb->ndef_info.initialized)) {
ce_data.raw_frame.status = p_data->status;
ce_data.raw_frame.p_data = p_msg;
p_ce_cb->p_cback(CE_T3T_RAW_FRAME_EVT, &ce_data);
return;
}
/* Verify that message contains at least Sod and cmd_id */
if (p_msg->len < 2) {
LOG(ERROR) << StringPrintf(
"CE: received invalid T3t message (invalid length: %i)", p_msg->len);
} else {
/* Get and validate command opcode */
STREAM_TO_UINT8(sod, p);
STREAM_TO_UINT8(cmd_id, p);
/* Valid command and message length */
cmd_type = ce_t3t_is_valid_opcode(cmd_id);
if (cmd_type == CE_T3T_COMMAND_INVALID) {
LOG(ERROR) << StringPrintf(
"CE: received invalid T3t message (invalid command: 0x%02X)", cmd_id);
} else if (cmd_type == CE_T3T_COMMAND_FELICA) {
ce_t3t_handle_non_nfc_forum_cmd(p_ce_cb, cmd_id, p_msg);
msg_processed = true;
} else {
/* Verify that message contains at least NFCID2 and NUM services */
if (p_msg->len < T3T_MSG_CMD_COMMON_HDR_LEN) {
LOG(ERROR) << StringPrintf(
"CE: received invalid T3t message (invalid length: %i)",
p_msg->len);
} else {
/* Handle NFC_FORUM command (UPDATE or CHECK) */
STREAM_TO_ARRAY(cmd_nfcid2, p, NCI_RF_F_UID_LEN);
STREAM_TO_UINT8(p_cb->cur_cmd.num_services, p); // 取值
// ############################################################
// 新增补丁判断,不能大于T3T_MSG_SERVICE_LIST_MAX
// #define T3T_MSG_SERVICE_LIST_MAX 16
/* Validate num_services */
if (p_cb->cur_cmd.num_services > T3T_MSG_SERVICE_LIST_MAX) {
LOG(ERROR) << StringPrintf(
"CE: recieved num_services (%i) exceeds maximum (%i)",
p_cb->cur_cmd.num_services, T3T_MSG_SERVICE_LIST_MAX);
} else {
// ############################################################
/* Calculate offset of block-list-start */
block_list_start_offset =
T3T_MSG_CMD_COMMON_HDR_LEN + 2 * p_cb->cur_cmd.num_services + 1;
if (p_cb->state == CE_T3T_STATE_NOT_ACTIVATED) {
LOG(ERROR) << StringPrintf("CE: received command 0x%02X while in bad state (%i))", cmd_id, p_cb->state);
} else if (memcmp(cmd_nfcid2, p_cb->local_nfcid2, NCI_RF_F_UID_LEN) != 0) {
LOG(ERROR) << StringPrintf("CE: received invalid T3t message (invalid NFCID2)");
p_nfcid2 = cmd_nfcid2; /* respond with ERROR using the NFCID2 from the command message */
} else if (p_msg->len < block_list_start_offset) {
/* Does not have minimum (including number_of_blocks field) */
LOG(ERROR) << StringPrintf("CE: incomplete message");
} else {
// 由于未对p_cb->cur_cmd.num_services进行长度判断,导致越界写
/* Parse service code list */
for (i = 0; i < p_cb->cur_cmd.num_services; i++) {
STREAM_TO_UINT16(p_cb->cur_cmd.service_code_list[i], p);
}
...
}
}
}
}
}
if (!msg_processed) {
ce_t3t_send_rsp(p_ce_cb, p_nfcid2, T3T_MSG_OPC_CHECK_RSP,
T3T_MSG_RSP_STATUS_ERROR,
T3T_MSG_RSP_STATUS2_ERROR_PROCESSING);
GKI_freebuf(p_msg);
}
}
Last updated