In this second and final blog post on this topic, we cover some OTA vulnerabilities we identified in wireless communication protocols, primarily Zigbee and BLE.
As in the previous post, the findings described herein are intended to illustrate the type of vulnerabilities a malicious actor could leverage to attack a specified target to achieve DoS, information leakage, or arbitrary code execution.
These vulnerabilities affect numerous devices within the IoT ecosystem. IOActive worked with the semiconductor vendors to coordinate the disclosure of these security flaws, but it is worth mentioning that due the specific nature of the IoT market and despite the fact that patches are available, a significant number of vulnerable devices will likely never be patched.
As usual, IOActive followed a responsible disclosure process, notifying the affected vendors and coordinating with them to determine the proper time to disclose issues. In general terms, most vendors properly handled the disclosure process.
At the time of publishing this blog post, the latest versions of the affected SDKs contain fixes for the vulnerabilities. Please note that IOActive has not verified these patches.
OTA Vulnerabilities
Affected vendors
- Nordic Semiconductor
- Texas Instruments
- Espressif Systems
- Qualcomm
Nordic Semiconductor - www.nordicsemi.com
Vulnerability
Integer overflow in ‘ble_advdata_search’
Affected Products
nRF5 SDK prior to version 16
Background
“The nRF5 SDK is your first stop for building fully featured, reliable and secure applications with the nRF52 and nRF51 Series. It offers developers a wealth of varied modules and examples right across the spectrum including numerous Bluetooth Low Energy profiles, Device Firmware Upgrade (DFU), GATT serializer and driver support for all peripherals on all nRF5 Series devices. The nRF5 SDK will almost certainly have something for your needs in developing exciting yet robust wireless products” https://www.nordicsemi.com/Software-and-tools/Software/nRF5-SDK
A malicious actor able to send specially crafted BLE advertisements could leverage this vulnerability to execute arbitrary code in the context of a device running a nRF5-SDK-based application. This may lead to the total compromise of the affected device.
Technical Details
At line 644, an attacker-controlled buffer pointed to by ‘p_encoded_data[i]’ may be 0x00, which will overflow ‘len’, whose value will be 0xFFFF after the operation.
This effectively bypasses the sanity check at line 645.
File: nRF5SDK160098a08e2/components/ble/common/ble_advdata.c
619: uint16_t ble_advdata_search(uint8_t const * p_encoded_data, 620: uint16_t data_len, 621: uint16_t * p_offset, 622: uint8_t ad_type) 623: { 624: if ((p_encoded_data == NULL) || (p_offset == NULL)) 625: { 626: return 0; 627: } 628: 629: uint16_t i = 0; 630: 631: while (((i < *p_offset) || (p_encoded_data[i + 1] != ad_type)) && (i < data_len)) 632: { 633: // Jump to next data. 634: i += (p_encoded_data[i] + 1); 635: } 636: 637: if (i >= data_len) 638: { 639: return 0; 640: } 641: else 642: { 643: uint16_t offset = i + 2; 644: uint16_t len = p_encoded_data[i] - 1; // FLAW 645: if ((offset + len) > data_len) // bypass 646: { 647: // Malformed. Extends beyond provided data. 648: return 0; 649: } 650: *p_offset = offset; 651: return len; 652: } 653: }
Exploitation
Different scenarios are possible depending on how ‘len’ is handled by the caller. In the following example, this vulnerability leads to a classic stack overflow at line 185.
File: nRF5SDK160098a08e2/examples/ble_central/experimental/ble_app_hrs_nfc_c/ble_m.c 153: static void on_adv_report(ble_gap_evt_adv_report_t const * p_adv_report) 154: { 155: ret_code_t err_code; 156: uint8_t * p_adv_data; 157: uint16_t data_len; 158: uint16_t field_len; 159: uint16_t dev_name_offset = 0; 160: char dev_name[DEV_NAME_LEN]; 161: 162: // Initialize advertisement report for parsing. 163: p_adv_data = (uint8_t *)p_adv_report->data.p_data; 164: data_len = p_adv_report->data.len; 165: 166: // Search for advertising names. 167: field_len = ble_advdata_search(p_adv_data, 168: data_len, 169: &dev_name_offset, 170: BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME); 171: if (field_len == 0) 172: { 173: // Look for the short local name if it was not found as complete. 174: field_len = ble_advdata_search(p_adv_data, 175: data_len, 176: &dev_name_offset, 177: BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME); 178: if (field_len == 0) 179: { 180: // Exit if the data cannot be parsed. 181: return; 182: } 183: } 184: 185: memcpy(dev_name, &p_adv_data[dev_name_offset], field_len);
Vulnerability
Incorrect DFU packet length resulting in remote code execution
Affected Products
nRF5 SDK for Mesh prior to version 4.1.0
Background
“The nRF5 SDK for Mesh combined with the nRF52 Series is the complete solution for your Bluetooth mesh development.” https://www.nordicsemi.com/Software-and-tools/Software/nRF5-SDK-for-Mesh
A malicious actor able to initiate a DFU connection to the affected device could potentially leverage this vulnerability to execute arbitrary code in the context of the bootloader. This may lead to the total compromise of the affected device.
Technical Details
When the bootloader handles DFU messages, the length of the mesh advertising data packets is not properly checked. The vulnerable code path is as follows:
File: nRF5-SDK-for-Mesh-master/mesh/bootloader/src/bootloader.c 439: void bootloader_init(void) 440: { 441: rtc_init(); 442: 443: memset(&m_flash_fifo, 0, sizeof(fifo_t)); …. SNIP … 461: 462: #ifdef RBC_MESH_SERIAL 463: mesh_aci_init(); 464: #endif 465: 466: transport_init(rx_cb, RBC_MESH_ACCESS_ADDRESS_BLE_ADV); 467: 468: bool dfu_bank_flash_start; 469: dfu_bank_scan(&dfu_bank_flash_start); …
File: nRF5-SDK-for-Mesh-master/mesh/bootloader/src/bootloader.c 209: static void rx_cb(mesh_packet_t* p_packet) 210: { 211: mesh_adv_data_t* p_adv_data = mesh_packet_adv_data_get(p_packet); 212: if (p_adv_data && p_adv_data->handle > RBC_MESH_APP_MAX_HANDLE) 213: { 214: bl_cmd_t rx_cmd; 215: rx_cmd.type = BL_CMD_TYPE_RX; 216: rx_cmd.params.rx.p_dfu_packet = (dfu_packet_t*) &p_adv_data->handle; 217: rx_cmd.params.rx.length = p_adv_data->adv_data_length - 3; 218: bl_cmd_handler(&rx_cmd); 219: } 220: }
File: nRF5-SDK-for-Mesh-master/mesh/bootloader/src/dfu_mesh.c 827: static uint32_t target_rx_data(dfu_packet_t* p_packet, uint16_t length, bool* p_do_relay) 828: { 829: uint32_t* p_addr = NULL; 830: uint32_t error_code = NRF_ERROR_NULL; 831: 832: if (m_data_req_segment == p_packet->payload.data.segment) 833: { 834: /* Got missing packet, stop requesting. */ 835: m_data_req_segment = DATA_REQ_SEGMENT_NONE; 836: bl_evt_t tx_abort_evt; 837: tx_abort_evt.type = BL_EVT_TYPE_TX_ABORT; 838: tx_abort_evt.params.tx.abort.tx_slot = TX_SLOT_BEACON; 839: bootloader_evt_send(&tx_abort_evt); 840: } 841: 842: if (p_packet->payload.data.segment <= 843: m_transaction.segment_count - m_transaction.signature_length / SEGMENT_LENGTH) 844: { 845: p_addr = addr_from_seg(p_packet->payload.data.segment, m_transaction.p_start_addr); 846: error_code = dfu_transfer_data((uint32_t) p_addr, 847: p_packet->payload.data.data, 848: length - (DFU_PACKET_LEN_DATA - SEGMENT_LENGTH)); 849: } 850: else /* treat signature packets at the end */ 851: { 852: uint32_t index = p_packet->payload.data.segment - 853: (m_transaction.segment_count - m_transaction.signature_length / SEGMENT_LENGTH) - 1; 854: if (index >= m_transaction.signature_length / SEGMENT_LENGTH || 855: m_transaction.signature_bitmap & (1 << index)) 856: { 857: error_code = NRF_ERROR_INVALID_STATE; 858: } 859: else 860: { 861: memcpy(&m_transaction.signature[index * SEGMENT_LENGTH], 862: p_packet->payload.data.data, 863: length - (DFU_PACKET_LEN_DATA - SEGMENT_LENGTH)); 864: 865: __LOG("Signature packet #%u\n", index); 866: m_transaction.signature_bitmap |= (1 << index); 867: error_code = NRF_SUCCESS; 868: }
Vulnerability
Multiple buffer overflows when handling Advertising Bearer data packets
Affected Products
nRF5 SDK for Mesh prior to version 4.1.0
Background
“The nRF5 SDK is your first stop for building fully featured, reliable and secure applications with the nRF52 and nRF51 Series. It offers developers a wealth of varied modules and examples right across the spectrum including numerous Bluetooth Low Energy profiles, Device Firmware Upgrade (DFU), GATT serializer and driver support for all peripherals on all nRF5 Series devices. The nRF5 SDK will almost certainly have something for your needs in developing exciting yet robust wireless products” https://www.nordicsemi.com/Software-and-tools/Software/nRF5-SDK
A malicious actor able to send malicious Advertising Bearer packets to the affected device could potentially leverage this vulnerability to execute arbitrary code. This may lead to the total compromise of the affected device.
Technical Details
The length of the Advertising Bearer data packets is not properly checked. The vulnerable code path is as follows:
File: nRF5-SDK-for-Mesh-master/mesh/prov/src/prov_bearer_adv.c 1059: AD_LISTENER(m_pb_adv_ad_listener) = { 1060: .ad_type = AD_TYPE_PB_ADV, 1061: .adv_packet_type = BLE_PACKET_TYPE_ADV_NONCONN_IND, 1062: .handler = packet_in, 1063: }; File: nRF5-SDK-for-Mesh-master/mesh/bearer/src/ad_listener.c 108: void ad_listener_process(ble_packet_type_t adv_type, const uint8_t * p_payload, uint32_t payload_length, const nrf_mesh_rx_metadata_t * p_metadata) 109: { 110: #ifdef AD_LISTENER_DEBUG_MODE 111: uint8_t frame_hash = hash_count(p_payload, payload_length); 112: #endif 113: 114: for (ble_ad_data_t * p_ad_data = (ble_ad_data_t *)p_payload; 115: (uint8_t *)p_ad_data < &p_payload[payload_length] && p_ad_data->length > 0; 116: p_ad_data = packet_ad_type_get_next((ble_ad_data_t *)p_ad_data)) 117: { 118: NRF_MESH_SECTION_FOR_EACH(ad_listeners, const ad_listener_t, p_listener) 119: { 120: if ((adv_type != p_listener->adv_packet_type && (uint8_t) p_listener->adv_packet_type != ADL_WILDCARD_ADV_TYPE) || 121: (p_listener->ad_type != p_ad_data->type && p_listener->ad_type != ADL_WILDCARD_AD_TYPE)) 122: { 123: continue; 124: } 125: 126: p_listener->handler(p_ad_data->data, p_ad_data->length - BLE_AD_DATA_OVERHEAD, p_metadata); 127: 128: #ifdef AD_LISTENER_DEBUG_MODE 129: NRF_MESH_ASSERT(hash_count(p_payload, payload_length) == frame_hash); 130: #endif 131: } 132: } 133: }
File: nRF5-SDK-for-Mesh-master/mesh/prov/src/prov_bearer_adv.c 1020: 1021: static void packet_in(const uint8_t * p_data, uint32_t data_len, const nrf_mesh_rx_metadata_t * p_metadata) 1022: { 1023: NRF_MESH_ASSERT(p_data != NULL); 1024: NRF_MESH_ASSERT(p_metadata != NULL); 1025: 1026: pb_adv_pdu_t * p_packet = (pb_adv_pdu_t *) p_data; 1027: 1028: nrf_mesh_prov_bearer_adv_t * p_pb_adv = get_bearer_from_link_id(BE2LE32(p_packet->link_id)); 1029: 1030: switch (p_packet->pdu.control) 1031: { 1032: case PB_ADV_PACKET_C_TRANSACTION_START: 1033: if (p_pb_adv != NULL && p_pb_adv->state == PROV_BEARER_ADV_STATE_LINK_OPEN) 1034: { 1035: handle_transaction_start_packet(p_pb_adv, p_packet, data_len); 1036: } 1037: break; 1038: case PB_ADV_PACKET_C_TRANSACTION_ACK: 1039: if (p_pb_adv != NULL && p_pb_adv->state == PROV_BEARER_ADV_STATE_LINK_OPEN) 1040: { 1041: handle_transaction_ack_packet(p_pb_adv, p_packet); 1042: } 1043: break; 1044: case PB_ADV_PACKET_C_TRANSACTION_CONTINUE: 1045: if (p_pb_adv != NULL && p_pb_adv->state == PROV_BEARER_ADV_STATE_LINK_OPEN) 1046: { 1047: handle_transaction_continuation_packet(p_pb_adv, p_packet, data_len); 1048: } 1049: break; 1050: case PB_ADV_PACKET_C_CONTROL: 1051: handle_control_packet(p_pb_adv, p_packet, data_len); 1052: break; 1053: default: 1054: /* Ignore */ 1055: break; 1056: } 1057: }
File: nRF5-SDK-for-Mesh-master/mesh/prov/src/prov_bearer_adv.c 684: /**** Packet handling ****/ 685: 686: static void handle_transaction_start_packet(nrf_mesh_prov_bearer_adv_t * p_pb_adv, pb_adv_pdu_t * p_packet, uint32_t length) 687: { 688: if (p_pb_adv->buffer.state == PROV_BEARER_ADV_BUF_STATE_UNUSED) 689: { 690: if (p_packet->transaction_number == p_pb_adv->transaction_in) 691: { 692: /* finished_segments, which is used in handle_transaction_continuation_packet 693: is 8-bits hence we are limited to receiving a maximum of 7 segments. */ 694: p_pb_adv->buffer.length = BE2LE16(p_packet->pdu.payload.transaction.start.total_length); 695: uint8_t SegN = transaction_total_segment_count_get(p_pb_adv->buffer.length); 696: if (SegN > (sizeof(p_pb_adv->buffer.finished_segments)*8) -1) 697: { 698: prov_bearer_adv_link_close(&p_pb_adv->prov_bearer, NRF_MESH_PROV_LINK_CLOSE_REASON_ERROR); 699: } 700: else 701: { 702: /* New message */ 703: p_pb_adv->buffer.fcs = p_packet->pdu.payload.transaction.start.fcs; 704: p_pb_adv->buffer.state = PROV_BEARER_ADV_BUF_STATE_RX; 705: p_pb_adv->buffer.finished_segments = 1; 706: uint32_t payload_length = length - PB_ADV_PACKET_OVERHEAD - PROV_BEARER_PACKET_TRANSACTION_START_OVERHEAD; 707: memcpy(p_pb_adv->buffer.payload, p_packet->pdu.payload.transaction.start.payload, payload_length);
File: nRF5-SDK-for-Mesh-master/mesh/prov/src/prov_bearer_adv.c 748: static void handle_transaction_continuation_packet(nrf_mesh_prov_bearer_adv_t * p_pb_adv, pb_adv_pdu_t * p_packet, uint32_t length) 749: { 750: if (p_pb_adv->buffer.state == PROV_BEARER_ADV_BUF_STATE_RX) 751: { 752: if (p_packet->transaction_number == p_pb_adv->transaction_in) 753: { 754: /* Check segment bitfield, to figure out if we've received this packet before: */ 755: if (!((1 << p_packet->pdu.id) & p_pb_adv->buffer.finished_segments)) 756: { 757: /* First time we receive this packet. */ 758: uint32_t data_index = (PROV_BEARER_ADV_PACKET_START_PAYLOAD_MAXLEN + (p_packet->pdu.id - 1) * PROV_BEARER_ADV_PACKET_CONTINUATION_PAYLOAD_MAXLEN); 759: uint32_t payload_length = length - PB_ADV_PACKET_OVERHEAD - PROV_BEARER_PACKET_TRANSACTION_CONTINUATION_OVERHEAD; 760: memcpy(&p_pb_adv->buffer.payload[data_index], p_packet->pdu.payload.transaction.continuation.payload, payload_length);
Vulnerability
Buffer overflow in BLE Queued Writes
Affected Products
nRF5 SDK prior to version 16
Background
“The nRF5 SDK is your first stop for building fully featured, reliable and secure applications with the nRF52 and nRF51 Series. It offers developers a wealth of varied modules and examples right across the spectrum including numerous Bluetooth Low Energy profiles, Device Firmware Upgrade (DFU), GATT serializer and driver support for all peripherals on all nRF5 Series devices. The nRF5 SDK will almost certainly have something for your needs in developing exciting yet robust wireless products” https://www.nordicsemi.com/Software-and-tools/Software/nRF5-SDK
A malicious actor able to send a initiate a Queued Write request to the affected device could potentially leverage this vulnerability to execute arbitrary code. This may lead to the total compromise of the affected device.
Technical Details
‘val_offset’ and ‘val_len’ are not properly sanitized. As a result, a malicious request containing a specific combination of both values (containing a large ‘val_len’ value) may lead to an integer overflow at line 135, resulting in a value that can bypass the check at line 136. Finally, at line 138, the overflow occurs as ‘val_len’ is used in the memcpy operation.
File: nRF5_SDK_16.0.0_98a08e2/components/ble/nrf_ble_qwr/nrf_ble_qwr.c 101: 102: ret_code_t nrf_ble_qwr_value_get(nrf_ble_qwr_t * p_qwr, 103: uint16_t attr_handle, 104: uint8_t * p_mem, 105: uint16_t * p_len) 106: { 107: VERIFY_PARAM_NOT_NULL(p_qwr); 108: VERIFY_PARAM_NOT_NULL(p_mem); 109: VERIFY_PARAM_NOT_NULL(p_len); 110: VERIFY_MODULE_INITIALIZED(); 111: 112: uint16_t i = 0; 113: uint16_t handle = BLE_GATT_HANDLE_INVALID; 114: uint16_t val_len = 0; 115: uint16_t val_offset = 0; 116: uint16_t cur_len = 0; 117: 118: do 119: { 120: handle = uint16_decode(&(p_qwr->mem_buffer.p_mem[i])); 121: 122: if (handle == BLE_GATT_HANDLE_INVALID) 123: { 124: break; 125: } 126: 127: i += sizeof(uint16_t); 128: val_offset = uint16_decode(&(p_qwr->mem_buffer.p_mem[i])); 129: i += sizeof(uint16_t); 130: val_len = uint16_decode(&(p_qwr->mem_buffer.p_mem[i])); 131: i += sizeof(uint16_t); 132: 133: if (handle == attr_handle) 134: { 135: cur_len = val_offset + val_len; 136: if (cur_len <= *p_len) 137: { 138: memcpy((p_mem + val_offset), &(p_qwr->mem_buffer.p_mem[i]), val_len); 139: } 140: else 141: { 142: return NRF_ERROR_NO_MEM; 143: } 144: } 145: 146: i += val_len; 147: } 148: while (i < p_qwr->mem_buffer.len); 149: 150: *p_len = cur_len; 151: return NRF_SUCCESS; 152: } 153: #endif
Texas Instruments - www.ti.com
Vulnerability
Z-Stack - Multiple heap overflows in ZCL parsing functions
Affected Products
Other Zigbee stacks based on the Z-Stack code are also affected (i.e. Telink)
Vendor advisory: https://www.ti.com/lit/an/swra699/swra699.pdf
“Z-Stack is a component of the SimpleLink™ CC13x2 / CC26x2 Software Development Kit. This component enables development of Zigbee® 3.0 specification based products. Z-Stack is TI’s complete solution for developing certified Zigbee 3.0 solution on CC13x2 and CC26x2 platforms. Z-Stack contained in this release is based on Zigbee 3.0 specification with the added benefit of running on top of TI-RTOS." https://www.ti.com/tool/Z-STACK
A malicious actor in possession of the NWK key (authenticated to the Zigbee Network) may send OTA malicious Zigbee ZCL packets to the victim’s node, which may result in the execution of arbitrary code in the context of the affected device.
Technical Details
Z-Stack parses the ZCL payloads by performing a two-steps flawed logic:
File: simplelink_cc13x2_26x2_sdk_4_20_00_35/source/ti/zstack/stack/zcl/zcl.c 3674: #ifdef ZCL_WRITE 3675: /********************************************************************* 3676: * @fn zclParseInWriteCmd 3677: * 3678: * @brief Parse the "Profile" Write, Write Undivided and Write No 3679: * Response Commands 3680: * 3681: * NOTE: THIS FUNCTION ALLOCATES THE RETURN BUFFER, SO THE CALLING 3682: * FUNCTION IS RESPONSIBLE TO FREE THE MEMORY. 3683: * 3684: * @param pCmd - pointer to incoming data to parse 3685: * 3686: * @return pointer to the parsed command structure 3687: */ 3688: void *zclParseInWriteCmd( zclParseCmd_t *pCmd ) 3689: { 3690: zclWriteCmd_t *writeCmd; 3691: uint8_t *pBuf = pCmd->pData; 3692: uint16_t attrDataLen; 3693: uint8_t *dataPtr; 3694: uint8_t numAttr = 0; 3695: uint8_t hdrLen; 3696: uint16_t dataLen = 0; 3697: 3698: // find out the number of attributes and the length of attribute data 3699: while ( pBuf < ( pCmd->pData + pCmd->dataLen ) ) 3700: { 3701: uint8_t dataType; 3702: 3703: numAttr++; 3704: pBuf += 2; // move pass attribute id 3705: 3706: dataType = *pBuf++; 3707: 3708: attrDataLen = zclGetAttrDataLength( dataType, pBuf ); 3709: pBuf += attrDataLen; // move pass attribute data 3710: 3711: // add padding if needed 3712: if ( PADDING_NEEDED( attrDataLen ) ) 3713: { 3714: attrDataLen++; 3715: } 3716: 3717: dataLen += attrDataLen; 3718: } 3719:
File: simplelink_cc13x2_26x2_sdk_4_20_00_35/source/ti/zstack/stack/zcl/zcl.c 3258: uint16_t zclGetAttrDataLength( uint8_t dataType, uint8_t *pData ) 3259: { 3260: uint16_t dataLen = 0; 3261: 3262: if ( dataType == ZCL_DATATYPE_LONG_CHAR_STR || dataType == ZCL_DATATYPE_LONG_OCTET_STR ) 3263: { 3264: dataLen = BUILD_UINT16( pData[0], pData[1] ) + 2; // long string length + 2 for length field 3265: } 3266: else if ( dataType == ZCL_DATATYPE_CHAR_STR || dataType == ZCL_DATATYPE_OCTET_STR ) 3267: { 3268: dataLen = *pData + 1; // string length + 1 for length field 3269: } 3270: else 3271: { 3272: dataLen = zclGetDataTypeLength( dataType ); 3273: } 3274: 3275: return ( dataLen );
3720: // calculate the length of the response header 3721: hdrLen = sizeof( zclWriteCmd_t ) + ( numAttr * sizeof( zclWriteRec_t ) ); 3722: 3723: writeCmd = (zclWriteCmd_t *)zcl_mem_alloc( hdrLen + dataLen ); 3724: if ( writeCmd != NULL ) 3725: { 3726: uint8_t i; 3727: pBuf = pCmd->pData; 3728: dataPtr = (uint8_t *)( (uint8_t *)writeCmd + hdrLen ); 3729: 3730: writeCmd->numAttr = numAttr; 3731: for ( i = 0; i < numAttr; i++ ) 3732: { 3733: zclWriteRec_t *statusRec = &(writeCmd->attrList[i]); 3734: 3735: statusRec->attrID = BUILD_UINT16( pBuf[0], pBuf[1] ); 3736: pBuf += 2; 3737: statusRec->dataType = *pBuf++; 3738: 3739: attrDataLen = zclGetAttrDataLength( statusRec->dataType, pBuf ); 3740: zcl_memcpy( dataPtr, pBuf, attrDataLen); 3741: statusRec->attrData = dataPtr; 3742: 3743: pBuf += attrDataLen; // move pass attribute data 3744: 3745: // advance attribute data pointer 3746: if ( PADDING_NEEDED( attrDataLen ) ) 3747: { 3748: attrDataLen++; 3749: } 3750: 3751: dataPtr += attrDataLen; 3752: } 3753: } 3754: 3755: return ( (void *)writeCmd ); 3756: }
File: simplelink_cc13x2_26x2_sdk_4_20_00_35/source/ti/zstack/stack/zcl/zcl.c 270: static CONST zclCmdItems_t zclCmdTable[]
File: simplelink_cc13x2_26x2_sdk_4_20_00_35/source/ti/zstack/stack/zcl/zcl_ll.c 1205: static ZStatus_t zclLL_ProcessInCmd_GetGrpIDsRsp( zclIncoming_t *pInMsg, 1206: zclLL_AppCallbacks_t *pCBs ) 1207: { 1208: ZStatus_t status = ZFailure; 1209: 1210: if ( pCBs->pfnGetGrpIDsRsp ) 1211: { 1212: zclLLGetGrpIDsRsp_t *pRsp; 1213: uint8_t cnt = pInMsg->pData[ZLL_CMDLEN_GET_GRP_IDS_RSP-1]; 1214: uint8_t rspLen = sizeof( zclLLGetGrpIDsRsp_t ) + ( cnt * sizeof( grpInfoRec_t ) ); 1215: 1216: pRsp = (zclLLGetGrpIDsRsp_t *)zcl_mem_alloc( rspLen ); 1217: if ( pRsp ) 1218: { 1219: uint8_t *pBuf = pInMsg->pData; 1220: uint8_t i; 1221: 1222: pRsp->total = *pBuf++; 1223: pRsp->startIndex = *pBuf++; 1224: pRsp->cnt = *pBuf++; 1225: pRsp->grpInfoRec = (grpInfoRec_t *)(pRsp+1); 1226: 1227: for ( i = 0; i < cnt; i++ ) 1228: { 1229: grpInfoRec_t *pRec = &(pRsp->grpInfoRec[i]); 1230: 1231: pRec->grpID = BUILD_UINT16( pBuf[0], pBuf[1] ); 1232: pBuf += 2; 1233: 1234: pRec->grpType = *pBuf++; 1235: } 1236: 1237: status = pCBs->pfnGetGrpIDsRsp( &(pInMsg->msg->srcAddr), pRsp ); 1238: 1239: zcl_mem_free( pRsp ); 1240: } 1241: } 1242: 1243: return ( status ); 1244: }
Vulnerability
EasyLink – memory corruption in ‘rxDoneCallback’
Affected Products
SIMPLELINK-CC13X2-26X2-SDK prior to version 4.40.00.44
Background
“The EasyLink API should be used in application code. The EasyLink API is intended to abstract the RF Driver in order to give a simple API for customers to use as is or extend to suit their application use cases." http://software-dl.ti.com/simplelink/esd/simplelink_cc13x0_sdk/4.10.01.01/exports/docs/proprietary-rf/proprietary-rf-users-guide/easylink/easylink-api-reference.html
A remote attacker may send a specially crafted OTA EasyLink packet to the victim’s device, which may result in either a DoS condition or the execution of arbitrary code.
Technical Details
EasyLink does not properly validate the length of the received packet. At line 533, the attacker-controlled buffer ('pDataEntry->data') is used to extract 1 byte that is then used to calculate the number of bytes that will be copied (at line 545) to the static buffer pointed to by 'rxBuffer.payload' (fixed at 128 bytes).
File: simplelink_cc13x2_26x2_sdk_4_20_00_35/source/ti/easylink/EasyLink.c 503: //Callback for Async Rx complete 504: static void rxDoneCallback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e) 505: { 506: EasyLink_Status status = EasyLink_Status_Rx_Error; 507: //create rxPacket as a static so that the large payload buffer it is not 508: //allocated from the stack 509: static EasyLink_RxPacket rxPacket; 510: rfc_dataEntryGeneral_t *pDataEntry; 511: pDataEntry = (rfc_dataEntryGeneral_t*) rxBuffer; 512: 513: if (e & RF_EventLastCmdDone) 514: { 515: //Release now so user callback can call EasyLink API's 516: Semaphore_post(busyMutex); 517: asyncCmdHndl = EASYLINK_RF_CMD_HANDLE_INVALID; 518: 519: //Check command status 520: if (EasyLink_cmdPropRxAdv.status == PROP_DONE_OK) 521: { 522: //Check that data entry status indicates it is finished with 523: if (pDataEntry->status != DATA_ENTRY_FINISHED) 524: { 525: status = EasyLink_Status_Rx_Error; 526: } 527: else if ( (rxStatistics.nRxOk == 1) || 528: //or filer disabled and ignore due to addr mistmatch 529: ((EasyLink_cmdPropRxAdv.pktConf.filterOp == 1) && 530: (rxStatistics.nRxIgnored == 1)) ) 531: { 532: //copy length from pDataEntry 533: rxPacket.len = *(uint8_t*)(&pDataEntry->data) - addrSize; 534: if(useIeeeHeader) 535: { 536: hdrSize = EASYLINK_HDR_SIZE_NBYTES(EASYLINK_IEEE_HDR_NBITS); 537: } 538: else 539: { 540: hdrSize = EASYLINK_HDR_SIZE_NBYTES(EASYLINK_PROP_HDR_NBITS); 541: } 542: //copy address from packet payload (as it is not in hdr) 543: memcpy(&rxPacket.dstAddr, (&pDataEntry->data + hdrSize), addrSize); 544: //copy payload 545: memcpy(&rxPacket.payload, (&pDataEntry->data + hdrSize + addrSize), rxPacket.len); 546: rxPacket.rssi = rxStatistics.lastRssi; 547: rxPacket.absTime = rxStatistics.timeStamp;
Espressif Systems - www.espressif.com
Vulnerability
Protocomm ‘transport_simple_ble_read’ information leak
Affected Products
ESP-IDF prior to v4.0.2 https://github.com/espressif/esp-idf
Background
“Espressif provides basic hardware and software resources to help application developers realize their ideas using the ESP32 series hardware. The software development framework by Espressif is intended for development of Internet-of-Things (IoT) applications with Wi-Fi, Bluetooth, power management and several other system features.” https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/
A remote attacker may send a specially crafted BLE packet to the victim’s device, which may result in either a DoS condition or an information leak.
Technical Details
When handling a BLE READ request from the client, ‘offset’ is not properly sanitized before copying data to the response (line 128). As a result, a malicious client may leak sensitive information from the device by setting an overly large ‘offset’ parameter in the READ request.
File: esp-idf-v4.0.1/components/protocomm/src/transports/protocomm_ble.c 107: static void transport_simple_ble_read(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) 108: { 109: static const uint8_t *read_buf = NULL; 110: static uint16_t read_len = 0; 111: esp_gatt_status_t status = ESP_OK; 112: 113: ESP_LOGD(TAG, "Inside read w/ session - %d on param %d %d", 114: param->read.conn_id, param->read.handle, read_len); 115: if (!read_len && !param->read.offset) { 116: ESP_LOGD(TAG, "Reading attr value first time"); 117: status = esp_ble_gatts_get_attr_value(param->read.handle, &read_len, &read_buf); 118: } else { 119: ESP_LOGD(TAG, "Subsequent read request for attr value"); 120: } 121: 122: esp_gatt_rsp_t gatt_rsp = {0}; 123: gatt_rsp.attr_value.len = MIN(read_len, (protoble_internal->gatt_mtu - 1)); 124: gatt_rsp.attr_value.handle = param->read.handle; 125: gatt_rsp.attr_value.offset = param->read.offset; 126: gatt_rsp.attr_value.auth_req = ESP_GATT_AUTH_REQ_NONE; 127: if (gatt_rsp.attr_value.len && read_buf) { 128: memcpy(gatt_rsp.attr_value.value, 129: read_buf + param->read.offset, 130: gatt_rsp.attr_value.len); 131: } 132: read_len -= gatt_rsp.attr_value.len; 133: esp_err_t err = esp_ble_gatts_send_response(gatts_if, param->read.conn_id, 134: param->read.trans_id, status, &gatt_rsp); 135: if (err != ESP_OK) { 136: ESP_LOGE(TAG, "Send response error in read"); 137: } 138: }
Qualcomm - www.qualcomm.com
Vulnerability
‘Api_ParseInfoElem’ improper handling of IEEE80211_ELEMID_RSN length may lead to a remote DoS
Affected Products
Qualcomm WIFI_QCA Middleware
Background
“The QCA4004 is an intelligent platform for the Internet of Things that contains a low-power Wi-Fi connectivity solution on a single chip. It includes a number of TCP/IP-based connectivity protocols along with SSL, allowing a low-cost, low-complexity system to obtain full-featured internet connectivity and reliable information exchange.” https://www.qualcomm.com/products/qca4004
The vulnerable code path is as follows:
1. When parsing the RSN IE, its length (‘ie_len’) is not properly sanitized against ‘len’ before calling ‘security_ie_parse’.
File: middleware/wifi_qca/common_src/api_interface/api_ioctl.c 695: A_STATUS 696: Api_ParseInfoElem(void *pCxt, WMI_BSS_INFO_HDR *bih, int32_t len, A_SCAN_SUMMARY *pSummary) 697: { 698: uint8_t *buf; 699: uint8_t *pie, *pieEnd, *pieTemp; 700: uint8_t ie_result[2]; 701: uint16_t ie_len; … SNIP… 740: case IEEE80211_ELEMID_RSN: 741: /*******************/ 742: /* parse RSN IE */ 743: /*******************/ 744: ie_len = pie[1]; /* init ie_len - sizeof wpa_oui */ 745: pieTemp = &pie[2]; /* init pieTemp beyond wpa_oui */ 746: 747: if (A_LE_READ_2(pieTemp) != RSN_VERSION) 748: { 749: break; 750: } 751: ie_len -= 2; 752: pieTemp += 2; 753: ie_result[0] = ie_result[1] = 0; 754: 755: security_ie_parse(pieTemp, ie_len, &ie_result[0], IEEE80211_ELEMID_RSN);
File: middleware/wifi_qca/common_src/api_interface/api_ioctl.c 629: static void security_ie_parse(uint8_t *pie, uint8_t ie_len, uint8_t *pResult, uint8_t ie_type) 630: { 631: uint16_t cnt; 632: uint16_t i; 633: uint8_t wepKeyLen; 634: /* skip mcast cipher */ 635: if (ie_len >= 4) 636: { 637: ie_len -= 4; 638: pie += 4; 639: } 640: /* examine ucast cipher(s) */ 641: if (ie_len > 2) 642: { 643: cnt = A_LE_READ_2(pie); 644: ie_len -= 2; 645: pie += 2; 646: 647: for (i = 0; ((i < cnt) && (ie_len > 0)); i++) 648: { 649: if (ie_type == IEEE80211_ELEMID_RSN) 650: { 651: pResult[0] |= rsn_cipher_parse(pie, &wepKeyLen); 652: } 653: else 654: { 655: pResult[0] |= wpa_cipher_parse(pie, &wepKeyLen); 656: } 657: 658: ie_len -= 4; 659: pie += 4; 660: } 661: }
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.