Security analysis of Cloud IoT services
Below is my analysis of Google’s “Cloud IoT Core” and Amazon’s “AWS IoT Core”, from a security perspective.
The “Core” service from both of these providers is very similar, and consists of a message broker that supports a publish/subscribe model. In both cases, it is possible for an external host to subscribe to messages, as well as to have messages sent to various compute resources within the respective provider’s cloud offerings. As the internals of these provider’s implementations are not available, this document makes no attempt to analyze the security within the provider’s network, but to evaluate the security concerning the communication between the individual devices and the service.
Both providers offer the MQTT protocol, as well as provide a few other gateways to make accessing the information via one or more web protocols. The web protocols can be useful to make data available within a webpage, as well as to support situations where a firewall may block the standard MQTT port used.
Google Cloud IoT Core
Cloud IoT Core is a fully managed service that allows you to easily and securely connect, manage, and ingest data from millions of globally dispersed devices.
There are two ways for devices to connect to the Cloud IoT Core service. There is an HTTP(s) (1.1 only) interface, and there is an MQTT interface that is required to be encoded with TLS. There is a summary of these two protocols in the provider’s documentation.
In both cases, individual devices must authenticate themselves to the service using a public-key-based authentication method known as JSON Web Tokens (JWT). Details are in the documentation.
The HTTP protocol will only be briefly considered here. As it does not support HTTPS, communications are not private, and there is no provisioning to prevent tampering with the messages. Although the client must send an authentication token to verify its identity, the authentication tokens are sent in plain text, and someone observing the traffic could easily reuse the token for the lifetime of the token (which can be for as long as an hour). In addition, the device itself has no way to know the identity of the party it is talking to.
We recommend against using HTTP to communicate with Google’s Cloud IoT Core.
Google’s security device-security page also recommends against using HTTP.
The security of HTTPS is very similar to MQTT/TLS below. Using HTTPS limits some of the functionality of the system (such as subscribing), since the connections are short lived, but may be useful in some situations, especially for testing, and possibly situations where there is a firewall that blocks MQTT.
The MQTT protocol is required to be sent over a TLS 1.2 connection. Their service server uses the standard root certificate authority model to authenticate the server to the client. This model seems to be as secure as TLS connections are.
The protocol requires client devices to identify themselves with the server using the same JSON Web Tokens (JWTs, RFC 7519) mentioned above. Although the tokens can be reused for a period of time, an attacker will find them difficult to access, since they are never sent in plaintext. The tokens can only be valid for one hour, and the client must regenerate and resend new tokens at least this often to prevent the connection from being dropped.
- The client and server mutually authenticate over a secure channel.
- Their service enforces strong key sizes for the RSA or EC keys used for the client authentication signatures.
- They allow up to 3 active keys per device which allows the development of key rotation systems.
- As far as I can tell, the cloud server (mqtt.googleapis.com:8883) sends a certificate using RSA. Although the device can authenticate with an EC2, it still must have the RSA code in the TLS library to be able to establish the TLS connection. I was unable to configure mbed TLS to support both RSA and EC, which would restrict the devices to RSA signatures.
- Google’s doc say that all of the certificates in https://pki.google.com/roots.pem must be trusted. Even when encoded compactly, this list is still around 60Kb. I would recommend working with Google to create a smaller list, appropriate for a small-resource IoT device, so that a device with a smaller list won’t suddenly stop working.
- The need to refresh the JWT tokens at least once an hour means the device will need to perform an expensive cryptographic operation at least once an hour. For battery-powered devices, this could become significant.
- It is not specified how these private keys should be managed on the devices. The system essentially requires that every device be pre-provisioned with a private key, and the associated public key be registered with the cloud service. This is indeed more secure, and protocols that provide for in-field provisioning generally have significant security weaknesses. However, provisioning this way adds complexity to the device manufacturing, as well as to the deployment and later management. It would be possible to user a lower-security protocol for the initial device provisioning, balancing the risks of this against the costs of managing provisioning every device with an initial private key.
- Both server certificate verification and the generation of the JWTs require the device to have a reasonably accurate clock (within about 5 minutes). Google recommends using their public NTP server for the device to get time. There is a risk of this host being spoofed, which could cause clients to generate tokens valid in the future. This attack also requires the server to be compromised, since the client won’t send the token until it has authenticated the server.
The certificates sent from mqtt.googleapis.com are:
Certificate chain 0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=mqtt.googleapis.com i:/C=US/O=Google Trust Services/CN=Google Internet Authority G3 1 s:/C=US/O=Google Trust Services/CN=Google Internet Authority G3 i:/OU=GlobalSign Root CA - R2/O=GlobalSign/CN=GlobalSign
Overall, Google’s Cloud IoT Core service provides a good set of security features, and other than a few issues related to verifying the server key, and the EC keys not being particularly useful.
AWS IoT Core
The AWS IoT Core service bears many similarities to the Google offering. In addition to secure MQTT and HTTPS, Amazon supports WebSockets, which is probably more useful for web apps to be able to access the messages in the system.
These protocols all communicate over TLS, although Amazon states a specific root certificate that signs the server’s certificate. This will allow the service to be used by a device that only needs to store a single root cert.
However, AWS authenticates the clients differently than does Google’s service.
There are two ways to authenticate the client to the server. One is by using certificates based on public/private keypairs. AWS provides a service to generate certificates that are signed by their CA (although they provide no justification for doing this rather than just using self-signed certificates). These certificates must be registered with the AWS service, and the private key stored on each device. Provisioning issues are similar to the Google solution.
The primary differences to this solution, over Google’s solution:
- The authentication is done with certificates rather than just with a keypair. There is additional complexity involved in implementing this, although this may not be significant, as the client must support certificate validation of the server, anyway.
- The authentication is done at the TLS layer. The primary advantage here is that once a connection is established, the client does not need to keep regenerating tokens, and the connection will persist as long as the server and client allow it to.
The other method of authentication is using the AWS IAM service. In this scenario, the client and the server will be issued the same shared key, and the protocol uses HMAC to verify that both parties have the same key. The security model is similar to the private key with the certificate authentication above, with some minor logistical differences in how the keys must be managed (the keys are generated by AWS, and have to be generated and stored at device provisioning time).
AWS does provide an Apache 2.0 licensed client library (based on mbed TLS) that can be considered.
Overall, the two services are quite similar. There are some logistical benefits to the AWS solution, especially in regards to smaller devices (both in regards to the smaller root cert list, and to somewhat less security implications of the client not knowing the time reliably). Both of these could be supported with a largely similar codebase.