Практический подход к атаке встроенных проектов Интернета вещей, часть первая

Практический подход к атаке встроенных проектов Интернета вещей, часть первая

Автор: Ruben Santamarta, IOActive Labs

Быстрое развитие экосистемы Интернета вещей вызывает массовый рост рынка встраиваемых систем из-за высокого спроса на подключенные “умные” устройства. В настоящее время проектирование встроенных устройств значительно упростилось. Производители полупроводников предоставляют готовые решения, комплекты, микросхемы и коды, чтобы помочь разработчикам справиться с огромным количеством разнородных требований, которым должны соответствовать IoT-устройства.

Нескончаемая гонка за созданием новых функций в сжатые сроки имеет свою цену. Довольно часто из-за высокой скорости разработки мало внимания уделяется безопасности устройства.

Предположим, поставщик продукта внедрил передовые методы безопасности. Тем не менее мы ставим цель взломать данное устройство. Давайте проверим, есть ли шансы на успех. У нас нет доступа ни к одному пользовательскому коду (даже бинарному), разработанному для данного конкретного устройства. Зато мы имеем код, предоставляемый поставщиками полупроводников.

Теперь нужно выяснить, насколько безопасен код во всех SDK и промежуточном программном обеспечении, на которых работают устройства Интернета вещей.

Я провел ручную проверку кода некоторых из наиболее широко используемых SDK пакетов для Интернета вещей. В результате было обнаружено множество уязвимостей в коде, предоставленном ведущими поставщиками полупроводников, такими как Texas Instruments, Nordic и Qualcomm.

Хочу отметить, что IOActive следовала ответственному процессу раскрытия информации, уведомляя поставщиков и согласовывая с ними подходящее время для раскрытия проблем. В целом, большинство поставщиков должным образом справились с процессом раскрытия информации.

На момент публикации все найденные уязвимости были устранены.

Вступление

Встроенные IoT системы обычно разрабатываются для выполнения определенных функций. Поэтому мы не можем использовать единую эталонную разработку. Тем не менее, можно определить наиболее распространенные архитектуры.

SoC (Однокристальная система)

Данные конструкции основаны на SoC, который объединяет MCU (микроконтроллер) и приемопередатчик связи в однокристальное решение. Таким образом, стек программного обеспечения беспроводной связи и прикладное программное обеспечение работают в одном компоненте.

MCU + трансивер

В данных конструкциях MCU отвечает за запуск необходимого программного обеспечения, включая приложения и даже часть беспроводного стека. Трансивер обычно обрабатывает физический уровень и уровень передачи данных. Также в конструкциях имеется интерфейс хоста (HIF), отвечающий за обработку связи между MCU (хостом) и трансивером. Связь обычно осуществляется через последовательную шину (например, SPI, UART или I2C).

MCU + сетевой сопроцессор

Вариант предыдущей конструкции, в которой трансивер заменен сетевым сопроцессором (NCP), который управляет всем стеком связи. В данной архитектуре приложение все еще выполняется в MCU (хосте), а операции сетевого стека полностью передаются на NCP. HIF по-прежнему необходим для обеспечения связи между хостом и NCP.

Виды атак

Как мы только что отметили, компоненты во встраиваемых проектах Интернета вещей не работают изолированно. Они взаимодействуют с внешним миром по беспроводной сети и на внутриплатном уровне с другими микросхемами.

1. Внутриплатные атаки

Большинство современных микроконтроллеров и высококлассных SoC поддерживают механизмы безопасной загрузки или целостности кода. Предполагая наихудший сценарий, поставщик закрывает от злоумышленника все стандартные лазейки. Поэтому скорее всего мы не сможем сбросить настройки или получить доступ к прошивке.

В такой ситуации лучше сосредоточиться на HIF коде, который обычно содержится в SDK от поставщиков полупроводников.

Несмотря на то, что микропрограмма, работающая в MCU хоста (далее хост), может быть неизвестна, анализ HIF-связи может выявить, каким образом микропрограмма хоста была скомпилирована с потенциально уязвимым SDKкодом.

Успешный HIF-эксплойт может открыть лазейку для выполнения кода на хосте, если локальный злоумышленник имеет возможность исполнять роль трансивера/NCP через HIF шину (SPI, UART, I2C, USB и т. Д.). В IOActive мы годами использовали этот вектор атаки для компрометации других устройств, интеллектуальных счетчиков, которые обычно реализуют дизайн «MCU + NCP» или «MCU + Transceiver».

Описанные в статье уязвимости призваны проиллюстрировать общие закономерности в реализации HIF уровня у разных поставщиков. Стоит отметить, что у каждого из поставщиков надлежащие функции проверки отсутствовали.

Одним из преимуществ внутриплатных атак является возможность их использования не только для обнаружения уязвимостей, связанных с повреждением памяти, но и для гораздо более интересных логических ошибок. Дело в том, что микропрограмма хоста не учитывает возможность злоумышленника перехватить связь внутри платы.

2. Беспроводные атаки

В данном случае ситуация аналогична внутриплатной атаке. Злоумышленник точно также может не иметь доступа к микропрограммному обеспечению. Однако, у него есть возможность атаковать стек поставщика полупроводников, который обычно предоставляется в соответствующем SDK компонента.

В исследовании мы сосредоточились на стеках BLE и Zigbee, наиболее распространенных интерфейсах беспроводной связи, используемых в IoT экосистеме. Об этих уязвимостях мы расскажем во второй части статьи.

Внутриплатные уязвимости

Затронутые поставщики

  • Texas Instruments
  • Qualcomm
  • Silicon Labs
  • Zephyr OS
  • Microchip
  • Infineon

Texas Instruments - www.ti.com

Уязвимость

Повреждение памяти через ‘NPITLSPI_CallBack’

Уязвимые продукты

CC1350 SDK, BLE-STACK (SDK v4.10.01 и предыдущие версии)

CC26x0 BLE-STACK (v2.2.4 и предыдущие версии)

Информационный бюллетень Texas Instruments:https://www.ti.com/lit/an/swra684/swra684.pdf

Бэкграунд

«Интерфейс сетевого процессора (NPI) Texas Instruments используется для установки последовательного канала передачи данных между SoC и внешними микроконтроллерами или ПК. Это абстрактный уровень над последовательным интерфейсом (UART или SPI), который обрабатывает отправку/получение данных, управление питанием и анализ данных. В основном он используется решениями сетевых процессоров Texas Instruments». (Информация с сайта Texas Instruments)

Влияние

Локальный злоумышленник может вмешаться в физическую SPI шину между хостом и NCP и отправить искаженный UNPI пакет, повреждающий динамическую память в хосте, потенциально достигая выполнения кода.

Технические подробности

Когда ‘NPITLSPI_CallBack’ анализирует UNPI пакет, поступающий от ведомого устройства, он не проверяет должным образом, находится ли 16-битная длина в пределах ‘npiRxBuf’.

В строках 210-211 ‘readLen’ вычисляется из ненадежных входных данных, поступающих от ведомого устройства.

Если локальный злоумышленник угадает или задаст детерминированную FCS с учетом реализации malloc, в строке 221 произойдет повреждение памяти.

File: ble_sdk_2_02_04_06/src/components/npi/src/unified/npi_tl_spi.c
190: // -----------------------------------------------------------------------------
191: //! \brief      This callback is invoked on transmission completion
192: //!
193: //! \param[in]  handle - handle to the SPI port
194: //! \param[in]  objTransaction    - handle for SPI transmission
195: //!
196: //! \return     void
197: // -----------------------------------------------------------------------------
198: static void NPITLSPI_CallBack(SPI_Handle handle, SPI_Transaction *objTransaction)
199: {
200:     uint16_t i;
201:     uint16_t readLen = 0;
202:     uint16_t storeWriteLen;
203:     
204:     // Check if a valid packet was found
205:     // SOF:
206:     if (npiRxBuf[NPI_SPI_MSG_SOF_IDX] == NPI_SPI_MSG_SOF &&
207:             objTransaction->count)
208:     {
209:         // Length:
210:         readLen = npiRxBuf[NPI_SPI_MSG_LEN_LSB_IDX];
211:        readLen += ((uint16)npiRxBuf[NPI_SPI_MSG_LEN_MSB_IDX] << 8);
212:         readLen += NPI_SPI_MSG_HDR_NOSOF_LEN; // Include the header w/o SOF
213:         
214:         // FCS:
215:         if (npiRxBuf[readLen + 1] == 
216:               NPITLSPI_calcFCS(&npiRxBuf[NPI_SPI_MSG_LEN_LSB_IDX],readLen))
217:         {
218:             // Message is valid. Shift bytes to remove SOF
219:             for (i = 0 ; i < readLen; i++)
220:             {
221:                 npiRxBuf[i] = npiRxBuf[i + 1];
222:             }
223:         }
224:         else
225:         {
226:             // Invalid FCS. Discard message
227:             readLen = 0;
228:         }
229:    }
230:     
231:     //All bytes in TxBuf must be sent by this point
232:     storeWriteLen = tlWriteLen;
233:     tlWriteLen = 0;
234:     RxActive = FALSE;  
235:     
236:     if (npiTransmitCB)
237:     {
238:         npiTransmitCB(readLen,storeWriteLen);
239:     }
240: }

‘npiRxBuf’ инициализируется в строке 193 с использованием значения по умолчанию 530 байт.

File: source/ti/npi/npi_task.c
198: /* Default NPI parameters structure */
199: const NPI_Params NPI_defaultParams = {
200:     .stackSize          = 1024,
201:     .bufSize            = 530,File: source/ti/npi/npi_task.c
511:     // Initialize Transport Layer
512:     transportParams.npiTLBufSize = params->bufSize;
…


File: ble_sdk_2_02_04_06/src/components/npi/src/unified/npi_tl.c
178: //!
179: //! \param[in]  params - Transport Layer parameters
180: //!
181: //! \return     void
182: // -----------------------------------------------------------------------------
183: void NPITL_openTL(NPITL_Params *params)
184: {
185:     _npiCSKey_t key;
186:     key = NPIUtil_EnterCS();
187:     
188:     // Set NPI Task Call backs
189:     memcpy(&taskCBs, ¶ms->npiCallBacks, sizeof(params->npiCallBacks));
190:     
191:     // Allocate memory for Transport Layer Tx/Rx buffers
192:     npiBufSize = params->
193:     npiRxBuf = NPIUTIL_MALLOC(params->npiTLBufSize);

Qualcomm - www.qualcomm.com

Уязвимость

Множественные переполнения буфера при разборе некорректных WMIпакетов в промежуточном программном обеспечении ‘Wifi_qca

Уязвимые продукты

Продукты, использующие промежуточное ПО Qualcomm Atheros WIFI_QCA: https://www.qualcomm.com/products/qca4004

Бэкграунд

«Интерфейс беспроводного модуля (WMI) - это протокол связи для беспроводных QCA компонентов. Он определяет набор команд, которые могут быть отправлены целевой прошивке или которые целевая прошивка может отправить обратно на хост для обработки. WMI взаимодействие происходит над определенным HIF слоем".

Влияние

Локальный злоумышленник, способный вмешаться в физическую шину SPI между хостом и целевой QCA SoC, может отправить искаженный WMIпакет, который повреждает память ядра на хосте, тем самым потенциально достигая выполнения локального кода с привилегиями ядра.

Технические подробности

В промежуточном программном обеспечении QCA есть несколько мест, где WMI сообщения, поступающие с устройства, не проверяются должным образом.

№ 1 «WMI_GET_CHANNEL_LIST_CMDID»

При обработке ‘WMI_GET_CHANNEL_LIST_CMDID’ в ‘wmi_control_rx’ не выполняется проверка работоспособности контролируемого злоумышленником значения ‘CHAN_EV-> numChannels’.

File: middleware/wifi_qca/common_src/wmi/wmi.c
667:     switch (id)
668:     {
669:         case (WMI_GET_CHANNEL_LIST_CMDID):
670:             A_WMI_CHANNELLIST_RX(wmip->wmi_devt, devId, (int8_t)CHAN_EV->numChannels, (void*)CHAN_EV->channelList);
671:             break;
672:         case (WMI_GET_BITRATE_CMDID):

Затем ‘Api_ChannelListEvent’ использует ‘numChan’ для вычисления количества байтов без проверки границ, которые будут скопированы в фиксированный буфер ‘pDCxt->ChannelList’.

File: middleware/wifi_qca/common_src/api_interface/api_wmi_rx.c
119: void Api_ChannelListEvent(void *pCxt, uint8_t devId, int8_t numChan, void *chanList)
120: {
121:     uint16_t i;
122:     A_DRIVER_CONTEXT *pDCxt = GET_DRIVER_COMMON(pCxt);
123:     UNUSED_ARGUMENT(devId);
124:     A_MEMCPY(pDCxt->channelList, chanList, numChan * sizeof(uint16_t));
125:     pDCxt->numChannels = numChan;
126:    /* convert each channel to proper endianness */
127:     for (i = 0; i < pDCxt-> i++)
128:     {
129:         pDCxt->channelList[i] = A_LE2CPU16(pDCxt->channelList[i]);
130:     }
131:
132:     API_CHANNEL_LIST_EVENT(pCxt, pDCxt->numChannels, pDCxt->channelList);
133: }
134:

Данный буфер определен в структуре контекста драйвера в строке 256. С точки зрения возможности использования, злоумышленник может легко перезаписать указатель функции в строке 272 контролируемыми значениями.

File: middleware/wifi_qca/common_src/include/driver_cxt.h
56: #define MAX_NUM_CHANLIST_CHANNELS (16)
File:  middleware/wifi_qca/common_src/include/driver_cxt.h
265:     uint16_t channelList[MAX_NUM_CHANLIST_CHANNELS];
266: 
267:     uint32_t regCode;
268:     int8_t rssi;
269:     int32_t bitRate;
270:     boolean wmmEnabled;
271:     boolean tx_complete_pend; /* tracks new tx completes for task sync */
272:     TEMP_FUNC_T asynchRequest;

#2 ‘WMI_STORERECALL_STORE_EVENTID’

File:  middleware/wifi_qca/common_src/wmi/wmi.c
775:         case (WMI_STORERECALL_STORE_EVENTID):
776:             A_WMI_STORERECALL_EVENT_RX(wmip->wmi_devt, devId, datap, len, osbuf);
777:             break;

При обработке ‘WMI_STORERECALL_STORE_EVENTID’ в ‘wmi_control_rx’ не выполняется проверка корректности значения ‘len’, чтобы убедиться, что оно не превышает ‘pDCxt-> tempStorageLength’. В результате слишком большой WMI пакет может повредить буфер фиксированной длины, на который указывает ‘strrclData’. Буфер инициализируется в Custom_Driver_ContextInit.

File: middleware/wifi_qca/common_src/api_interface/api_wmi_rx.c
882: void Api_StoreRecallEvent(void *pCxt, uint8_t devId, uint8_t *datap, int32_t len, void *pReq)
883: {
884:     WMI_STORERECALL_STORE_EVENT *pEv;
885:     A_DRIVER_CONTEXT *pDCxt = GET_DRIVER_COMMON(pCxt);
886:     uint8_t *strrclData = pDCxt->tempStorage;
887: 
888:     UNUSED_ARGUMENT(devId);
889: 
890:     switch (pDCxt->strrclState)
891:     {
892:         case STRRCL_ST_START:
893:             A_MEMCPY(strrclData, datap, len);

Этот буфер инициализируется в Custom_Driver_ContextInit.

File: middleware/wifi_qca/custom_src/driver/cust_driver_main.c
150: Custom_Driver_ContextInit(void *pCxt)
151: {
152:     uint32_t tempStorageLen = 0;
153:     A_DRIVER_CONTEXT *pDCxt = GET_DRIVER_COMMON(pCxt);
154: 
155:    /*Allocate the temporary storage buffer. This may be shared by multiple modules.
156:       If store recall is enabled, it may use this buffer for storing target data.
157:       Will also be shared by scan module to store scan results*/
158:     tempStorageLen = max((STORE_RECALL_BUF_SIZE), (ATH_MAX_SCAN_BUFFERS * sizeof(QCA_SCAN_INFO)));
159:     tempStorageLen = max(tempStorageLen, (ATH_MAX_SCAN_BUFFERS * sizeof(ATH_SCAN_EXT)));
160: 
161:     if (tempStorageLen)
162:     {
163:         if (NULL == (pDCxt->tempStorage = A_MALLOC(tempStorageLen, 0)))
164:         {
165:             return A_NO_MEMORY;
166:         }
167:         pDCxt->tempStorageLength = tempStorageLen;

#3 ‘WMI_HOST_DSET_STORE_EVENTID’

File: middleware/wifi_qca/common_src/wmi/wmi.c
783:         case (WMI_HOST_DSET_STORE_EVENTID):
784:             A_WMI_HOST_DSET_EVENT_STORE_RX(wmip->wmi_devt, devId, datap, len, osbuf);

В Api_HostDsetStoreEvent, dset_length - это значение, контролируемое злоумышленником. В строке 418 имеется целочисленное переполнение, которое может обойти условие «если». В результате «dset_length» по-прежнему может быть больше, чем ‘pDCxt-> tempStorageLength’, что приведет к повреждению памяти.

File: middleware/wifi_qca/common_src/api_interface/api_wmi_rx.c
403: int dset_length;
404: 
405: voidApi_HostDsetStoreEvent(void *pCxt, uint8_t devId, uint8_t *datap, int32_t len, void *pReq)
406: {
407:     A_DRIVER_CONTEXT *pDCxt = GET_DRIVER_COMMON(pCxt);
408:     uint8_t *strrclData = pDCxt->tempStorage;
409:     uint16_t cur_len = pDCxt->strrclCxtLen;
410: 
411:     WMI_HOST_DSET_STORE_EVENT *pDsetEvent = (WMI_HOST_DSET_STORE_EVENT *)datap;
412:     UNUSED_ARGUMENT(devId);
413: 
414:     dset_length = pDsetEvent->length;
415: 
416:     strrclData = pDCxt->tempStorage + cur_len;
417: 
418:     if (cur_len + dset_length <= pDCxt->tempStorageLength)
419:     {
420:         A_MEMCPY(strrclData, pDsetEvent->data, dset_length);
421:     }
422:     else
423:     {
424:         A_ASSERT(0);
425:     }
426:     pDCxt->strrclCxtLen += dset_length;
427: }

Любой другой код, основанный на ‘dset_length’, также может быть уязвимым (например, ‘Api_HostDsetReadEvent’).

#4 ‘WMI_P2P_NODE_LIST_EVENTID’

File:  middleware/wifi_qca/common_src/wmi/wmi.c
834:         case WMI_P2P_NODE_LIST_EVENTID:
835:             status = wmi_p2p_node_list_event_rx(wmip, devId, datap, len);
836:            break;

При обработке сообщений ‘WMI_P2P_NODE_LIST_EVENTID’, поступающих от устройства, контролируемое злоумышленником значение ‘num_p2p_dev’ не очищается. В результате в строке 1399 можно повредить буфер фиксированной длины, на который указывает 'tmpBuf', то есть 'pCxt-> pScanOut' (на самом деле это 'pDCxt-> tempStorage', что объяснялось ранее).

File: middleware/wifi_qca/common_src/api_interface/api_wmi_rx.c

1382: void Api_p2p_node_list_event(void *pCxt, uint8_t devId, uint8_t *datap, uint32_t len)
1383: {
1384:     uint32_t evt_id = 0;
1385:     uint8_t *tmpBuf;
1386:     evt_id = WMI_P2P_NODE_LIST_EVENTID;
1387:     WMI_P2P_NODE_LIST_EVENT *handleP2PDev = (WMI_P2P_NODE_LIST_EVENT *)datap;
1388:     A_DRIVER_CONTEXT *pDCxt = GET_DRIVER_COMMON(pCxt);
1389: 
1390:     tmpBuf = GET_DRIVER_COMMON(pCxt)->pScanOut;
1391:     DRIVER_SHARED_RESOURCE_ACCESS_ACQUIRE(pCxt);
1392:     {
1393:         A_MEMZERO(GET_DRIVER_COMMON(pCxt)->pScanOut, pDCxt->tempStorageLength);
1394:         A_MEMCPY(GET_DRIVER_COMMON(pCxt)->pScanOut, &evt_id, sizeof(uint32_t));
1395:         tmpBuf += sizeof(uint32_t);
1396:         *tmpBuf = handleP2PDev->num_p2p_dev;
1397:         tmpBuf++;
1398: 
1399:         A_MEMCPY((uint8_t *)tmpBuf, ((uint8_t *)(handleP2PDev->data)),
1400:                  (sizeof(P2P_DEVICE_LITE) * (handleP2PDev->num_p2p_dev)));
1401: 
1402:         GET_DRIVER_COMMON(pCxt)->p2pEvtState = false;
1403:     }
1404:     DRIVER_SHARED_RESOURCE_ACCESS_RELEASE(pCxt);
1405: 
1406:     DRIVER_WAKE_USER(pCxt);
1407: }

Silicon Labs - www.silabs.com

Уязвимость

Переполнение буфера в ‘sl_wfx_get_pmk’

Уязвимые продукты

FMAC WFx драйвер от Silicon Labs: https://github.com/SiliconLabs/wfx-fullMAC-driver/

Бэкграунд

«FMAC WFx драйвер - программный ресурс, позволяющий хосту обмениваться данными с WFx Wi-Fi трансивером. API, предоставляемый драйвером, контролирует возможности WFx Wi-Fi. Кроме того, API позволяет передавать данные на IP уровне. Теперь хосту требуется IP стек для отправки/получения Ethernet кадров».

https://docs.silabs.com/wifi/wf200/rtos/latest/wfx-fmac-driver

Влияние

Локальный злоумышленник, способный вмешаться в физическую SPI/SDIO шину между хостом и NCP Silicon Labs, может подделать искаженный фрейм WFx ответа, который повреждает память на хосте, потенциально обеспечивая выполнение локального кода.

Технические подробности

‘Sl_wfx_get_pmk’ не очищает ‘reply-> body.password_length’, сравнивая его со значением ‘password_length’ или проверяя SL_WFX_PASSWORD_SIZE перед его копированием (строка 1119) в предоставленный буфер. В результате нет гарантии, что буфер, на который указывает «пароль», может безопасно получить длину, указанную в ответе.

File: wfx-fullMAC-driver-master/wfx_fmac_driver/sl_wfx.c
1097: /**************************************************************************//**
1098:  * @brief Get the PMK used to connect to the current secure network
1099:  *
1100:  * @param password is the current Pairwise Master Key
1101:  * @param password_length is its length in bytes
1102:  * @param interface is the interface used to send the request.
1103:  *   @arg         SL_WFX_STA_INTERFACE
1104:  *   @arg         SL_WFX_SOFTAP_INTERFACE
1105:  * @returns SL_STATUS_OK if the command has been sent correctly,
1106:  * SL_STATUS_FAIL otherwise
1107:  *****************************************************************************/
1108: sl_status_t sl_wfx_get_pmk(uint8_t *password,
1109:                            uint32_t *password_length,
1110:                            sl_wfx_interface_t interface)
1111: {
1112:  sl_status_t      result;
1113:   sl_wfx_get_pmk_cnf_t *reply = NULL;
1114: 
1115:   result = sl_wfx_send_command(SL_WFX_GET_PMK_REQ_ID, NULL, 0, interface, (sl_wfx_generic_confirmation_t **)&reply);
1116: 
1117:   if (result == SL_STATUS_OK) {
1118:     result = sl_wfx_get_status_code(sl_wfx_htole32(reply->body.status), SL_WFX_GET_PMK_REQ_ID);
1119:     memcpy(password, reply->body.password, sl_wfx_htole32(reply->body.password_length));
1120:     *password_length = sl_wfx_htole32(reply->body.password_length);
1121:   }
1122: 
1123:   return result;
1124: }

Уязвимость

Повреждение памяти ядра при декодировании кадра HIF "Secure Channel"

Уязвимые продукты

WFx драйвер для Linux от Silicon Labs: https://github.com/SiliconLabs/wfx-linux-driver

Бэкграунд

Микросхемы WF (M) 200 от Silicon Labs обладают способностью шифровать SPI или SDIO последовательный интерфейс между хостом и устройством.

Влияние

Локальный злоумышленник, способный вмешаться в физическую SPI/SDIO шину между хостом и NCP Silicon Labs, может отправить искаженный HIF фрейм, который повреждает память ядра на хосте, тем самым потенциально обеспечивая выполнение локального кода с привилегиями ядра.

Технические подробности

Драйвер обрабатывает входные данные, контролируемые злоумышленником (строки 78-80), при использовании HIF протоколом «функции безопасного канала», даже до того, как будет выполнена надлежащая проверка работоспособности в поле ‘hif-> len’ (строка 94). В результате вычисленная длина HIF кадра будет отличаться от фактического ‘read_len’.

File: wfx-linux-driver-master/bh.c
051: static int rx_helper(struct wfx_dev *wdev, size_t read_len, int *is_cnf)
052: {
053: 	struct sk_buff *skb;
054: 	struct hif_msg *hif;
055: 	size_t alloc_len;
056: 	size_t computed_len;
057: 	int release_count;
058: 	int piggyback = 0;
059:
060: 	WARN(read_len < 4, "corrupted read");
061: 	WARN(read_len > round_down(0xFFF, 2) * sizeof(u16),
062: 	     "%s: request exceed WFx capability", __func__);
063: 
064: 	// Add 2 to take into account piggyback size
065: 	alloc_len = wdev->hwbus_ops->align_size(wdev->hwbus_priv, read_len + 2);
066: 	skb = dev_alloc_skb(alloc_len);
067: 	if (!skb)
068: 		return -ENOMEM;
069: 
070: 	if (wfx_data_read(wdev, skb->data, alloc_len))
071: 		goto err;
072: 
073: 	piggyback = le16_to_cpup((__le16 *)(skb->data + alloc_len - 2));
074: 	_trace_piggyback(piggyback, false);
075: 
076: 	hif = (struct hif_msg *)skb->data;
077: 	WARN(hif->encrypted & 0x1, "unsupported encryption type");
078: 	if (hif->encrypted == 0x2) {
079:		if  (wfx_sl_decode(wdev, (void *)hif)) {
080: 			dev_kfree_skb(skb);
081: 			// If frame was a confirmation, expect trouble in next
082: 			// exchange. However, it is harmless to fail to decode
083: 			// an indication frame, so try to continue. Anyway,
084: 			// piggyback is probably correct.
085: 			return piggyback;
086: 		}
087: 		computed_len =
088: 			round_up(le16_to_cpu(hif->len) - sizeof(hif->len), 16) +
089: 			sizeof(struct hif_sl_msg) +
090: 			sizeof(struct hif_sl_tag);
091: 	} else {
092: 		computed_len = round_up(le16_to_cpu(hif->len), 2);
093: 	}
094:	if  (computed_len != read_len) {
095: 		dev_err(wdev->dev, "inconsistent message length: %zu != %zu\n",
096: 			computed_len, read_len);
097: 		print_hex_dump(KERN_INFO, "hif: ", DUMP_PREFIX_OFFSET, 16, 1,
098: 			       hif, read_len, true);
099: 		goto err;
100: 	}

‘Clear_len’ контролируется злоумышленником, поэтому ‘payload_len’, ‘tag’ и ‘output’ также в некоторой степени косвенно контролируются (строки 51-54). В строке 69 вызывается ‘mbedtls_ccm_auth_decrypt’ для дешифрования полезной нагрузки HIF с использованием ‘payload_len’ с буфером ‘skb-> data’ в качестве вывода. Поскольку длина ‘skb-> data’ может отличаться от ‘payload_len’, возможно повреждение этого фрагмента памяти.

File: wfx-linux-driver-master/secure_link.c
48: int wfx_sl_decode(struct wfx_dev *wdev, struct hif_sl_msg *m)
49: {
50: 	int ret;
51: 	size_t clear_len = le16_to_cpu(m->len);
52: 	size_t payload_len = round_up(clear_len - sizeof(m->len), 16);
53: 	u8 *tag = m->payload + payload_len;
54: 	u8 *output = (u8 *)m;
55: 	u32 nonce[3] = { };
56: 
57: 	WARN(m->hdr.encrypted != 0x02, "packet is not encrypted");
58: 
59: 	// Other bytes of nonce are 0
60: 	nonce[1] = m->hdr.seqnum;
61:	if  (wdev->sl.rx_seqnum != m->hdr.seqnum)
62: 		dev_warn(wdev->dev, "wrong encrypted message sequence: %d != %d\n",
63: 				m->hdr.seqnum, wdev->sl.rx_seqnum);
64: 	wdev->sl.rx_seqnum = m->hdr.seqnum + 1;
65: 	if (wdev->sl.rx_seqnum == slk_renew_period)
66: 		schedule_work(&wdev->sl.key_renew_work);
67: 
68: 	memcpy(output, &m->len, sizeof(m->len));
69: 	ret = mbedtls_ccm_auth_decrypt(&wdev->sl.ccm_ctxt, payload_len,
70: 			(u8 *)nonce, sizeof(nonce), NULL, 0,
71: 			m->payload, output + sizeof(m->len),
72: 			tag, sizeof(struct hif_sl_tag));
73: 	if (ret) {
74: 		dev_err(wdev->dev, "mbedtls error: %08x\n", ret);
75: 		return -EIO;
76: 	}
77: 	if (memzcmp(output + clear_len, payload_len + sizeof(m->len) - clear_len))
78: 		dev_warn(wdev->dev, "padding is not 0\n");
79: 	return 0;
80: }

Фактическое повреждение памяти происходит в строке 146 в CTR_CRYPT, поскольку ‘dst’ указывает на полезную HIFнагрузку.

File:  wfx-linux-driver-master/mbedtls/library/ccm.c
131: /*
132:  * Encrypt or decrypt a partial block with CTR
133:  * Warning: using b for temporary storage! src and dst must not be b!
134:  * This avoids allocating one more 16 bytes buffer while allowing src == dst.
135:  */
136: #define CTR_CRYPT( dst, src, len  )                                            \
137:     do                                                                  \
138:     {                                                                   \
139:         if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctr,       \
140:                                            16, b, &olen ) ) != 0 )      \
141:         {                                                               \
142:             return( ret );                                              \
143:         }                                                               \
144:                                                                        \
145:         for( i = 0; i < (len); i++ )                                    \
146:             (dst)[i] = (src)[i] ^ b[i];                                 \
147:     } while( 0 )

Zephyr OS - www.zephyrproject.org

Уязвимость

Множественные переполнения буфера в eswifi ‘Zephyr’драйвере

Затронутые продукты

Zephyr RTOS 2.3.0:

Влияние

Локальный злоумышленник, способный вмешаться в физическую SPI шину между хостом и целевым контроллером, может отправить искаженный SPI ответ, который повреждает память ядра на хосте, тем самым потенциально достигая выполнения локального кода с привилегиями ядра.

Технические подробности

# 1 переполнение буфера __parse_ipv4_address

Эта функция не проверяет должным образом, что «байт» находится в пределах IP-адреса (4 байта) при синтаксическом анализе IPv4-адреса. В результате неверно сформированная IP строка с чрезмерно большим количеством «точек» приведет к повреждению ‘ip’ буфера.

File: zephyr-master/drivers/wifi/eswifi/eswifi_core.c
179: static int __parse_ipv4_address(char *str, char *ssid, uint8_t ip[4])
180: {
181: 	unsigned int byte = -1;
182: 
183: 	/* fmt => [JOIN   ] SSID,192.168.2.18,0,0 */
184: 	while (*str) {
185: 		if (byte == -1) {
186: 			if (!strncmp(str, ssid, strlen(ssid))) {
187: 				byte = 0U;
188: 				str += strlen(ssid);
189: 			}
190: 			str++;
191: 			continue;
192: 		}
193: 
194: 		ip[byte++] = atoi(str);
195: 		while (*str && (*str++ != '.')) {
196: 		}
197: 	}
198: 
199: 	return 0;
200: }

Уязвимость приводит к переполнению стека в строках 243 и 286.

File:zephyr-master/drivers/wifi/eswifi/eswifi_core.c
240: static int eswifi_connect(struct eswifi_dev *eswifi)
241: {
242: 	char connect[] = "C0\r";
243: 	struct in_addr addr;

…SNIP…

284: 	/* Any IP assigned ? (dhcp offload or manually) */
285: 	err = __parse_ipv4_address(rsp, eswifi->sta.ssid,
286: 				   (uint8_t *)&addr.s4_addr);
287: 	if (err < 0) {
288:		LOG_ERR("Unable to retrieve IP address");
289: 		goto error;
290: 	}
#2 ‘__parse_ssid’ buffer overflow

Аналогичная ситуация происходит в ‘__parse_ssid’, который извлекает и затем копирует указанный SSID, полученный из SPI ответа, без проверки его длины.

File: zephyr-master/drivers/wifi/eswifi/eswifi_core.c
54: static inline int __parse_ssid(char *str, char *ssid)
55: {
56: 	/* fnt => '"SSID"' */
57: 
58: 	if (!*str || (*str != '"')) {
59: 		return -EINVAL;
60: 	}
61: 
62: 	str++;
63: 	while (*str && (*str != '"')) {
64: 		*ssid++ = *str++;
65: 	}
66: 
67: 	*ssid = '\0';
68: 
69: 	if (*str != '"') {
70: 		return -EINVAL;
71: 	}
72: 
73:	return  -EINVAL;
74: }
75: 

Уязвимость также заканчивается сценарием переполнения стека по следующему уязвимому пути:

1.

File: zephyr-master/drivers/wifi/eswifi/eswifi_core.c
202: static void eswifi_scan(struct eswifi_dev *eswifi)
203: {
204: 	char cmd[] = "F0\r";
205: 	char *data;
206: 	int i, ret;
207:
208: 	LOG_DBG("");
209: 
210: 	eswifi_lock(eswifi);
211: 
212: 	ret = eswifi_at_cmd_rsp(eswifi, cmd, &data);
213: 	if (ret < 0) {
214: 		eswifi->scan_cb(eswifi->iface, -EIO, NULL);
215: 		eswifi_unlock(eswifi);
216: 		return;
217: 	}
218: 
219: 	for (i = 0; i < ret; i++) {
220:  		if(data[i] == '#') {
221: 			struct wifi_scan_result res = {0};
222: 
223: 			__parse_scan_res(&data[i], &res);
224: 
225: 			eswifi->scan_cb(eswifi->iface, 0, &res);
226: 			k_yield();
227: 
228: 			while (data[i] && data[i] != '\n') {
229: 				i++;
230: 			}
231: 		}
232: 	}

2.

File: zephyr-master/include/net/wifi_mgmt.h
84: /* Each result is provided to the net_mgmt_event_callback
85:  * via its info attribute (see net_mgmt.h)
86:  */
87: struct wifi_scan_result {
88: 	uint8_t ssid[WIFI_SSID_MAX_LEN];
89: 	uint8_t ssid_length;
90: 
91: 	uint8_t channel;
92: 	enum wifi_security_type security;
93: 	int8_t rssi;
94: };

3.

File: zephyr-master/drivers/wifi/eswifi/eswifi_core.c
76: static void __parse_scan_res(char *str, struct wifi_scan_result *res)
77: {
78: 	int field = 0;
79: 
80: 	/* fmt => #001,"SSID",MACADDR,RSSI,BITRATE,MODE,SECURITY,BAND,CHANNEL */
81: 
82: 	while (*str) {
83: 		if (*str != ',') {
84: 			str++;
85: 			continue;
86: 		}
87: 
88: 		if (!*++str) {
89: 			break;
90: 		}
91: 
92: 		switch (++field) {
93: 		case 1: /* SSID */
94: 			__parse_ssid(str, res->ssid);

Микрочип - www.microchip.com

Уязвимость

Множественные уязвимости в «CryptoAuth Lib» 3.2.2

Затронутые продукты

"CryptoAuthLib, предназначенная для работы с устройствами криптоаутентификации, такими как ATECC608B, ATSHA204A или ATSHA206A, для упрощения разработки, представляет собой библиотеку поддержки программного обеспечения, написанную на языке C. Библиотека присутствует в компоненте любого приложения или драйвера устройства, для которого требуются службы шифрования от CryptoAuthentication. CryptoAuthLib работает на различных платформах, включая микроконтроллеры Arm® Cortex®-M или PIC®, ПК под управлением операционной системы Windows® или встроенной Linux® платформе» (Информация с сайта Microchip)

Влияние

Локальный злоумышленник, способный частично имитировать вредоносное устройство крипто-аутентификации через USB, может отправить искаженные пакеты KIT протокола, которые повреждают память на хосте, что потенциально может привести к выполнению кода.

Технические подробности

Когда «kit_phy_receive» получает KIT пакет от устройства, он не проверяет должным образом, находится ли общий объем полученных байтов в пределах «rxdata».

Условие цикла чтения просто «continue_read == true» без учета «rxsize» в строке 324.

В строке 308 мы видим, как логика постоянно пытается прочитать фиксированное количество одного байта с USB-устройства.

В строке 316 total_bytes_read увеличивается на bytes_read. Поскольку злоумышленник управляет вводом, можно избежать проверки на '\ n' в строке 319. В результате, 'total_bytes_read' будет увеличиваться за пределы 'rxsize', таким образом переполняя 'rxdata' в строке 308 во время вызова 'fread'.

File: secure_elements/lib/hal/hal_linux_kit_hid.c
287: ATCA_STATUS kit_phy_receive(ATCAIface iface, uint8_t* rxdata, int* rxsize)
288: {
289:     ATCAIfaceCfg *cfg = atgetifacecfg(iface);
290:     atcahid_t* pHid = (atcahid_t*)atgetifacehaldat(iface);
291:     bool continue_read = true;
292:    size_t  bytes_read = 0;
293:    size_t total_bytes_read = 0;
294: 
295:     if ((rxdata == NULL) || (rxsize == NULL) || (cfg == NULL) || (pHid == NULL))
296:     {
297:         return ATCA_BAD_PARAM;
298:     }
299: 
300:     if (pHid->kits[cfg->atcahid.idx].read_handle == NULL)
301:     {
302:         return ATCA_COMM_FAIL;
303:     }
304: 
305:     // Receive the data from the kit USB device
306:     do
307:     {
308:         bytes_read = fread(&rxdata[total_bytes_read], sizeof(uint8_t), 1,
309:                            pHid->kits[cfg->atcahid.idx].read_handle);
310:        if  (ferror(pHid->kits[cfg->atcahid.idx].read_handle) != 0)
311:        {
312:             clearerr(pHid->kits[cfg->atcahid.idx].read_handle);
313:             return ATCA_RX_FAIL;
314:         }
315: 
316:         total_bytes_read += bytes_read;
317: 
318:         // Check if the kit protocol message has been received
319:       if   (strstr((char*)rxdata, "\n") != NULL)
320:         {
321:             continue_read = false;
322:         }
323:     }
324:    while  (continue_read == true);
325: 
326:     // Save the total bytes read
327:     *rxsize = total_bytes_read;
328: 
329:     return ATCA_SUCCESS; 

Похожая проблема также обнаружена в ‘kit_phy_receive’, хотя в этом случае вместо одного байта он считывает CDC_BUFFER_MAX в локальный буфер стека в строке 263. ‘bytes_to_cpy’ используется для увеличения смещения (‘total_bytes’) ( строка 288), куда будут скопированы байты (строка 287).

File: secure_elements/lib/hal/hal_linux_kit_cdc.c
232: ATCA_STATUS kit_phy_receive(ATCAIface iface, char* rxdata, int* rxsize)
233: {
234:     ATCA_STATUS status = ATCA_SUCCESS;
235:     ATCAIfaceCfg *cfg = atgetifacecfg(iface);
236:     int cdcid = cfg->atcauart.port;
237:     atcacdc_t* pCdc = (atcacdc_t*)atgetifacehaldat(iface);
238:     uint8_t buffer[CDC_BUFFER_MAX] = { 0 };
239:     bool continue_read = true;
240:     int bytes_read = 0;
241:     uint16_t total_bytes = 0;
242:     char* location = NULL;
243:     int bytes_remain = 0;
244:     int bytes_to_cpy = 0;
245: 
246:     do
247:     {
248:         // Verify the input variables
249:         if ((rxdata == NULL) || (rxsize == NULL) || (pCdc == NULL))
250:         {
251:             status = ATCA_BAD_PARAM;
252:             break;
253:         }
254:         // Verify the write handle
255:         if (pCdc->kits[cdcid].read_handle == INVALID_HANDLE_VALUE)
256:         {
257:             status = ATCA_COMM_FAIL;
258:             break;
259:         }
260:         // Read all of the bytes
261:         while (continue_read == true)
262:         {
263:             bytes_read = read(pCdc->kits[cdcid].read_handle, buffer, CDC_BUFFER_MAX);
264: 
265:             // Find the location of the '\n' character in read buffer
266:             // todo: generalize this read...  it only applies if there is an ascii protocol with an <eom> of \n and if the <eom> exists
267:             location = strchr((char*)&buffer[0], '\n');
268:             if (location == NULL)
269:             {
270:                 // Copy all of the bytes
271:                 bytes_to_cpy = bytes_read;
272:             }
273:             else
274:             {
275:                 // Copy only the bytes remaining in the read buffer to the <eom>
276:                 bytes_to_cpy = (uint8_t)(location - (char*)buffer) + 1;
277:                 // The response has been received, stop receiving more data
278:                 continue_read = false;
279:             }
280:             // Protect rxdata from overwriting, this will have the result of truncating the returned bytes
281:             // Remaining space in rxdata
282:             //bytes_remain = (*rxsize - total_bytes);
283:             // Use the minimum between number of bytes read and remaining space
284:             //bytes_to_cpy = min(bytes_remain, bytes_to_cpy);
285: 
286:             // Copy the received data
287:             memcpy(&rxdata[total_bytes], &buffer[0], bytes_to_cpy);
288:             total_bytes += bytes_to_cpy;
289:         }
290: 
291:     }
292:     while (0);
293: 
294:     *rxsize = total_bytes;
295: #ifdef KIT_DEBUG
296:     printf("<-- %s", rxdata);
297: #endif
298:     return status;
299: }
300: 

Аналогичная ситуация приведена ниже, где функция постоянно пытается прочитать ‘cfg-> atcahid.packetsize + 1)’, а затем скопировать в ‘rxdata’ в 365 строке без выполнения проверки границ.

File: secure_elements/lib/hal/hal_win_kit_hid.c
333:     while (continue_read == true)
334:     {
335:         result = ReadFile(pHid->kits[hidid].read_handle, buffer, (cfg->atcahid.packetsize + 1), &bytes_read, NULL);
336:         if (result == false)
337:         {
338:             return ATCA_RX_FAIL;
339:         }
340:         // Find the location of the '\n' character in read buffer
341:         // todo: generalize this read...  it only applies if there is an ascii protocol with an <eom> of \n and if the <eom> exists
342:         location = strchr((char*)&buffer[1], '\n');
343:        if (location == NULL)
344:         {
345:             // Copy all of the bytes
346:             bytes_to_cpy = bytes_read;
347:             // An extra byte is prepended to HID communication
348:             size_adjust = 1;
349:         }
350:         else
351:         {
352:             // Copy only the bytes remaining in the read buffer to the <eom>
353:             bytes_to_cpy = (uint8_t)(location - (char*)buffer);
354:             size_adjust = 0;
355:             // The response has been received, stop receiving more data
356:             continue_read = false;
357:         }
358:         // Protect rxdata from overwriting, this will have the result of truncating the returned bytes
359:         // Remaining space in rxdata
360:         //bytes_remain = (*rxsize - total_bytes);
361:         // Use the minimum between number of bytes read and remaining space
362:         //bytes_to_cpy = min(bytes_remain, bytes_to_cpy);
363: 
364:         // Copy the received data
365:         memcpy(&rxdata[total_bytes], &buffer[1], bytes_to_cpy);
366:         total_bytes += bytes_to_cpy - size_adjust;
367:     }

Infineon - www.infineon.com

Уязвимость

Повреждение памяти через ‘DtlsRL_Record_ProcessRecord’

Уязвимые продукты

Optiga Trust X DTLS: https://github.com/Infineon/optiga-trust-x/tree/master/optiga/dtls

Бэкграунд

Infineon Website

Влияние

Локальный злоумышленник, способный вмешаться в физическую I2C шину между хостом и микросхемой безопасности Optiga Trust X, может отправить искаженную DTLS запись, которая повреждает память кучи на хосте, потенциально обеспечивая выполнение локального кода.

Технические подробности

Во время установления DTLS рукопожатия поле длины фрагмента DTLS записи не очищается должным образом.

File: optiga_trust_x/optiga/dtls/DtlsRecordLayer.c
159:         wRecvFragLen = Utility_GetUint16(PpsBlobRecord->prgbStream + OFFSET_RL_FRAG_LENGTH);

‘WRecvFragLen’ - 16-битное значение, управляемое злоумышленником, используется в последующей логике обработки записи без очистки. В результате можно вызвать повреждение памяти в 235 строке.

File: optiga_trust_x/optiga/dtls/DtlsRecordLayer.c
233:             PpsRecData->bContentType = bContentType;
234:             //No Decryption, just copy the data
235:             Utility_Memmove(PpsRecData->psBlobInOutMsg->prgbStream, \
236:                    PpsBlobRecord->prgbStream + OFFSET_RL_FRAGMENT, \
237:                     wRecvFragLen);
238:             PpsRecData->psBlobInOutMsg->wLen = wRecvFragLen;
239:             i4Status = OCP_RL_OK;

‘PpsRecData-> psBlobInOutMsg-> prgbStream’ указывает на динамически выделяемый буфер, размер которого фиксирован (TLBUFFER_SIZE 1500 байтов).

File: optiga_trust_x/optiga/dtls/DtlsHandshakeProtocol.c 
1361:     sMessageLayer.sTLMsg.prgbStream = (uint8_t*)OCP_MALLOC(TLBUFFER_SIZE);

Уязвимый путь выглядит следующим образом:

  1. DtlsHS_Handshake
  2. DtlsHS_ReceiveFlightMessage
  3. DtlsRL_Recv
  4. DtlsCheckReplay
  5. DtlsRL_CallBack_ValidateRec
  6. DtlsRL_Record_ProcessRecord

Уязвимые продукты

Optiga Trust X: https://github.com/Infineon/optiga-trust-x/

Влияние

Локальный злоумышленник, способный вмешаться в физическую I2C шину между хостом и микросхемой безопасности Optiga Trust X, может отправить искаженный ответ ‘CmdLib_CalcHash’, который повреждает память в хосте, в результате потенциально может привести к выполнению локального кода.

Технические подробности

В функции ‘CmdLib_CalcHash’ потенциально ненадежное поле длины используется без очистки.

Длина тега напрямую получается из буфера ответа в 1757 строке, которая может содержать значение больше, чем PpsCalcHash-> sOutHash.wBufferLength. Затем в строке 1758 эта длина используется для выполнения операции memcpy, которая запускает повреждение памяти. Та же проблема относится к 1772 и 1773 строкам.

File: optiga_trust_x/optiga/cmd/CommandLib.c
1748:         if((TAG_HASH_OUTPUT == (*(sApduData.prgbRespBuffer + LEN_APDUHEADER))) && (sApduData.wResponseLength != 0))
1749:         {
1750:             //Length check for sOutData
1751:             if((psHashinfo->bHashLen) > PpsCalcHash->sOutHash.wBufferLength)
1752:             {
1753:                 i4Status = (int32_t)CMD_LIB_INSUFFICIENT_MEMORY;
1754:                 break;
1755:             }
1756: 
1757:             PpsCalcHash->sOutHash.wRespLength = Utility_GetUint16(sApduData.prgbRespBuffer + LEN_APDUHEADER + BYTES_SEQ);
1758:             OCP_MEMCPY(PpsCalcHash->sOutHash.prgbBuffer, (sApduData.prgbRespBuffer + CALC_HASH_FIXED_OVERHEAD_SIZE), PpsCalcHash->sOutHash.wRespLength);
1759:         }
1760: 
1761:         //Validate the Context buffer size if the 0x06 context data tag is there in response and 
1762:        //copy the context data to pbContextData buffer
1763:         if((TAG_CONTEXT_OUTPUT == (*(sApduData.prgbRespBuffer + LEN_APDUHEADER))) && (sApduData.wResponseLength != 0))
1764:         {
1765:             //Length check for Context Data
1766:             if((psHashinfo->wHashCntx) > PpsCalcHash->sContextInfo.dwContextLen)
1767:             {
1768:                 i4Status = (int32_t)CMD_LIB_INSUFFICIENT_MEMORY;
1769:                 break;
1770:             }
1771: 
1772:             PpsCalcHash->sContextInfo.dwContextLen = Utility_GetUint16(sApduData.prgbRespBuffer + LEN_APDUHEADER + BYTES_SEQ);
1773:             OCP_MEMCPY(PpsCalcHash->sContextInfo.pbContextData, (sApduData.prgbRespBuffer + CALC_HASH_FIXED_OVERHEAD_SIZE), PpsCalcHash->sContextInfo.dwContextLen);

Уязвимость

Множественные проблемы с повреждением памяти в ‘Optiga_cmd.c’

Уязвимые продукты

Optiga Trust M: https://github.com/Infineon/optiga-trust-m/

Бэкграунд

Влияние

Локальный злоумышленник, способный вмешаться в физическую I2C шину между хостом и микросхемой безопасности Optiga Trust M, может отправить искаженный ответ, который повреждает память в хосте, что потенциально может привести к выполнению произвольного кода.

Технические подробности

В функции optiga_cmd_gen_keypair_handler потенциально ненадежное поле длины используется без очистки.

Длина тега закрытого ключа получается непосредственно из буфера ответа в 2576строке, который может содержать значение больше, чем буфер, указанный параметром ‘p_optiga_ecc_gen_keypair-> private_key’. Затем в 2579 строке эта длина используется для выполнения операции memcpy, которая вызовет повреждение памяти.

File: infineon/optiga_cmd.c
2573:                 else if (CMD_GEN_KEY_PAIR_PRIVATE_KEY_TAG == me->p_optiga->optiga_comms_buffer[OPTIGA_CMD_APDU_INDATA_OFFSET +
2574:                                                              header_offset])
2575:                 {
2576:                     optiga_common_get_uint16(&me->p_optiga->optiga_comms_buffer[OPTIGA_CMD_APDU_INDATA_OFFSET + header_offset
2577:                                              + OPTIGA_CMD_NO_OF_BYTES_IN_TAG], &private_key_length);
2578: 
2579:                     pal_os_memcpy(p_optiga_ecc_gen_keypair->private_key,
2580:                                   &me->p_optiga->optiga_comms_buffer[OPTIGA_CMD_APDU_INDATA_OFFSET + header_offset +
2581:                                   OPTIGA_CMD_UINT16_SIZE_IN_BYTES+ OPTIGA_CMD_NO_OF_BYTES_IN_TAG], private_key_length);
2582:                     header_offset +=  OPTIGA_CMD_UINT16_SIZE_IN_BYTES+ OPTIGA_CMD_NO_OF_BYTES_IN_TAG + private_key_length;
2583:                     return_status = OPTIGA_LIB_SUCCESS;

Та же проблема применяется к 3068 и 3072 строкам при обработке ответа ‘Calc_Hash’ в функции ‘optiga_cmd_calc_hash_handler’.

File:  infineon/optiga_cmd.c
3052:         case OPTIGA_CMD_EXEC_PROCESS_RESPONSE:
3053:         {
3054:             OPTIGA_CMD_LOG_MESSAGE("Processing response for calculate hash command...");
3055:             // check if the write was successful
3056:             if (OPTIGA_CMD_APDU_FAILURE == me->p_optiga->optiga_comms_buffer[OPTIGA_COMMS_DATA_OFFSET])
3057:             {
3058:                 OPTIGA_CMD_LOG_MESSAGE("Error in processing calculate hash response...");
3059:                 SET_DEV_ERROR_NOTIFICATION(OPTIGA_CMD_EXIT_HANDLER_CALL);
3060:                 break;
3061:             }
3062:             if (OPTIGA_CRYPT_HASH_FINAL == p_optiga_calc_hash->hash_sequence)
3063:             {
3064:                 if (OPTIGA_CRYPT_HASH_DIGEST_OUT != me->p_optiga->optiga_comms_buffer[OPTIGA_CMD_APDU_INDATA_OFFSET])
3065:                 {
3066:                    break;
3067:                 }
3068:                 optiga_common_get_uint16(&me->p_optiga->optiga_comms_buffer[OPTIGA_CMD_APDU_INDATA_OFFSET +
3069:                                          OPTIGA_CMD_NO_OF_BYTES_IN_TAG], &out_data_size);
3070: 
3071:                 pal_os_memcpy(p_optiga_calc_hash->p_out_digest,
3072:                               &me->p_optiga->optiga_comms_buffer[OPTIGA_CMD_APDU_INDATA_OFFSET + OPTIGA_CMD_UINT16_SIZE_IN_BYTES +
3073:                               OPTIGA_CMD_NO_OF_BYTES_IN_TAG], out_data_size);
3074:             }

Большой брат следит за вами, но мы знаем, как остановить его

Подпишитесь на наш канал!