IoTHazard! Evaluating Security Risks of IoT Devices via Third-party SDK Inspection

1. Introduction

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.

2. Testing Objects Information

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

SDK Download Link

#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

SDK Download Link

#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

SDK Download Link

#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

SDK Download Link

#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

SDK Download Link

#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

SDK Download Link

#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

SDK Download Link

#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

SDK Download Link

3. Detailed Results

3.1 Type-I Hazard: Code Defects

H1.1: Memory Safety Bugs

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.

Memory Management Functions Identification Results
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.

Memory Safety Bugs Results
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.

H1.2: Crypto Misuses

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.

Crypto Misuses Results
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.
H1.3: Vulnerable Third-party Components

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

Security Issues

#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

3.2 Type-II Hazard: Incomplete Implementations

H2.1: Partially Implemented Functions

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);
                    ...
                }
            
        

H2.2: Undefined Device Parameters

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

3.3 Type-III Hazard: Unsafe Options/Configurations

H3.1: Weak Options for Authentication

We describe the weak optional authentication schemes for each SDK that may lead to security threats.

Weak Options for Authentication
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
H3.2: Insecure Protocols for Data Transmission

We describe the optional insecure protocols for data transmissions of each SDK that may lead to security threats.

Insecure Protocols for Data Transmission
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
H3.3: Potentially Vulnerable Third-party Components

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:-