To improve development efficiency and reduce project costs, IoT device Software Development Kits (IoT SDKs) are widely used as it provides the IoT device developers with devices access to the cloud quickly and two-way communication with the cloud. However, the security implications of such SDKs are seldom studied systematically. In this paper, we evaluate the security of IoT devices from a novel perspective of IoT SDK inspecting. Instead of checking the released firmware, our security evaluation focuses on the IoT SDKs with source code and well-documented guides. We summarized three typical security hazards, code defects, incomplete implementations, and unsafe options/configurations, that an IoT SDK often contains, and presented hazard detection techniques correspondingly. With an evaluation of eight real-world IoT device SDKs, our study brings to the pervasiveness of security risks in these SDKs, resulting in manufacturing vulnerable IoT devices. We additionally reviewed nine developers on their opinions of our security evaluation. The feedback showed our evaluation received a very positive response from experienced IoT developers.
We have implemented a prototype of paper. Our target SDKs is shown below.
#1: aliyun-linkkit-c-sdk
version: 3.2.0
total func number: 3,586
lines of code: 6,120,420
third-party components: ARMmbed mbedtls, DaveGamble cJSON, nghttp2, eclipse paho.mqtt.embedded-c
#2: aws-iot-device-sdk-embedded-c
version: 202103.00
total func number: 414
lines of code: 441,379
third-party components: FreeRTOS coreMQTT, FreeRTOS coreHTTP, FreeRTOS coreJSON, FreeRTOS corePKCS11, FreeRTOS backoffAlgorithm, AWS IoT Device Shadow, AWS IoT Jobs, AWS IoT Device Defender, AWS IoT Over-the-air Update, ThrowTheSwitch CMock, eclipse mosquitto
#3: azure-iot-sdk-c
version: LTS_01_2021_Ref01
total func number: 3,891
lines of code: 7,460,183
third-party components: Azure azure-c-shared-utility, Azure azure-umqtt-c, Azure azure-uamqp-c, Azure azure-utpm-c, Azure azure-uhttp-c, Azure umock-c, Azure azure-macro-utils-c, Azure azure-c-testrunnerswitcher, Azure azure-ctest, Krzysztof Parson, Microsoft RIoT
#4: baidu-iot-sdk-c
version: 1.1.19
total func number: 1,798
lines of code: 2,164,557
third-party components: Azure azure-c-shared-utility, Azure azure-uamqp-c, Azure azure-umqtt-c, Azure azure-uhttp-c, Azure umock-c, Azure ctest, kgabis parson
#5: googlecloudplatform-iot-device-sdk-embedded-c
version: 1.0.3
total func number: 980
lines of code: 876,336
third-party components: protobuf-c, nmathewson tinytest, ARMmbed mbedtls, Google cmocka, Google googletest, MicrochipTech cryptoauthlib
#6: huaweicloud-iot-device-sdk-c
version: 0.9.0
total func number: 173
lines of code: 309,259
third-party components: DaveGamble cJSON, Openssl, Eclispse Paho-mqtt-c, Madler zlib
#7: qcloud-iot-explorer-sdk-embedded-c
version: 3.1.7
total func number: 2,200
lines of code: 2,968,114
third-party components: ARMmbed mbedtls
#8: qcloud-iot-sdk-embedded-c
version: 3.2.3
total func number: 1,904
lines of code: 2,547,859
third-party components: ARMmbed mbedtls, DaveGamble cJSON
We utilized Clang Static Analyzer-based function classification to identify memory management functions. The identification results are shown as following.
More details about memory management functions identified by our tool can be found in here, including customized and normal memory functions.
SDK | Alloc Functions | Free Functions | ||
---|---|---|---|---|
Normal | Customized | Normal | Customized | |
#1: Aliyun | 20 | 5 | 11 | 0 |
#2: AWS | 64 | 1 | 15 | 21 |
#3: Azure | 126 | 7 | 58 | 177 |
#4: Baidu | 45 | 0 | 17 | 47 |
#5: GoogleCloud | 43 | 4 | 29 | 24 |
#6: Huawei | 43 | 3 | 1 | 0 |
#7: QcloudE | 20 | 1 | 25 | 21 |
#8: QcloudH | 21 | 1 | 26 | 21 |
Memory safety bugs contain improper use of pointers, insecure string functions and uninitialized variables. The results are shown as following.
SDK | Improper use of pointers (IUP) | Insecure string functions (ISF) | Uninitialized variables (UV) | ||||
---|---|---|---|---|---|---|---|
strcpy | strcmp | strlen | strcat | sum | |||
#1: Aliyun | 4 | 39 | 46 | 1408 | 3 | 1,496 | 12 |
#2: AWS | 0 | 0 | 2 | 62 | 0 | 64 | 0 |
#3: Azure | 23 | 128 | 354 | 420 | 1 | 903 | 6 |
#4: Baidu | 14 | 0 | 4 | 16 | 0 | 20 | 0 |
#5: GoogleCloud | 3 | 0 | 7 | 49 | 0 | 56 | 0 |
#6: Huawei | 1 | 1 | 9 | 21 | 11 | 42 | 0 |
#7: QcloudE | 11 | 13 | 42 | 257 | 6 | 318 | 13 |
#8: QcloudH | 4 | 8 | 20 | 214 | 1 | 243 | 13 |
More details about memory safety bugs identified by our clang-based analyzer tool and Cppcheck can be found in here.
Note that the data in the table is the result of manual verification.
Five common cases of crypto misuses include:
● Constant encryption keys
● Insecure encryption mode
● Non-random Initialized Vector (IV)
● Static Seeds to generate random numbers
● Insecure hash functions
● The detailed results are shown as following.
SDK | Details |
---|---|
#1: Aliyun | 1. Using constant encryption keys: Aliyun SDK uses the product secret as the hmac key during dynamic registeration and uses device secret as the hmac key during MQTT password generation, where the product secret and device secret are fixed for one device. |
2. Using non-random IV: Aliyun SDK uses a fixed strings "543yhjy97ae7fyfg" as IV in AES-CBC algorithm during CoAP communication. | |
3. Using insecure hash functions: Aliyun SDK uses MD5 insecure hash algorithm to generate file checksum during OTA update. | |
#2: AWS | - |
#3: Azure | 1. Using constant encryption keys: Azure SDK utilizes the fixed enrollment group key to generate Shared Access Signature (SAS) tokens in Device Provisioning Service. |
2. Using static seeds to generate random numbers: Azure SDK directly invoke rand() without srand() to generate random numbers, in which the seed is set to 1. | |
#4: Baidu | 1. Using static seeds to generate random numbers: Baidu SDK directly invoke rand() without srand() to generate random numbers, in which the seed is set to 1. |
2. Using insecure hash functions: Baidu SDK uses MD5 insecure hash algorithm by default to generate MQTT credential (i.e., password). | |
#5: GoogleCloud | - |
#6: Huawei | - |
#7: QcloudE | 1. Using constant encryption keys: QcloudE SDK uses the product secret as the hmac key during dynamic registeration and uses device secret as the hmac key during MQTT password generation, where the product secret and device secret are fixed for one device. |
2. Using non-random IV: QcloudE SDK uses a fixed strings with all zero as IV in AES-CBC algorithm during CoAP communication. | |
3. Using insecure hash functions: QcloudE SDK uses MD5 insecure hash algorithm to generate file checksum during OTA update. | |
#8: QcloudH | 1. Using constant encryption keys: QcloudH SDK uses the product secret as the hmac key during dynamic registeration and uses device secret as the hmac key during MQTT password generation, where the product secret and device secret are fixed for one device. |
2. Using non-random IV: QcloudH SDK uses a fixed strings with all zero as IV in AES-CBC algorithm during CoAP communication. | |
3. Using insecure hash functions: QcloudH SDK uses MD5 insecure hash algorithm to generate file checksum during OTA update. |
IoT SDKs tend to leverage open-source third-party libraries to implement common functions such as data compression and message parsing. m libraries. If a vulnerable third-party library is used, the attacker could exploit such component to obtain privileged permissions.
The detailed results are shown as following.
#1: Aliyun
Integrated third-party components: ARMmbed@@mbedtls mbedtls-2.5.0, DaveGamble@@cJSON v1.5.3, eclipse@@paho.mqtt.embedded-c v1.0.0, nghttp2@@nghttp2 v1.32.0, mbed@@infra_httpc, DavidYoung@@ieee80211_radiotap
Vulnerable components:
● ARMmbed@@mbedtls mbedtls-2.5.0
○ CVE: CVE-2021-26529, CVE-2020-36426, CVE-2020-36422, CVE-2020-16150, CVE-2018-16528, CVE-2018-1000520, CVE-2016-3739
● DaveGamble@@cJSON v1.5.3
○ CVE: CVE-2019-11835, CVE-2019-11834, CVE-2019-1010239, CVE-2018-1000217, CVE-2018-1000216, CVE-2018-1000215, CVE-2016-4303
● eclipse@@paho.mqtt.embedded-c v1.0.0
○ CVE: CVE-2019-11777
● nghttp2@@nghttp2 v1.32.0
○ CVE: CVE-2020-11080
#2: AWS
Integrated third-party components: -
#3: Azure
Integrated third-party components: Azure@@azure-c-shared-utility 1.1.10, Azure@@azure-umqtt-c 2020-01-22, Azure@@azure-utpm-c 2020-12-09, Azure@@azure-uhttp-c 2017-09-25
Vulnerable components: -
#4: Baidu
Integrated third-party components: Azure@@azure-c-shared-utility 2016-08-26, Azure@@azure-uamqp-c 2016-08-16, Azure@@azure-umqtt-c 2016-02-08, Azure@@azure-uhttp-c 2017-09-25, Azure@@umock-c 2017-01-27, Azure@@ctest 2017-01-27
Vulnerable components: -
#5: GoogleCloud
Integrated third-party components: protobuf-c@@protobuf-c v1.1.1, nmathewson@@tinytest, ARM@@mbedtls 2.12.0, Google@@cmocka 1.0.1
Vulnerable components:
● ARMmbed@@mbedtls mbedtls-2.12.0
○ CVE: CVE-2021-26529, CVE-2020-36426, CVE-2020-36422, CVE-2020-16150
● protobuf-c@@protobuf-c v1.1.1
○ CVE: CVE-2015-5237
#6: Huawei
Integrated third-party components: DaveGamble@@cJSON v1.7.11
Vulnerable components:
● DaveGamble@@cJSON v1.7.11
#7: QcloudE
Integrated third-party components: ARMmbed@@mbedtls mbedtls-2.4.0
Vulnerable components:
● ARMmbed@@mbedtls mbedtls-2.4.0
○ CVE: CVE-2021-26529, CVE-2020-36426, CVE-2020-36422, CVE-2020-16150, CVE-2018-16528, CVE-2018-1000520, CVE-2016-3739
#8: QcloudH
Integrated third-party components: ARMmbed@@mbedtls mbedtls-2.4.0, DaveGamble@@cJSON v1.7.14
Vulnerable components:
● ARMmbed@@mbedtls mbedtls-2.4.0
○ CVE: CVE-2021-26529, CVE-2020-36426, CVE-2020-36422, CVE-2020-16150, CVE-2018-16528, CVE-2018-1000520, CVE-2016-3739
A partially implemented function refers to a function that is expected to execute certain operations but is not actually implemented. For instance, if a checksum function is implemented to return a fixed value for all input data,we regard such a function as a partially implemente done. Using partially implemented functions would fail to guarantee normal program behaviors, and hence lead to unexpected results or security risks.
The detailed results are as follows.
#1: Aliyun
partially implemented functions: 52
example: CoAPNetwork.c
#ifdef COAP_DTLS_SUPPORT
/* TODO: */
if (COAP_NETWORK_DTLS == network->type) {
} else {
}
#endif
example: cJSON.c
cJSON_ArrayForEach(a_element, a) {
/* TODO This has O(n^2) runtime, which is horrible! */
cJSON *b_element = get_object_item(b, a_element->string, case_sensitive);
if (b_element == NULL) {
return false;
}
#2: AWS
partially implemented functions: -
#3: Azure
partially implemented functions: 13
example: iothubtransport_mqtt_common.c
static int buildConfigForUsernameStep2IfNeeded(PMQTTTRANSPORT_HANDLE_DATA transport_data)
{
...
const char* modelId = transport_data->transport_callbacks.get_model_id_cb(transport_data->transport_ctx);
// TODO: The preview API version in SDK is only scoped to scenarios that require the modelId to be set.
// https://github.com/Azure/azure-iot-sdk-c/issues/1547 tracks removing this once non-preview API versions support modelId.
const char* apiVersion = IOTHUB_API_VERSION;
...
}
#4: Baidu
partially implemented functions: 3
example: iotcore_mqtt_client.c.c
if (iotcore_client->xio_transport == NULL)
{
LogError("failed to create connection with server");
// TODO: add code to handle release data for IOTCORE_MQTT_CLIENT_HANDLE
_result = IOTCORE_ERR_ERROR;
}
// TODO: to support sha256 algrithm
mqtt_param->passwd = (char*)malloc(33); // MD5 passwd len has 32 characters
#5: GoogleCloud
partially implemented functions: 15
example: iotc_resource_manager.h
/**
* @brief iotc_resource_manager_open begins the open sequence
*
* @todo would be nice to think about a timeout for each function related to
* long-term resource reading/writing related tasks.
*/
if (IOTC_STATE_OK != local_state) {
//@TODO add proper implementation and error handling
iotc_debug_logger("error while canceling task timeout");
}
#6: Huawei
partially implemented functions: -
#7: QcloudE
partially implemented functions: 2
example: mqtt_client_net.c
// TODO: how to implement
/**
* @brief Check if TLS connection is valid
*
* @param pNetwork
* @return
*/
int qcloud_iot_mqtt_tls_is_connected(Network *pNetwork)
{
return 1;
}
#8: QcloudH
partially implemented functions: 2
example: log_upload.c
static int _post_one_http_to_server(char *post_buf, size_t post_size)
{
...
#ifdef LOG_CHECK_HTTP_RET_CODE
/* TODO: handle recv data from log server */
#define HTTP_RET_JSON_LENGTH 256
#define HTTP_WAIT_RET_TIMEOUT_MS 1000
char buf[HTTP_RET_JSON_LENGTH] = {0};
sg_http_c->http_data.response_buf = buf;
sg_http_c->http_data.response_buf_len = sizeof(buf);
...
}
Some SDKs ask developers to define important device parameters (e.g.,device ID, device name, device key, product key) for each device. However, they do not regulate how those parameters should be securely defined
In the following, we present the undefined device parameters of each SDK and check whether they are regulated.
Unfortunately, except for AWS and Azure, six SDKs did not regulate how developers should define them (H2.2).
#1: Aliyun
undefined device parameters: ProductKey, ProductSecret, DeviceName, DeviceSecret
#2: AWS
undefined device parameters: ThingsName
requirement: https://docs.aws.amazon.com/iot/latest/developerguide/thing-registry.html
● Should not use personally identifiable information in your thing name. The thing name can appear in unencrypted communications and reports.
#3: Azure
undefined device parameters: HubName, deviceName, deviceId, deviceKey
requirement: https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-create-through-portal
● Since IoT hub will be publicly discoverable as a DNS endpoint, be sure to avoid entering any sensitive or personally identifiable information when you name it.
● The device ID may be visible in the logs collected for customer support and troubleshooting, so make sure to avoid any sensitive information while naming it.
#4: Baidu
undefined device parameters: name, password
#5: GoogleCloud
undefined device parameters: RegistryID, deviceID
#6: Huawei
undefined device parameters: productID, deviceID, key...
#7: QcloudE
undefined device parameters: ProductId, ProductSecret, DeviceName, DeviceSecret
#8: QcloudH
undefined device parameters: ProductId, ProductSecret, DeviceName, DeviceSecret
We describe the weak optional authentication schemes for each SDK that may lead to security threats.
SDK | Authentication with fixed identifiers | Authentication with non-unique credentials |
---|---|---|
#1: Aliyun | device key based registration | dynamic information based registeration |
#2: AWS | - | - |
#3: Azure | device key based registration | dynamic information based registeration |
#4: Baidu | device key based registration | - |
#5: GoogleCloud | - | - |
#6: Huawei | device key based registration | - |
#7: QcloudE | device key based registration | dynamic information based registeration |
#8: QcloudH | device key based registration | dynamic information based registeration |
We describe the optional insecure protocols for data transmissions of each SDK that may lead to security threats.
SDK | Transmission in plaintext | Transmission with obsolete crypto protocols | Transmission without anti-replay mechanism |
---|---|---|---|
#1: Aliyun | MQTT over TCP, CoAP over UDP, HTTP | TLS 1.0/1.1 | Insecure anti-replay mechanisms implementation: fixed random "8Ygb7ULYh53B6OA" |
#2: AWS | - | - | - |
#3: Azure | - | TLS 1.0/1.1 | - |
#4: Baidu | MQTT over TCP, CoAP over UDP, HTTP | SSL, TLS1.0/1.1 | No anti-replay mechanisms |
#5: GoogleCloud | HTTP | - | - |
#6: Huawei | MQTT over TCP, LwM2M/CoAP over UDP, HTTP | SSL, TLS 1.0/1.1 | Optional anti-replay mechanisms: provide "signType" to determine whether checking timestamps |
#7: QcloudE | MQTT over TCP, CoAP over UDP, HTTP | TLS 1.0/1.1 | No anti-replay mechanisms |
#8: QcloudH | MQTT over TCP, CoAP over UDP, HTTP | TLS 1.0/1.1 | No anti-replay mechanisms |
Many SDKs support different third-party components with similarity functionalities. Unfortunately, an IoT SDK usually do not restrict and check the version of the adopted third-party components. If the developer chooses a (potentially) vulnerable or obsolete component rather than a secure one, it inevitably weakens the security level of the further built system.
Hence, we present the optional third-party components of each SDK that may lead to potential security hazards.
#1: Aliyun
Optional third-party components:-
#2: AWS
Optional third-party components:
● FreeRTOS coreMQTT
● FreeRTOS coreHTTP
● FreeRTOS coreJSON
● FreeRTOS corePKCS11
● FreeRTOS backoffAlgorithm
● AWS IoT Device Shadow
● AWS IoT Jobs
● AWS IoT Device Defender
● AWS IoT Over-the-air Update
● ThrowTheSwitch CMock
● eclipse mosquitto
#3: Azure
Optional third-party components:
● Azure azure-c-shared-utility
● Azure azure-umqtt-c
● Azure azure-uamqp-c
● Azure azure-uhttp-c
● Azure azure-utpm-c
● Azure umock-c
● Azure azure-macro-utils-c
● Azure azure-c-testrunnerswitcher
● Azure azure-ctest
● Krzysztof Parson
● Microsoft RIoT
#4: Baidu
Optional third-party components:
● kgabis parson
● Azure azure-umqtt-c
#5: GoogleCloud
Optional third-party components:
● google googletest
● MicrochipTech cryptoauthlib
#6: Huawei
Optional third-party components:
● Openssl/wolfssl
● Eclispse Paho-mqtt-c
● Madler zlib
#7: QcloudE
Optional third-party components:-
#8: QcloudH
Optional third-party components:-